• apple cocoa内存管理笔记


    下面的这种方式是不对的

     

    Instance you don’t own is sent release
    - (void)reset {
    NSNumber
    *zero = [NSNumber numberWithInteger:0];创建的是一个autorelease的对象
    [self setCount:zero];
    [zero release];
    //这里释放是危险的
    }

    When you add an object to a collection such as an array, dictionary, or set, the collection takes ownership of

    it.在集合中增加object,那么这个object的所有者就变成了集合了

     

     

    代码
    // ...
    for (i = 0; i < 10; i++) {
    NSNumber
    *convenienceNumber = [NSNumber numberWithInteger:i];
    [array addObject:convenienceNumber];
    }
    //这种情况不需要release

    NSMutableArray
    *array;
    NSUInteger i;
    // ...
    for (i = 0; i < 10; i++) {
    NSNumber
    *allocedNumber = [[NSNumber alloc] initWithInteger: i];
    [array addObject:allocedNumber];
    [allocedNumber release];
    }
    //这种情况需要,此处只是将retain的计数减1而已

    安全返回对象

    下面两种方式是正确的

    - (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
    return string;
    }
    
    - (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName,
    lastName] autorelease];
    return string;
    }
    
    相反,下面的方式是错误的
    - (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName,
    lastName] release];
    return string;
    }
    
    同样,下面的方式也是错的
    - (NSString *)fullName {
    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@", firstName,
    lastName];
    return string;
    }
    


    对象拷贝机制

    有两种实现拷贝协议的copyWithZone:方法的方式:

    • 使用alloc and init..
    • 使用 NSCopyObject
    看下面对象的定义

    @interface Product : NSObject <NSCopying>

    {

    NSString *productName;

    float price;

    id delegate;

    }

    @end

     

    拷贝后的内存位置图如下:

     



    • 假设从supercalass继承了NSCopying,但是父类没有实现NSCopying,那么你要实现的话必须拷贝super的实例,同样包括自己声明的变量。一般情况下安全的方式是使用alloc,

    init..., and set methods

    • 另外一方面,如果super类已经实现了NSCopying,并且在你的类中你声明了一些实例变量,那么你必须实现copyWithZone:
    • 如果类没有继承NSCopying的行为,那么实现copyWithZone: using alloc,init..., and set methods.下面是一个例子

    - (id)copyWithZone:(NSZone *)zone

    {

    Product *copy = [[[self class] allocWithZone: zone]

    initWithProductName:[self productName]

    price:[self price]];

    [copy setDelegate:[self delegate]];

    return copy;

    }

     

     

    有些继承了NSCopying behavior的类,但是他们的super类的实现可能使用了 NSCopyObject function. NSCopyObject creates an exact shallow copy of an object

    by copying instance variable values but not the data they point to. 举个例子, NSCell类采用如下的方式实现copyWithZone

     

    - (id)copyWithZone:(NSZone *)zone

    {

    NSCell *cellCopy = NSCopyObject(self, 0, zone);

    /* Assume that other initialization takes place here. */

    cellCopy->image = nil;

    [cellCopy setImage:[self image]];

    return cellCopy;

    }

    在上面的实现采用的是浅拷贝


    对可变长度的对象的拷贝实现 ,要继承NSMutableCopying


    Core Foundation Objects in Cocoa中的内存管理


    Core Foundation's memory allocation policy is that you need to release values returned by functions with “Copy” or “Create” in their name; you should not release values returned by functions that do not have “Copy” or “Create” in their name.


    举几个例子

    NSString *str = [[NSString alloc] initWithCharacters: ...]; ... [str release];

    is equivalent to

    CFStringRef str = CFStringCreateWithCharacters(...); ...

    CFRelease(str);

    and

    NSString *str = (NSString *)CFStringCreateWithCharacters(...); ...

    [str release];

    and

    NSString *str = (NSString *)CFStringCreateWithCharacters(...);

    ... [str autorelease];



    Memory Management of Nib Objects


    The File’s Owner of a nib file缺省要去释放NIB资源及顶层的对象

    NIB文件的全局拥有者是全局应用对象NSApp,但是当Cocoa应用终止时,nib中的顶层对象也没有自动获得dealloc消息,因为NSApp已经被析构了。换句话说,即使nib主文件中,你也不得不管理顶层对象的内存

    实际上也不用担心,mac已经有两个特征可以帮助你了

    1. NSWindow对象有一个isReleasedWhenClosed属性,设置为YES则关闭窗口对象时自动关闭相关对象
    2. nib文件的拥有者是一个NSWindowController对象,那么他会调用NSDocument来管理一个NSWindowController的实例,会自动释放他管理的窗口的

    所以现实情况就是虽然你要负责释放一个nib文件中的top-level对象,但是只要你的nib文件的owner是一个NSWindowController的实例,那么它会帮你释放的。如果你的一个对象加载了nib自身并且文件的拥有者并不是NSWindowController,那么你可以为nib中的对象定义outlets,这样你就可以在恰当的时候释放他们。如果你不想为每个对象都声明outlet,你也可以这样:

    NSNib类的instantiateNibWithOwner:topLevelObjects: 方法来获得nib文件中的所有顶层对象



    内存管理总之可以归结为:

    (1)你通过带alloc,new,copy的函数创建的对象,你拥有他

    (2)通过retain你可以获得拥有权

    (3)任何一个对象都可能有很多个owner

    (4)你拥有的对象你必须通过发送release或者是autorelease释放他们

    (5)你不能释放不是你拥有的对象

    (6)对set类型的赋值函数,你可以retain传入的对象,你也可以copy一份,看你自己的要求咯

    (7)在函数(void)dealloc中一定要释放你声明的instance变量呀

    (8)指针变量使用完了一定要设为nil

    (9)你要确定一个对象不被释放掉,你最好提前retain一下

    (10)在任何时候都不要直接调用dealloc


     

     

     



  • 相关阅读:
    串口通讯编程一日通2(Overlapped IO模型)
    串口通讯编程一日通1(整合资料)
    Overlapped I/O模型深入分析(转)
    JVM7、8详解及优化
    vmstat工具
    spring 每个jar的作用
    Linux查看内存使用情况
    mysql datetime与timestamp精确到毫秒的问题
    eclipse UTF-8
    java.security
  • 原文地址:https://www.cnblogs.com/wordadobe/p/1895487.html
Copyright © 2020-2023  润新知