iOS 基础读书杂集(二)

没有废话直接来,传送门:

iOS 基础读书杂集(一)

NO.11 处理KVC:setValue赋值时,给属性赋值nil的问题
当我们给引用数据类型赋值nil,不会出现问题,但是给int类型呢?
举例:
@interface JJTest : NSObject
{
    //定义两个属性,一个string,一个int
    NSString *_name;
    NSInteger _age;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    JJTest *test = [[JJTest alloc]init];
    //给这两个属性都赋值为nil
    [test setValue:nil forKey:@"_name"];
    [test setValue:nil forKey:@"_age"];
    NSLog(@"name = %@",[test valueForKey:@"_name"]);
    NSLog(@"age = %@",[test valueForKey:@"_age"]);
}
//崩溃报错:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<JJTest 0x600000030e60> setNilValueForKey]: could not set nil as the value for the key _age.'

//报错是因为:给基本数据类型赋值nil.
//解决方法:
上面的报错信息是因为在程序尝试给一个属性赋值为nil的时候,该属性又不接受nil值,那么程序会自动调用setNilValueForKey:方法
那么我们可以重写这个方法来解决这个崩溃问题
//重写setNilValueForKey:方法
-(void)setNilValueForKey:(NSString *)key{
    //如果尝试将key为_age的属性设置为nil
    if ([key isEqualToString:@"_age"]) {
        //那么将_age直接设置为0
        _age = 0;
    }else{
        //其它情况依然回调父类的方法
        [super setNilValueForKey:key];
    }
}
//再次运行打印:
 name = (null)
 age = 0

NO.12 KVO的简单模拟实现
使用KVO的步骤:
1.为被监听对象(通常是数据模型组件)注册监听器
2.监听对象重写observeValueForKeyPath:ofObject:change:context方法
举例:
@interface JJTest1 : NSObject -- 相当于模型类
/**<#注释#>*/
@property (nonatomic , copy) NSString *name;
/**<#注释#>*/
@property (nonatomic , assign) NSInteger age;
@end
@class JJTest1;

@interface JJTest : NSObject -- 相当于Cell类
//在这里JJTest类相当于一个视图View. JJTest1相当于一个模型数据类
/**test1*/
@property (nonatomic , weak) JJTest1 *test1;
//这个方法用于显示Model对象的状态
-(void)showModelInfo;
@end
#import "JJTest.h"
#import "JJTest1.h"
@implementation JJTest

//展示模型数据
-(void)showModelInfo{
    NSLog(@"test1的名称为%@,年龄为%ld",self.test1.name,self.test1.age);
}

//重写setTest1方法
//监听器的设置添加时机:当JJTest对象对test1属性设置值的时候,添加监听器
-(void)setTest1:(JJTest1 *)test1{
    
    _test1 = test1;
    //为test1添加监听器,监听test1的name属性的改变
    //理解为:test1对象你的name属性被这个JJTest对象监听了,只要你这个name属性改变了。下面的observeValueForKeyPath:方法就会被调用
    [self.test1 addObserver:self forKeyPath:@"name" options: NSKeyValueObservingOptionNew context:nil];
    //监听test1的age属性改变
    [self.test1 addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
}
//重写该方法,当被监听的数据模型发生改变时,就会回调监听器的该方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    NSLog(@"observeValueForKeyPath:方法被调用");
    //获取修改时所设置的数据
    NSLog(@"被修改的keyPath为:%@",keyPath);
    NSLog(@"被修改的对象为:%@",object);
    NSLog(@"新被修改的属性值为:%@",[change objectForKey:@"new"]);
    NSLog(@"被修改的上下文为:%@",context);
    
}

-(void)dealloc{
  //移除监听器
    [self.test1 removeObserver:self forKeyPath:@"name"];
    [self.test1 removeObserver:self forKeyPath:@"age"];
 }

