got*_*tye 5 iphone allocation equals retain nsarray
我的代码越多,我就越迷失...所以我决定为我(以及其他人)创建一个完全专注于内存管理的主题,不要浪费时间理解obj-c基础...我会将其更新为问了新问题!
以下是一些例子:
// myArray is property (retain)
myArray = otherArray;
//myArray isn't a property
myArray = otherArray;
//myArray is a property (retain)
myArray = [[NSArray alloc] init];
//myArray isn't a property
myArray = [[NSArray alloc] init];
Run Code Online (Sandbox Code Playgroud)
---所以,如果我明白了......当你把self.myArray放到Xcode上时,你告诉Xcode使用getter或setter,但是当你做myArray时,你对一切负责,对吧?
[求助] UPDATE1:之间是否有区别:
//myArray is a property
myArray = otherArray; // it is only a reference, releasing otherArray will imply releasing myArray
self.myArray = otherArray; // otherArray is sent a retain message so releasing otherArray will still keep myArray in memory
Run Code Online (Sandbox Code Playgroud)
---是的,有区别(见上面的评论)
[已解决] UPDATE2: myArray是否等于零?
NSArray *myArray;
Run Code Online (Sandbox Code Playgroud)
--- Kubi:是的,它等于零.
[已解决]更新3:它是否计入2个保留?一个保留自己,一个保留来自alloc?这是内存泄漏吗?
self.myArray = [[NSArray alloc] init];
Run Code Online (Sandbox Code Playgroud)
--- Kubi:是的,这是内存泄漏!
[求助] UPDATE4:财产照顾一切?无需分配或发布?
self.myArray = [NSArray array];
Run Code Online (Sandbox Code Playgroud)
---我们在这里使用setter,以便正确保留数组
[求助]更新5:这两个块是一样的吗?
//myArray is a retained property
self.myArray = [NSArray array]; //retain
self.myArray = nil; //release and set to nil
myArray = [[NSArray alloc] initWithArray]; //retain
self.myArray = nil; //release and set to nil
Run Code Online (Sandbox Code Playgroud)
---库比:是的,他们是完全相同的
谢谢你的时间.
高堤耶.
首先,我假设您有一个叫做的属性myArray并且调用了一个iVar myArray?如果是这样,情况1,2是相同的,3,4是相同的.如果需要设置当前类的属性,则必须通过以下方法之一进行:
self.myArray = otherArray;
[self setMyArray:otherArray];
Run Code Online (Sandbox Code Playgroud)
该行myArray = otherArray只会设置iVar,而不是属性.
第二部分,你要问的是内存管理.第一步:阅读Apple的指南.这真的是需要阅读.不要担心,如果你不完全理解,每月阅读一次,它最终会结晶.
步骤二:请记住这个经验法则:如果alloc,copy,new,或retain一个对象,你是负责释放该对象,如果你不这样做,就会被泄露.
在所有其他情况下,您不负责释放对象,但它最终将被释放.如果你需要保留它,你需要retain它(当然,稍后发布它).
回到您的示例,在前两种情况下,如果您不保留myArray它,将在此代码块之后的某个时刻释放它.如果您稍后尝试发送该对象,则会收到错误消息.在后两种情况下,如果你不在myArray某个时候释放对象,它将被泄露.
更新1 非常大的区别.这两条线完全不同.关于点语法的重要一点是这两行是完全等价的:
self.myArray = otherArray;
[self setMyArray:otherArray];
Run Code Online (Sandbox Code Playgroud)
注意第二行是方法调用.从理论上讲,你可以在这种方法中放置任何你想要的东西.您可以设置myArray为nil,或将其设置为someOtherArray,或更新twitter或其他任何内容.
更新2 Yup,Obj-C中的指针初始化为nil.
完全更新3.如果myArray声明属性retain并且您正在使用默认合成器,则会导致内存泄漏.
更新5 也完全正确.
库比的答案很好.重读Apple的指南直到你理解它是非常强制性的.
与此同时,您可以通过采用我遵循的这些严格的实践来避免意外的内存错误.这些规定的输入比严格必要的更多,并且它们在运行时的效率可能比它们可能略低,但是遵循这些规则将始终保护您免受最常见的内存管理错误的影响.然后,随着您对内存管理的熟悉程度越来越高,您可能会选择偏离这些规则,尽管我仍然很少这样做.
为您创建的每个对象实例变量声明一个属性.将其声明为(非原子,保留),除非它是您的类不拥有的对象,如委托,它将创建循环引用.在这种情况下,将其声明为(非原子,assign)以避免泄漏该循环中的所有对象.
@property (nonatomic, retain) NSString *title;
@property (nonatomic, assign) id <WidgetDelegate> delegate;
Run Code Online (Sandbox Code Playgroud)即使对象实例变量仅供类私有使用,也要在.m文件顶部的类扩展中为其声明一个属性,以便合成的setter方法可以为您处理内存管理.
// Widget.m
@interface Widget()
@property (nonatomic, retain) NSString *privateState;
@end
@implementation Widget
@synthesize title, delegate, privateState;
// ...
@end
Run Code Online (Sandbox Code Playgroud)每次分配实例变量对象时,始终使用self在属性中设置它.
self.title = @"Title";Run Code Online (Sandbox Code Playgroud)在dealloc中,将每个对象属性设置为nil.如果您已遵循上述做法,则会同时正确释放您的实例变量并将其设置为nil以防止EXC_BAD_ACCESS.将dealloc设为您班级中的第一个方法,这样您就不会忘记任何属性.
- (void) dealloc {
self.title = nil;
self.delegate = nil;
self.privateState = nil;
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)对于您编写的每个自定义类,请确保它至少有一个类工厂方法,该方法使用相同的参数委托给init方法,并自动释放返回的对象.这几乎限制了对这些工厂方法的所有alloc和init调用,而不是将它们分散到整个代码中.
- (id)initWithTitle:(NSString *)theTitle delegate:(id )theDelegate {
if (self = [super init]) {
self.title = theTitle;
self.delegate = theDelegate;
self.privateState = @"start";
}
return self;
}
+ (id)widgetWithTitle:(NSString *)theTitle delegate:(id )theDelegate {
return [[[self alloc] initWithTitle:theTitle delegate:theDelegate] autorelease];
}
Run Code Online (Sandbox Code Playgroud)无论何时实例化对象,如果可能,始终通过工厂类方法执行此操作.这为您提供了一个自动释放的对象,因此除非您保留它,否则不必释放它.
self.widget = [Widget widgetWithTitle:@"My Widget" delegate:self];
Run Code Online (Sandbox Code Playgroud)当您需要实例化没有适当工厂类方法的对象时,请在同一行自动释放它,因此您不要忘记稍后再执行此操作.(例外:如果您在紧密循环中执行了数千次,则手动释放.)
self.containerView = [[[UIView alloc] initWithFrame:self.bounds] autorelease];
Run Code Online (Sandbox Code Playgroud)如果您要释放具有委托或类似属性的对象,该对象指向循环引用,请先将该属性设置为nil.如果对象超过其委托并尝试在委托被取消分配后调用该委托上的方法,则会阻止EXC_BAD_ACCESS.
- (void)dealloc {
self.widget.delegate = nil;
self.widget = nil;
self.containerView = nil;
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)许多有经验的开发人员成功管理内存,而不遵循所有这些做 如果您了解内存管理并且不会有与内存相关的错误,我当然鼓励您坚持使用适合您的内容.但是,如果您是iPhone内存管理新手,或者您的代码受到意外内存相关错误的困扰,我希望您发现这些实践与我一样有用.
| 归档时间: |
|
| 查看次数: |
1816 次 |
| 最近记录: |