iOS 基础读书杂集(一)

前言:最近没怎么做项目,除了学习Java的基础知识。空闲时间也通过读书巩固自己iOS的基础知识。特做了一些笔记(按自己理解的),分享出来方便查阅和学习。。。
No.1 成员变量
成员变量:
iOS: 成员变量指的是在类接口部分或类实现部分定义的变量,Object-C的成员变量都是实例变量,并不支持真正的类变量

iOS: 实例变量从该类的实例(对象)被创建开始起存在,直到系统完全销毁这个实例, 实例变量可以理解为实例成员变量,它作为实例的一个成员,与实例共存亡。

iOS: 实例变量(成员变量)无须显式初始化,只要一个类定义了实例变量,系统会默认初始化,基本类型的实例变量默认为0,指针类型的成员变量默认初始化为nil.

iOS: Object-C的static关键字,但这个static关键字不能用于修饰成员变量,它只能修饰局部变量,全局变量和函数。
1.static修饰局部变量表示该局部变量存储到静态存储区
2.static修饰全局变量用于限制该全局变量只能在当前源文件中访问
3.static修饰函数,说这个函数只能在当前源文件访问
Java: static修饰的为类变量
NO.2 单例最简单写法--单例完整版
1.最简单单例:
@interface JJTest : NSObject
//提供一个类方法创建对象
+(instancetype)shareInstance;
@end


//定义一个全局变量
static id instance = nil;
@implementation JJTest
+(instancetype)shareInstance{
   //判断这个全局变量是否为nil,不为nil,就不用再创建这个实例了
    if (instance == nil) {
        //创建一个实例
        instance = [[super alloc]init];
    }
        return instance;
}

//使用:
- (void)viewDidLoad {
    [super viewDidLoad];
  
    JJTest *test1 = [JJTest shareInstance];
    JJTest *test2 = [JJTest shareInstance];
    NSLog(@"test1的地址是:%@,test2的地址是:%@",test1,test2);
   //这是最简单的单例类,不完整,如果我用alloc init创建的还是不一样的对象
    JJTest *test3 = [[JJTest alloc]init];
    JJTest *test4 = [[JJTest alloc]init];
    NSLog(@"test3-%@,test4-%@",test3,test4);
}
NO.3 隐藏成员变量
@interface JJTest : NSObject
{
    //通过private修饰符完全私有化实例变量
    @private
    NSString *_name;
    NSInteger _age;
    
}

//写set和get方法
-(void)setName:(NSString *)name;
-(NSString *)name;

-(void)setAge:(NSInteger)age;
-(NSInteger)age;

@implementation JJTest

//写set和get方法
-(void)setName:(NSString *)name{
    
    _name = name;
    
}
-(NSString *)name{
    return _name;
}
//在set方法中对年龄作一些限制
-(void)setAge:(NSInteger)age{
    if(age>0 && age<100){
        _age = age;
        NSLog(@"年龄正确");
    }else{
        NSLog(@"您给的年龄不符合实际");
    }
    
}
-(NSInteger)age{
    return _age;
}
//使用:
- (void)viewDidLoad {
    [super viewDidLoad];
  
    JJTest *test = [[JJTest alloc]init];
    //set方法给age赋值
    [test setAge:27];
     test.age = 101;//(test.age = xxx) 点语法就相当于调用了setAge方法
    //get方法获得age的值
    NSInteger num = [test age];
    NSLog(@"num=%ld",num);
}

NO.4 @property解读
1.从Objective-C 2.0版本开始,自动合成了setter方法和getter方法,并且生成一个同名的成员变量
2.虽然系统为我们提供了setter方法和getter方法,开发者依然可以提供setter或getter方法,这个方法就可以覆盖系统的setter或者getter方法

3.思考:
 3.1:我们平时的Model作为自定义cell下的一个属性,常常通过重写model的setter方法
     -(void)setModel:(Model *)model{
       _model = model;
       //拿到model给cell中的各个属性赋值
     }
     我们为什么没有写Model的setter方法的声明,因为声明在我们用@property定义model属性时候,系统已经为我们自动生成的setter和getter方法的声明和实现。 我们只需要重写setter方法的实现就好
  3.2 cell.model = self.modelArr[indexPath.row];
      cell.model = xxx  和  test.age = 101;是一样的,相当于调用了model实例变量(属性)的setter方法 ,就是给cell中的model赋值的一个过程  
   
   //4.简要说说点语法
   对于@property定义的属性,自动合成setter和getter方法
    cell.model  这是点语法,当调用点语法获取属性值的时候,调用的是getter方法, 当cell.model = XXX, 调用点语法给属性赋值的时候,相当于调用setter方法 
     
     
NO.5 atomic 和 nonatomic
atomic:主要指在定义@property的时候,存取方法合成是否是原子操作,所谓原子操作: 主要指是否线程安全

1.如果使用 atomic,那么合成的存,取方法都是线程安全的,当一个线程进入存,取方法的方法体后,其它线程无法进入。 这样就可以避免多线程并发破坏对象的数据完整性。 虽然atomic可以保证对象数据的完整性,但atomic的线程安全会造成性能下降。

2.因此,大多数单线程环境下,我们都会考虑使用nonatomic来提高存取方法的访问性能

