OC - 第十章 属性的内部实现原理

本文详细探讨了Objective-C与Swift两种语言在iOS开发领域的应用与区别,包括其核心特性、语法对比以及实际项目中的使用案例。Objective-C作为iOS早期的主要开发语言,至今仍有一部分应用在使用;而Swift作为苹果推出的全新替代语言,以其安全性、性能和易读性受到开发者欢迎。文章旨在帮助开发者理解这两种语言的特点,选择更适合当前项目需求的语言。
//                  第十章 属性的实现原理

//  引用计数: (retainCount) 指向同一块内存的引用个数; 仍然需要release
//        1.引用计数只对堆区的对象有意义,每个对象都有引用计数
//        1)字符串引用计数问题
//        情况1:常量区
        NSString *str = @"程序员";
        NSLog(@"%@ %lu", str, str.retainCount);//打印结果:18446744073709551615
        //%lu溢出,打印出很大的书,说明是个负数, 用 %d 打印
        NSLog(@"%@, %d", str, str.retainCount);//打印结果:-1

//        情况2:常量区
        NSString *str1 = [NSString alloc]initWithString:@"产品狗"];
        NSLog(@"%@ %lu", str1, str1.retainCount);

//        情况3:堆区
        NSString *str2 = [[NSString alloc]initWithFormat:@"架构狮"];
        NSLog(@"%@ %lu", str2, str2.retainCount);
        //注: 当[[NSString alloc]initWithFormat:@"架构狮"];中字符串为中文, retainCount ++; 若为中文或数字 10 个以内为 - 1, 之后为 1;

//        2)setter和getter方法 属性的内部实现

//    assign:
//        内部实现:
        @synthesize age = _age;
        //非对象类型 直接写
        -(void)setAge:(NSInteger)age{

            _age = age;
        }
        -(NSInteger)age{
            return _age;
        }

//    copy、retain:

//      (1)(setter): 释放实例变量上一次的retain, 为这次赋值retain
//        (上次为0则retainCount ++, 否则不变)
//      (2)(getter): 帮别人retain, 自动释放(retainCount ++)

//        情况1:setter方法的野指针异常
//        原理:
        Person *per = [[Person alloc]init];
        per.name = [str1 retain];//不加retain, 访问per.name会奔溃
        per.name = [str2 retain];//每一次给属性命名, 都要加上retain; 因此需要在属性内部加上 retain
        [str2 release];
        NSLog(@"%@", per.name);
        [per.name release];

        [per release];
        [per sayHello];//给一个已经被alloc的对象发消息, 会造成crash
        NSLog(@"%lu", per.retainCount);

//        setter方法的内部实现
        @synthesize name = _name;
        -(void)setName:(NSString *)name{
            //_name = name;单纯这样写会造成Crash
            if (_name != name) {
                [_name release];//给nil对象发送消息不会造成奔溃; 但是给一个释放内存的对象发送消息就会产生野指针异常
                _name = [name retain];
            }
        }

//        情况2: getter方法的野指针异常
//        原理:
        NSString *str3 = @"小笨猪";
        Person *per3 = [[Person alloc]init];
        per3.name = str3;//此时per3.name指向str3
        [str3 release];//str3释放
        NSString *str4 = per.name;//此时如果str被释放, 会造成Crash
        [per3 release];
        NSLog(@"%@", str4);

//        2.对象定义的内存管理: 被赋值的实例变量retainCount++
//        1)便利构造器:
//        原理:
        NSArray *arr = [NSArray arrayWithObjects:@"2", @"3", @"4", nil];
        NSLog(@"%lu", arr.retainCount);//arr的引用计数
        [arr release];
//        内部实现:
        +(instancetype)personWithName:(NSString *)name{
            Person *per = [[Person alloc]initWithName:name];
            return [per autorelease];
        }


//        2)初始化:
//        原理:
        NSString *str = [[NSString alloc]initWithString:@"产品狗"];
        Person *per = [[Person alloc]initWithName:str age:23];//在这里面需要_name retain
        per.name = @"CTO";//这里会使引用计数变为 -1
        NSLog(@"Str 的引用计数: %lu", str.retainCount);//str的引用计数为3
        NSLog(@"per.name 的引用计数: %lu", per.name.retainCount);//per.name的引用计数也为3, 因为它们指向同一块内存空间

//        内部实现:
        -(instancetype)initWtihName:(NSString *)name age:(NSInteger)age{
            if ([super init]) {
                self.name = name;//因为set方法已经为name retain 了一次, 所以直接赋值
                self.age = age;
            }
            return self;
        }

//        例子1:分析打印结果: str的引用计数:1  per.name的引用计数:3
        NSString *str = [[NSString alloc]initWithFormat:@"产品狗"];
        Person *per = [[Person alloc]initWtihName:str age:23];
        per.name = [[NSString alloc]initWithFormat:@"逗比"];//先释放使str.retainCount --
        NSLog(@"str 的引用计数: %lu", str.retainCount);
        NSLog(@"per.name 的引用计数: %lu", per.name.retainCount);

//        例子2:分析打印结果:  1 , - 1 , -1
        NSString * aString = [[NSString alloc] initWithFormat:@"程序员"]; 
        NSLog(@"%d",aString.retainCount);
        aString = @"456";
        NSLog(@"%d",aString.retainCount);
        [aString release];
        aString = @"789";
        NSLog(@"%d",aString.retainCount);

//         3)集合的内存管理: 数组、集合、字典:
        Person *per = [[Person alloc]init];
        Person *per1 = [[Person alloc]init];
        Person *per2 = [[Person alloc]init];
        NSLog(@"%lu", per.retainCount);//引用计数为1
        NSMutableArray *arr = [[NSMutableArray alloc]initWithObjects:per, per1, per2, nil];//对象添加到数组中的时候,引用计数 +1
        NSLog(@"%lu", per.retainCount);//引用计数为2
        [per release];
        NSLog(@"%@", arr[0]);

        [arr removeObject:per];//将对象从数组中移除的时候, 引用计数减1
        NSLog(@"%lu",per.retainCount);
        [arr release];//数组中被(dealloc)释放的时候, 数组中的每个元素引用计数减1
        NSLog(@"%lu",per2.retainCount);

//        4)类的回收
//        内部实现:
        -(void)dealloc{
            [_name release];//当Person被回收时, 同时释放_name
            [super dealloc];//一定要写在最下面
        }

打下手 -> 程序员 -> Teemo队长 -> 项目经理 -> 架构师 -> CTO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值