• objective C 内存管理及属性方法具体解释


    oc为每一个对象提供一个内部计数器。这个计数器跟踪对象的引用计数,当对象被创建或拷贝时。引用计数为1。每次保持对象时,调用retain接口。引用计数加1。假设不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc

    当对象包括其它对象时,就得在dealloc中自己释放他们

    NSObject是IOS全部类的基类

    有两个基本函数。alloc和dealloc

    alloc相似于C++的new。dealloc相似于delete

    当对象的retaincount为0时。自己主动调用dealloc函数

    release仅仅是使retaincount-1。不是调用dealloc函数

    内存管理的原则:

    假设使用alloc。copy创建的对象。一定要release

    假设你retain一个对象,那么必需要release

    Song 类的实现

    #import <Foundation/Foundation.h>

    @interface Song : NSObject
    {
        NSString *_title;
        NSString *_artist;
        long int _duration;
    }
    @property (nonatomic,retain) NSString *title;
    @property (nonatomic,retain) NSString *artist;
    @property (nonatomic,assign) long int duration;
    -(Song*)initwithTitle:(NSString *)t AndArtist:(NSString *)art AndDuration:(long int)d;
    @end

    #import "Song.h"

    @implementation Song
    @synthesize title=_title;
    @synthesize artist=_artist;
    @synthesize duration=_duration;

    -(Song*)initwithTitle:(NSString *)t AndArtist:(NSString *)art AndDuration:(long)d
    {
        self=[super init];
        if(self)
        {
            self.title=t;
            self.artist=art;
            self.duration=d;
        }
        return self;
    }
    @end
    main函数code

    int main(int argc, const char * argv[])
    {

        Song *Song1=[[Song alloc] initwithTitle:@"what" AndArtist:@"hello" AndDuration:3];
        Song *Song2=[[Song alloc] initwithTitle:@"aaa" AndArtist:@"bbb" AndDuration:4];
        NSLog(@"Song1 retain count is %ld",[Song1 retainCount]);
        NSLog(@"Song2 retain count is %ld",[Song2 retainCount]);
        [Song1 retain];
        [Song2 retain];
        NSLog(@"Song1 retain count is %ld",[Song1 retainCount]);
        NSLog(@"Song2 retain count is %ld",[Song2 retainCount]);
        [Song1 release];
        [Song2 release];
        NSLog(@"Song1 retain count is %ld",[Song1 retainCount]);
        NSLog(@"Song2 retain count is %ld",[Song2 retainCount]);
        [Song1 release];
        [Song2 release];
        return 0;
    }

    the result:

    2013-05-07 14:44:55.170 Access[2891:303] Song1 retain count is 1
    2013-05-07 14:44:55.173 Access[2891:303] Song2 retain count is 1
    2013-05-07 14:44:55.173 Access[2891:303] Song1 retain count is 2
    2013-05-07 14:44:55.173 Access[2891:303] Song2 retain count is 2
    2013-05-07 14:44:55.174 Access[2891:303] Song1 retain count is 1
    2013-05-07 14:44:55.174 Access[2891:303] Song2 retain count is 1


    内存管理释放池提供了一个对象容器。每次对象发送autorelease时。对象的引用计数并不真正变化。而是内存释放池记录一条记录,记下该对象的要求,直到内存释放池发送retain或release时,当池在销毁之前通知池内全部元素,发送release消息减1。这部分代码必须放在:

    NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];

    和     [pool release]; 之间

    int main(int argc, const char * argv[])
    {
     
        NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
        NSArray *weeks1=[NSArray arrayWithObjects:@"monday",@"tuesday",@"thursday", nil];
        NSArray *weeks2=[[NSArray alloc ]initWithObjects:@"monday",@"tuesday",@"thursday", nil];
        //[weeks1 autorelease];
        [weeks1 release];
        [weeks2 release];
        //[weeks2 autorelease];
        
        NSLog(@"retain count is %ld",[weeks1 retainCount]);
        NSLog(@"retain count is %ld",[weeks2 retainCount]);
        [pool release];
          return 0;
    }

    属性简单介绍

    @property 和@synthesize 能够自己主动生成某个类成员变量的存取方法,

    语法 @property(參数) 类型 名字

    这里的參数分为三大类:

    读写属性:(readwrite/readonly) readwrite:这个属性是默认的,readonly:仅仅生成getter 不会有setter

    原子性(nonatomic)atomic ;是为了保证程序能够并发,避免同步问题

    内存管理:(assign/retain/copy) 

    assign:这个属性用来处理基础类型,比方int,float。假设你声明的类型就是基础类型,该属性能够不加

    对于assign而言。set函数和get函数例如以下所看到的:

    @property(nonatomic,assign)int val;

    -(int)val

    {

     return val;

    }

    (void)setVal:(int)newVal

    {

    val=newVal;

    }

    copy:自己主动生成该对象的克隆


    代码例如以下:

    @property (nonatomic,copy) NSString *title;

    -(NSString*)title
    {
        return title;
    }
    -(void)settitle:(NSString*)newtitile

    {

       //首先推断是否与旧对象一致,假设不一致进行赋值。 

    if(newTitle!=title)

    {

        [title release];
        title=[newtitile copy];

    }

    }



    retain:会自己主动retain对象。实现

    代码例如以下:

    @property (nonatomic,retain) NSString *title;

    -(NSString*)title
    {
        return title;
    }
    -(void)settitle:(NSString*)newtitile

    {

       //首先推断是否与旧对象一致。假设不一致进行赋值。

    //对于nil对象运行release,不会抛异常,假设不会nil,release正好释放旧的对象,这样就能够保证不会出现内存泄露

    //由于假设是一个对象的话。进行if内的代码会造成一个极端的情况:当此name的retain为1时,使此次的set操作让实例name提前释放。而达不到赋值目的。 

    if(newTitle!=title)

    {

        [title release];
        title=[newtitile retain];

    }

    }

    在对属性进行赋值时,会调用属性的set方法,使引用计数加一从而保证内存的正确引用。

    自己定义的类是不能用COPY的,由于自己定义的类没有实现<NSCopy>协议,该协议里面有各种copy方法,所以,copy别乱用,尽量仅仅在设置字符串时使用。

    assign,retain 和 copy的差别

    • copy: 建立一个索引计数为1的对象,然后释放旧对象
    • retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
    • assign:直接复制。并未创建新的对象

    比方一个NSString对象。NSString *str=【NSString alloc】initwithString:@"hello";

    在内存分配的步骤例如以下:

    首先,在堆上创建一块内存,内容初始化为“hello”,地址为0X1111

    其次,在栈上创建一内存,地址为0X2222,内容为1111,

    assign : NSString *newStr=[str assign];

    则newStr是str的别名。地址为0X2222,内容为1111,retaincount值不变,对newStr运行删除操作,则str也会被删除

    copy:NSString *newStr=[str copy];

    newStr地址为0×3333,内容为3333。在栈上分配空间,地址为0X3333,内容为“hello”,新的对象retainCount为1。str对象没有变化,对newStr运行删除操作仅仅会涉及其本身,与str无关
    retain:NSString *newStr=[str retain];

    newStr地址为0X4444,内容为1111。str的retaincount++,

     assign就是直接赋值。删除时可能引起问题。当数据为int, float等原生类型时,能够使用assign。retain使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为0时,dealloc函数被调用。内存被回收。copy是在你不希望a和b共享一块内存时会使用到。a和b各自有自己的内存。



  • 相关阅读:
    深入理解协程(三):async/await实现异步协程
    AES中ECB模式的加密与解密(Python3.7)
    深入理解协程(二):yield from实现异步协程
    系统结构实践期末大作业
    第7次实践作业
    第6次实践作业
    第5次实践作业
    第4次实践作业
    第3次实践作业
    第2次实践作业
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10631278.html
Copyright © 2020-2023  润新知