NO.6 使用copy修饰的用意
解读: 使用copy指示符,当调用setter方法对成员变量赋值时,会将被赋值的对象复制一个副本,在将该副本赋值给成员变量。
问题:对于一个NSString类型作为属性时,如果不用copy修饰,有时会出问题:
演示问题:
@interface JJTest : NSObject
//只定义一个name属性,不用copy修饰
/**name*/
@property (nonatomic , strong) NSString *name;
@end
- (void)viewDidLoad {
    [super viewDidLoad];
  
    JJTest *test = [[JJTest alloc]init];
   //定义一个可变字符串
    NSMutableString *str = [NSMutableString stringWithString:@"我是iOS菜鸟"];
    //调用setter方法给这个test对象的name赋值
    [test setName:str];
    //获取name值打印一下
    NSLog(@"第一次test.name=%@",[test name]);
    //接下来改变这个str可变字符串的值
    [str appendString:@",向着中高级程序员进发"];
    //再来打印一次name值
    NSLog(@"第二次test.name=%@",[test name]);
    //打印结果: 第一次test.name=我是iOS菜鸟 / 第二次test.name=我是iOS菜鸟,向着中高级程序员进发

    //出现的问题:我们并没有改变这个name的值,但是由于赋值给它的str是个可变字符串。 str和test.name都指向NSMutableString这个对象的地址,所以当我们通过str指向NSMutableString的地址,改变其值后,我们的test.name值也就改变了。
    //这个问题应该是我们并不想看到的,所以这个时候我们就需要采取copy修饰符了
   
  #解决问题:strong改为copy
@property (nonatomic , copy) NSString *name;
//打印结果:第一次test.name=我是iOS菜鸟/第二次test.name=我是iOS菜鸟
    //从这次打印结果来看:
    /*
     当调用[test setName:str]方法时,程序会将str指向的NSMutableString对象复制一个副本,再将副本作为setName:的参数值,这样就可以实现当程序通过str修改底层NSMutableString对象时,test的name属性不会随着改变
     */
  }

NO.7 自己重命名这个setter和getter方法
我们在用@property定义属性的时候,可以给setter和getter方法重命名
/**name*/
@property (nonatomic , copy, setter = tmac:, getter = kobe) NSString *name;
//使用:
JJTest *test = [[JJTest alloc]init];
   //用我们重新命名的setter和getter方法给这个test的name属性赋值,取值
    [test tmac:@"我是菜鸟"];
    NSLog(@"test.name = %@",[test kobe]);

NO.8 readonly // readwrite
readonly修饰符:指系统只合成getter方法,不再合成setter方法
readwrite修饰符:setter和getter方法都合成,我们没有设置,系统自动为我们默认为readwirte.

NO.9 KVC简单的实现原理
setValue:forKey方法:
(1)程序优先考虑调用属性的setter方法完成设置
(2)如果该类没有setter方法,KVC机制会搜索该类名为_name的成员变量,无论成员变量是在类接口部分定义,还是在类实现部分定义的,也无论用哪个访问控制符修饰,KVC的底层代码实际上就是对_name成员变量赋值
//这也是我们为什么能通过KVC设置textField的提示文字的颜色
[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"]; 
//因为对于textField来说, _placeholderLabel.textColor这个成员变量是被隐藏在类实现部分的(猜测),所以我们只能通过KVC赋值

(3)如果该类以上两个都找不到,KVC会搜索该类名为name的成员变量,无论成员变量是在类接口部分定义,还是在类实现部分定义的,也无论用哪个访问控制符修饰,这个KVC代码实际就是返回name成员变量的值

(4)如果以上都找不到,系统会执行该对象的valueforUndefinedKey方法
默认的valueforUndefinedKey:方法实现就是引发一个异常,这个异常将会导致程序因为异常结束

#举例:
@interface JJTest : NSObject
{
    //定义一个name的成员变量和_name的成员变量
    NSString *name;
    NSString *_name;
}
@implementation JJTest
{
    //类实现部分定义一个age属性
    int age;
}
JJTest *test = [[JJTest alloc]init];
    [test setValue:@"tmac" forKey:@"name"];
    [test setValue:@"kobe" forKey:@"_name"];
    [test setValue:@19 forKey:@"age"];
    
    NSLog(@"name = %@",[test valueForKey:@"name"]);
    NSLog(@"_name = %@",[test valueForKey:@"_name"]);
    NSLog(@"age = %@",[test valueForKey:@"age"]);
其实可以看出区别的,对于name和_name是有差别的

NO.10 简单处理KVC操作属性赋值找不到属性的情况
我们在Test类中什么都不设置,然后我们直接来访问两个属性名
- (void)viewDidLoad {
    [super viewDidLoad];
    JJTest *test = [[JJTest alloc]init];
    [test setValue:@"tmac" forKey:@"name"];
    [test setValue:@19 forKey:@"age"];
    
    NSLog(@"name = %@",[test valueForKey:@"name"]);
    NSLog(@"age = %@",[test valueForKey:@"age"]);
}
//崩溃报错:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<JJTest 0x60000000e400> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.'

//我们在Test类实现部分重写KVC找不到key会调用的方法
@implementation JJTest
//重写setValue:forUndefinedKey:方法
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"您尝试设置的key:<%@>并不存在",key);
}

//重写valueForUndefinedKey:(id)key
-(id)valueForUndefinedKey:(id)key{
    
    NSLog(@"您尝试访问的key:<%@>并不存在",key);
    return nil;
}
@end


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

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,166评论 30 470
  • 1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch...
    阳光的大男孩儿阅读 4,999评论 0 13
  • 37.cocoa内存管理规则 1)当你使用new,alloc或copy方法创建一个对象时,该对象的保留计数器值为1...
    如风家的秘密阅读 856评论 0 4
  • 把网上的一些结合自己面试时遇到的面试题总结了一下,以后有新的还会再加进来。 1. OC 的理解与特性 OC 作为一...
    AlaricMurray阅读 2,569评论 0 20
  • 就这样 倒数着乘坐 Z112次列车的次数 同行人误了点 再次独自踏上回程的路。这学年的结束 开始能理解 我们...
    九品鲸阅读 603评论 0 2