Objective-C实训(六)

练习与示例:

1.代理

  • 新建Boss类,在.h中声明其方法和代理属性:
@protocol NannyDelegate <NSObject>
- (void)washClothes;
- (void)cook;

@optional
- (void)takeCareBaby;
@end

@interface Boss : NSObject
//实现了这个协议的任意类型的对象
// 代理属性要用assign和weak去修饰,不需要使用oc中的内存管理
@property (nonatomic, assign)id<NannyDelegate>delegate;
-(void)clothesDirty;
-(void)hungry;
-(void)working;
@end
  • 在.m中实现方法:
-(void)clothesDirty {
    NSLog(@"衣服脏了");
    [self.delegate washClothes];
}

-(void)hungry {
    NSLog(@"饿了");
    [self.delegate cook];
}

-(void)working {
    NSLog(@"去上班");
    // 判断我的代理人能否响应(是否实现)某方法
    if ([self.delegate respondsToSelector:@selector(takeCareBaby)]) {
        [self.delegate takeCareBaby];
    } else {
        NSLog(@"带孩子去上班");
    }
}
  • 新建一个Worker类,导入头文件并继承Boss类的代理:
#import "Boss.h"
@interface Worker : NSObject<NannyDelegate>
  • 在.h中实现:
- (void)washClothes {
    NSLog(@"洗衣服");
}

//- (void)cook {
//    NSLog(@"做饭");
//}
- (void)cook {
    NSLog(@"zuofan");
}

- (void)takeCareBaby {
    NSLog(@"保姆照顾孩子");
}
  • 在主函数中导入头文件:
#import "Boss.h"
#import "Worker.h"
  • 在主函数中实现:
    Boss *boss = [[Boss alloc]init];
    Worker *worker = [[Worker alloc]init];
    boss.delegate = worker;
    [boss hungry];
    [boss clothesDirty];
    [boss working];

2.类的扩展

  • 新建OC文件SayHi为NSString类,在.h中进行方法的声明:
- (void)sayHi;

- (void)getCharacterOfPre;
// 为NSString类扩展一个新的方法,要求获取字符串的首字母并且将该首字母大写。
- (NSString *)firstCharacter;
  • 在.m中进行实现:
- (void)sayHi {
    NSLog(@"我是%@,我是一个牛逼的字符串", self);//self指的是当前调用这个方法的字符串对象
}

- (void)getCharacterOfPre {
    NSString *s = [[self substringToIndex:1] capitalizedString];
    NSLog(@"%@", s);
}

- (NSString *)firstCharacter {
    if (self.length > 0) {
        return [[self substringToIndex:1] uppercaseString];
    }
    NSLog(@"空字符串别凑热闹");
    return @"";//或者写nil或self 
}
  • 在主函数中进行头文件导入:
#import "NSString+SayHi.h"
  • 在主函数中进行调用:
int main(int argc, const char * argv[]) {
    
    [@"徐博杰" sayHi];
    [@"dfdf" getCharacterOfPre];
    NSLog(@"%@", [@"abc" firstCharacter]);
    return 0;
}
  • 新建一个Person类,在.m中自定义初始化方法:
@interface Person ()

@property(nonatomic, retain) NSString *age;

@end

@implementation Person

- (instancetype)init
{
    self = [super init];
    if (self) {
        //私有方法通常是通过其它方法间接调用,目的是将某一部分的代码分装起来,多次使用
        [self sayHi];
    }
    return self;
}

// 没在.h中声明的都是私有方法
- (void)sayHi {
    NSLog(@"hahahaha");
}

@end

