ios - 有趣的内存错误 - NSMutableArray 被一致替换

标签 ios ipad nsmutablearray

在我的 iPad 应用程序中,我有以下功能:

+ (void)addDot:(Dot *)d {
    if(dots == nil)
        dots = [[NSMutableArray alloc] init];

    NSLog(@"before adding, dots = %@",dots);
    NSLog(@"adding dot %@",d);
    [dots addObject:d];
    NSLog(@"dots is now %@",dots);
}

请注意,打印点会导致 x,y 坐标由空格分隔。

每次主体点击屏幕时,都会绘制一个点,并调用此方法,从而添加一个点。请注意,dots 被定义为该函数所在类顶部的 static NSMutableArray *dots。发生了一些奇怪的事情。数组的每个元素都被替换。点击屏幕后,查看 NSLog 的输出,形成 2 个点:

before adding, dots = (
)
2012-02-13 23:58:48.159 MoreMost[520:707] adding dot 418.000000 548.000000
2012-02-13 23:58:48.161 MoreMost[520:707] dots is now (
    "418.000000 548.000000"
)
2012-02-13 23:58:48.748 MoreMost[520:707] before adding, dots = (
    "635.000000 410.000000"
)
2012-02-13 23:58:48.749 MoreMost[520:707] adding dot 635.000000 410.000000
2012-02-13 23:58:48.750 MoreMost[520:707] dots is now (
    "635.000000 410.000000",
    "635.000000 410.000000"
)

看看整个数组是如何被传入元素替换的?为什么是这样?不,该函数没有在代码中的其他任何地方被调用。它仅被调用一次,即每次用户点击屏幕在该位置绘制一个点时)。

请注意,程序中的其他任何地方都没有使用这些点。只有这个功能

这是Dot的实现:

#import "Dot.h"

@implementation Dot
@synthesize tapPosition;
CGRect frame;
UIColor *dotColor;

float radius = 20;

- (id)initWithTapPosition:(CGPoint)pt color:(UIColor *)col {
    if(self = [super init]) {
    tapPosition = pt;
    float topLeftX = pt.x - radius;
    float topLeftY = pt.y - radius;
    if(topLeftX + (radius*2) >= 1024)
        return nil;
    if(topLeftY + (radius*2) >= 728)
        return nil;
    if(topLeftY <= 0 || topLeftX <= 0)
        return nil;

    frame = CGRectMake(topLeftX, topLeftY, radius*2, radius*2);
    dotColor = col;
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
   Dot *dot = [[[self class] allocWithZone:zone] initWithTapPosition:tapPosition color:dotColor];
   return dot;
}

- (CGRect)getFrame {
    return frame;
}

- (UIColor *)getColor {
    return dotColor;
}

- (NSString *)description {
    return [NSString stringWithFormat:@"%f %f",frame.origin.x,frame.origin.y];
}

@end

和标题:

    #import <Foundation/Foundation.h>

@interface Dot : NSObject {
@public
    CGPoint tapPosition;
}

@property (nonatomic, assign) CGPoint tapPosition;

- (CGRect)getFrame;
- (id)initWithTapPosition:(CGPoint)pt color:(UIColor *)col;

- (UIColor *)getColor;
@end

最佳答案

移动

CGRect frame;
UIColor *dotColor;
CGPoint tapPosition;
float radius = 20;

@implementation@interface:

@interface Dot : NSObject
{
   CGRect frame;
   // etc.
}
...
@end

声明它们的方式使它们实际上成为“全局变量”,因此所有 Dot 实例将共享相同的值。将它们放入 @interface 中,使它们成为“实例变量”,这样每个点都可以有不同的值。

<小时/>

旧答案

请注意

[dots addObject:d];

仅添加点d引用。如果您稍后就地修改点,例如

d.x = 123;
d.y = 456;

那么数组中的那个也会看到同样的变化。

您需要添加一个副本,例如

[dots addObject:[d copy]];
// note: you need to implement -copyWithZone: with the <NSCopying> protocol

关于ios - 有趣的内存错误 - NSMutableArray 被一致替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9271940/

相关文章:

iphone - 我们如何在主类 Xib 中添加子类 Xib?

ios - xamarin iOS 中的后台线程在 3 分钟后自动结束

ios - 如何从 Parse.com 获取单个键的所有值

objective-c - NSString 和崩溃

ios - 在 NSMutableArray 的第 0 个索引处添加数据

iphone - 避免自动释放 NSMutablearray ..... iphone 应用程序

ios - Xcode - 将字体从 iPhone 缩放到 iPad 大小

javascript - 仅对所有 iPhone 和 IPADS 进行样式设置的 CSS 样式

iOS 9 iPad 分屏完成/完成通知

ios - CCSprite 不会将自己添加到 NSArray