//使用:
- (void)viewDidLoad {
    [super viewDidLoad];
   //创建JJTest1对象
    JJTest1 *test1 = [[JJTest1 alloc]init];
    //设置test1的属性值
    test1.name = @"tmac";
    test1.age = 18;
    //解读:以上就相当于这个在cell中通过 JJModel *model = self.modelArr[indexPath.row];获取到了对应cell行的模型数据
    
    //创建JJTest对象
    JJTest *test = [[JJTest alloc]init];
    //将test的test1属性设置为test1
    test.test1 = test1;
    //解读:这个就相当于 cell.model = model.现在在这一瞬间我们还给model的每个属性添加了监听器
    
    //调用方法展示一下test1中的东西
    [test showModelInfo];
    
    //再次更改test1对象的属性,将会激发监听器方法
    test1.name = @"kobe";
    test1.age = 24;
   
    /*
    observeValueForKeyPath:方法被调用
     被修改的keyPath为:name
     被修改的对象为:<JJTest1: 0x60000003f9a0>
     新被修改的属性值为:kobe
     被修改的上下文为:(null)
     observeValueForKeyPath:方法被调用
     被修改的keyPath为:age
     被修改的对象为:<JJTest1: 0x60000003f9a0>
     新被修改的属性值为:24
     被修改的上下文为:(null)
     */
}

NO.13 对象初始化
Objective-C的初始化是分为两步
alloc:分配内存空间
init:初始化对象

Java: new xxx();构造器是一样的原理,只不过两步合成为一步了

NO.14 便利初始化
//原有初始化方法
-(id)init;
//便利初始化方法
-(id)initWithName:(NSString *) age:(NSInteger)age;

NO.15 重写父类方法
1.子类重写父类方法,直接在类实现里重写父类方法的实现部分

2.通过super关键字可以调用父类的实例方法
//父类方法
-(void)fly{
  NSLog(@"飞起来了");
}
//子类重写父类方法]
-(void)fly{
  NSLog(@"我不会飞啊!");
}
//子类中单独写个方法,可以在里面用Super调用被覆盖的父类方法
-(void)fatherMethod{
     [super fly];
}

NO.16 子类成员变量问题
1.由于子类继承自父类,会获得父类中所有的成员变量。所以
子类接口部分不允许定义与父类接口部分重名的成员变量

2.类实现中定义的成员变量不受影响

NO.17 多态
概述: Objective-C 指针类型的变量有两个: 一个是编译时的类型,一个是运行时的类型。 
编译时的类型由声明该变量时使用的类型决定
运行时的类型由实际赋给该变量的对象决定
如果编译时类型和运行时类型不一致,就可能出现所谓的多态

NO.18 多态简单演示
//定义一个父类
@interface JJFather : NSObject
//在父类定义两个方法
-(void)method1;
-(void)method2;
@end
@implementation JJFather
//实现这个两个方法
-(void)method1{
        NSLog(@"父类的普通method1方法");
}
-(void)method2{
       NSLog(@"父类即将被覆盖的method2方法");
}
@end

//搞一个子类继承JJFather
//继承自JJFather
@interface JJSon : JJFather
//子类自己的一个方法
-(void)sonMethod;
@end
@implementation JJSon
//子类独有的方法
-(void)sonMethod{
    NSLog(@"子类独有的方法");
}
//子类覆盖父类的方法
-(void)method2{
    NSLog(@"子类覆盖了父类的method2方法");
}
@end