3.省市区

     NSMutableArray *provinceArray = [NSMutableArray array];
        
     // 加载文件得到字符串
     // 参数一:文件路径
     // 参数二:编码格式
     // 参数三:错误信息
     NSString *contentString = [NSString stringWithContentsOfFile:@"area.txt" encoding:NSUTF8StringEncoding error:nil];
     // NSLog(@"%@", contentString);
     // 以换行符分割字符串,得到每一行的字符串内容
     NSArray *lineArray = [contentString componentsSeparatedByString:@"\n"];
     for (NSString *lineString in lineArray) {
//          NSLog(@"line:%@", lineString);
            if (![lineString hasPrefix:@" "]) {
                // 前缀不是空格是省名
                
                // 创建一个省份字典
                NSMutableDictionary *provinceDic = [NSMutableDictionary dictionary];
                // 省份字典添加键值对(provinceName:省份名)
                [provinceDic setObject:lineString forKey:@"provinceName"];
                // 创建一个城市数组(用于后面存放城市字典)
                NSMutableArray *cityArray = [NSMutableArray array];
                // 添加键值对(cityName:城市名)
                [provinceDic setObject:cityArray forKey:@"cityArray"];
                [provinceArray addObject:provinceDic];
                
            } else if (![lineString hasPrefix:@"    "]) {
                // 前缀有空格且不是四个空格为城市名
                
                // 读取到城市名的时候需要找到该城市所属省份(当前省份数组中最后一个元素就是当前城市所属省份)
                NSMutableDictionary *provinceDic = [provinceArray lastObject];
                NSMutableArray *cityArray = [provinceDic objectForKey:@"cityArray"];
                
                // 创建城市字典
                NSMutableDictionary *cityDic = [NSMutableDictionary dictionary];
                // 添加键值对(cityName:城市名)
                [cityDic setObject:lineString forKey:@"cityName"];
                
                //创建地区数组(后面用于存放地区名称)
                NSMutableArray *areaArray = [NSMutableArray array];
                // 添加键值对(areaArray:地区数组)
                [cityDic setObject:areaArray forKey:@"areaArray"];
                //将城市的字典存到对应的城市数组中
                [cityArray addObject:cityDic];
                    
            } else {
                // 前缀有空格且有四个空格的为地区名
                
                // 获取当前地区所在省份
                NSMutableDictionary *provinceDic = [provinceArray lastObject];
                // 获取该省份的城市数组
                NSMutableArray *cityArray = [provinceDic objectForKey:@"cityArray"];
                // 从城市数组中获取当前城市所属城市
                NSMutableDictionary *cityDic = [cityArray lastObject];
                // 获取该城市的地区数组
                NSMutableArray *areaArray = [cityDic objectForKey:@"areaArray"];
                // 将地区名存到该地区数组
                [areaArray addObject:lineString];
                
            }
        }
        
    for (NSMutableDictionary *provinceDic in provinceArray) {
        NSLog(@"省份:%@", [provinceDic objectForKey:@"provinceName"]);
        for (NSMutableDictionary *cityDic in [provinceDic objectForKey:@"cityArray"]) {
            NSLog(@"城市:%@", [cityDic objectForKey:@"cityName"]);
            for (NSString *areaName in [cityDic objectForKey:@"areaArray"]) {
                NSLog(@"地区:%@", areaName);
            }
        }
    }

知识点:

1.属性的内存管理

语义特性              使用范围
assign              基本数据类(char, short, int, float, double)
retain              对象类型
 copy               对象类型,且遵守了<NSCopying>协议 

2.集合的内存管理

1️⃣常见的集合类有:NSArray,NSDictionary,NSSet。
2️⃣集合会自主管理集合内部元素。
3️⃣集合内存管理的方式:
  加入集合的元素会被retain;
  移除出集合的元素会被release;
  集合被释放时,会对集合中所有元素release;

3.KVC

1️⃣KVC:Key Value Coding,键值编码,是一种间接访问实例变量的方法。
2️⃣KVC提供了一种使用字符串(key)而不是访问器方法,去访问一个对象实例变量的机制。
3️⃣KVC中常用的方法:
- (id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
4️⃣KVC按顺序使用如下技术:
  1)、检查是否存在getter方法-<key>或者setter方法-set<key>:的方法;
  2)、如果没有上述方法,则检查是否存在名字为-_<key>、<key>的实例变量;
  3)、如果仍未找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。这些方法的默认实现都是抛出异常,我们可以根据需要重写它们。

4.ARC

ARC:Automatic Reference Counting,自动引用计数,由开发人员开辟内存空间,但是不需要释放该内存空间,由系统自动释放该空间。
ARC本质上还是基于MRC的,只不过是系统自动添加了释放内存的方法。
ARC是编译器特性,而不是运行时特性,更不是垃圾回收器(GC)。
从Xcode5.0后,创建的工程默认是开启ARC的。
当工程开启ARC后,由于编译器会自动帮你释放内存,所有和内存相关操作retain、release、autorelease,都不能写。
当重写dealloc方法时, 也不能写[super dealloc],否则会报错。
ARC中的属性语义特性:
语义特性             使用范围
assign             基本数据类(char, short, int, float, double)
strong             对象类型,相当于MRC中的retain
 copy              对象类型,且遵守了<NSCopying>协议
 weak              对象类型,但是内部不会对对象做retain的操作
ARC与MRC的混编:
如果需要对特定文件开启或关闭ARC,可以在工程选项中选择Targets -> Compile Phases -> Compile Sources,在里面找到对应文件,添加flag:
打开ARC:-fobjc-arc
关闭ARC:-fno-objc-arc

5.总结

1️⃣assign、retain、copy对应不同的setter实现。为实例变量赋值时,尽量使用setter方法,再次赋值时,会把之前值release。
2️⃣dealloc在对象引用计数为0时自动调用,不要显示调用。dealloc实现内部,先要释放实例变量,然后执行[super dealloc]。
3️⃣便利构造器的内存管理是借助autorelease实现的。
4️⃣集合会管理自己的元素。
5️⃣KVC是一种间接访问实例变量的方法。
6️⃣ARC系统管理内存,不需要开发人员手动管理。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容