//多态演示:
- (void)viewDidLoad {
    [super viewDidLoad];
   //演示多态
    //1.下面编译时类型和运行时类型完全一致,不存在多态
    JJFather *father = [[JJFather alloc]init];
    //调用父类自己的方法
    [father method1];
    [father method2];
    
    //2.下面编译时类型和运行时类型完全一致,不存在多态
    JJSon *son = [[JJSon alloc]init];
    //分别调用父类的方法和子类自己的方法
    [son method1];
    [son method2];
    [son sonMethod];
    
    //3.下面编译时类型和运行时类型不一致,多态产生
    //解释:[[JJSon alloc]init]:创建了一个JJSon的对象,然后由父类类型的引用指向这个对象
    //其实按照Java的说法是父类引用指向子类对象,进行了一次向上转型
    JJFather *fatherSon = [[JJSon alloc]init];
    //调用方法
    //(1).
    [fatherSon method1];//调用从父类继承的方法
    //(2).
    [fatherSon method2];//调用覆盖父类的方法
    //(3).调用子类特有的方法是不行的
    //[fatherSon sonMethod];
    /**解释:
     对于(2):编译时会看JJFather的类型,从而找到method2方法的声明。
     当运行时,总是看赋值对象的类型,所以运行时会找到子类重写父类后的method2方法的实现
     
     对于(3).你就发现在fatherSon指针变量调用这个sonMethod时,编译时在JJFather中找不到该方法的声明,所以直接会报编译错误。
     这就是多态...
     **/
}
//打印结果:
     test1[899:35039] 父类的普通method1方法
     test1[899:35039] 父类即将被覆盖的method2方法
     test1[899:35039] 父类的普通method1方法
     test1[899:35039] 子类覆盖了父类的method2方法
     test1[899:35039] 子类独有的方法
     test1[899:35039] 父类的普通method1方法
     test1[899:35039] 子类覆盖了父类的method2方法

NO.19 Objective-C 包装类
基本概念不做过多概念,我们只说注意点
1. NSInteger / NSUInteger / CGFloat 
这三个并不是包装类,依然是基本数据类型。 在64位平台和类似于64位平台的各种平台上,NSInteger-> long, NSUInteger-> unsigned long, CGFloat-> double. 所以为了更好的兼容不同的平台,当需要定义整型变量的时候,用这三个

2. Objective-C虽然提供了类似于自动装箱的机制,把int型等直接赋值给NSNumber变量。但机制并不完善,使用自动装箱生成的NSNumber不支持ARC. 因此通常建议显式将基本类型的值包装成NSNumber对象
基本类型变量-> [NSNumber numberWihtXxx:值]-> 包装类对象
包装类对象-> [NSNumber对象 xxxValue]-> 基本类型变量

3.为什么需要将基本类型包装为类对象:
只有通过包装才能将基本类型放入数组,集合中.

NO.20 重写description方法
//创建一个测试类
@interface Test : NSObject
/**姓名*/
@property (nonatomic , copy) NSString *name;
//便利构造
-(instancetype)initWithName:(NSString *)name;
@end
@implementation Test
//便利构造
-(instancetype)initWithName:(NSString *)name{
    if (self = [super init]) {
        self.name = name;
    }
    return self;
}
@end
//演示:
- (void)viewDidLoad {
    [super viewDidLoad];
    Test *test = [[Test alloc]initWithName:@"克里斯蒂亚诺-罗"];
    NSLog(@"打印结果:%@",test);
    //打印结果:<Test: 0x608000001f90>
    //我们解读这个打印:
    //上面的结果是<Test: 16进制的首地址>
    //那么上面是怎么来的,其实我们直接打印test和 [test description]方法的返回值
    //所以对于我们程序员来说,有时需要自己的自定义类能够详细显示一些信息,我们就可以重写这个方法
    //description:是所有继承自NSObject类都有的方法,所以我们在Test的实现中重写这个方法
    
    //重写description方法
//    -(NSString *)description{
//        return [NSString stringWithFormat:@"Test类-> name = %@",self.name];
//    }
    
    //重写后:打印结果:Test类-> name = 克里斯蒂亚诺-罗
 }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,035评论 29 470
  • 前言:面试笔试都是必考语法知识点。请认真复习和深入研究OC。 目录:iOS-面试题-OC基础篇 (1) - (84...
    麦穗0615阅读 4,210评论 0 33
  • 37.cocoa内存管理规则 1)当你使用new,alloc或copy方法创建一个对象时,该对象的保留计数器值为1...
    如风家的秘密阅读 765评论 0 4
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,633评论 0 9
  • 今天收到老师的信息,让我写个刊物的祝贺辞,我想了半天才写的。 丁酉闰六月酷日炎炎,当人们都忙着避暑凉快时,不知有位...
    赵秋凯阅读 342评论 11 5