GeekBand:Oc第二周学习笔记

认识oc字符串NSString

NSString是一个Unicode编码、16位字符的字符序列
NSString被定义为类,引用类型,拷贝时具有引用语义
初始化方法:字面量初始化、初始化器、工厂方法
NSString拥有恒定性,所有的操作无法更改字符串本身,如有更改都是返回新值的形式
NSString拥有共享机制,引用计数管理对其有特殊的管理规则
<small>恒定性与共享机制相辅相成,正因为有了共享机制,才需要恒定性来保证原字符串不发生变化。同时共享机制也为系统内存管理带来了很大的好处,通常应用中字符串的用量很大,如果每个相同的字符串都有一个自己的内存空间,那就会造成很大的资源浪费。所以,在oc中,当我们申明一个字符串,而这个字符串在内存中已经存在,那么该指针就会指向已存在的字符串地址上</small>

NSMutableString

NSMutableString具有可变性,NSString具有恒定性
NSMutableString为NSString的子类
NSMutableString不具有共享性,NSString具有共享性
NSMutableString并不是在原有内存上直接增长,而是重新分配一个更大或更小的缓存容量存放字符

数组 列表 字典

<small>- 类型差不多,这里主要详细讲数组</small>

认识数组:

  • 数组是一个有序的元素序列,支持随机存取。索引从0开始,索引访问越界会抛出运行时异常。注意与C语言不通。
  • NSArray被定义为class,引用类型,拷贝时具有引用语义。
  • NSArray的元素必须是对象,即NSObeject的子类:
    1.如为基本数值类型,须用NSNumber封装为对象类型后,才能放入数组中。
    2.如为C语言结构类型,须用NSValue封装为对象类型后,才能放入数组中。
    3.数组元素可以是不用对象类型,可能会有类型不安全。
    注:对于类型不安全问题,我们可以使用泛型来限制数组类型。ClassName<T>
    4.NSArra具有常量性:长度和元素指针都不能更改。但指针指向的对象内部可以更改。

常用操作:

  • 数组遍历:
    1.最快——Fast Enumeration ,直接访问内存,优化索引检查,快5-10倍,用到了多线程。
        //快速枚举
    for ( BLNPoint* point in array5)
    {
        point.x++;
        point.y++;
    }
    
    2.较慢——NSEnumerator遍历:索引检查+动态消息调用
        //迭代器模式
    NSEnumerator *enumerator = [array5 objectEnumerator];
    BLNPoint* item;
    while (item = [enumerator nextObject])
    {
        item.x++;
        item.y++;
    }
    
    3.最慢——For循环访问:索引检查+动态消息调用
        //for循环
    for (int i=0; i<array5.count; i++) {
        NSLog(@"array5[%d],%@",i,array5[i]);
    }
    
  • 注:for...in...利用了快速枚举NSFastEnumerate
    当我们想要改变数组变量中的数据或者删除数组中的数据的时候,不能用for...in...。Objective-C中的foreach循环与Java中的相似,在内部是用iterator(迭代器)实现遍历的。而不管是在Java还是C++中,一旦修改了被遍历对象,在修改前生成的iterator都会失效,所以在用iterator遍历集合时增删集合元素
    NSArray的枚举操作中有一条需要注意:对于可变数组进行枚举操作时,你不能通过添加或删除对象这类操作来改变数组容器。如果你这么做了,枚举器会很困惑,而你将得到未定义的结果。
  • 解决方法:当我们需要改变数组中的内容时(这里指NSMutableArray可变数组),可以使用enumerateObjectsUsingBlock。
    [arr enumerateObjectsUsingBlock:^(NSMutableDictionary *obj, NSUInteger idx, BOOL *stop) { 
     if (...) {
          // do sth 
         *stop = YES; // 相当于break ; stop控制跳出枚举器.   
         }
    }];
    

//使用enumerateObjectsUsingBlock快速迭代,比起forloop要快。但是要再block中如果需要改变外部变量,那么需要在外部变量前声明__block
```

可变数组(NSMutableArray)

1.NSMutableArray支持更改数组长度和元素指针。为NSArray子类。
2.NSMutableArray初始化后,会分配一个缓存容量capacity,一般大于实际元素数量,当长度增长时,如实际需求大于capacity,其capacity会以近似二倍的方式指数增长。伴随代价:(1)分配新的堆内存2*capacity (2)将原来堆内存上的元素拷贝到新内存(3)释放原来的堆内存
3.最佳实践:估计好capacity,预先分配一定容量,避免以后增长
4.尽量避免使用insertObject:atIndex:和removeObjectAtIndex:等操作,因为会改变数组元素序列,涉及大量内存拷贝操作,代价高。

ARC

自动引用计数(Automatic Reference Counting)是OC默认的内存管理机制,针对堆上的对象,由编译器自动生成操作引用计数的指令(retain和release),来管理对象的创建与释放
新创建一个对象时,它的引用计数为1,retain操作计数+1,release-1;
当一个对象的引用计数变为0的时候,内存自动释放

自动释放池(Autorelease Pool)

release会导致对象立即释放。如果频繁对对象进行release,可能会造成琐碎的内存管理负担。autorelease可以将release的调用延迟到自动释放池被释放时。
推荐使用自动释放池(Autorelease Pool)Block,当其结束时,所有接受autorelease消息的对象将会被立即释放
大多数情况下,这样使用就行了,无需程序员干预

何时需要手工管理Autorelease Pool?
1.编写的程序不基于UI框架,如命令行程序

@autoreleasepool {
       block块
       todo   

}

2.在循环中创建大量临时对象,需要更早地释放,避免临时对象聚集导致内存峰值过大
3.在主线程之外创建新的线程,在新线程开始执行处,需要创建自己的Autorelease Pool。
4.可以嵌套使用AutoreleasePool

认识协议 Protocol

OC学习篇之---协议的概念和用法

协议:类型的合同约定,只描述外部申明,不提供具体实现。所以只有h文件
协议可以包含以下成员:
1.属性
2.实例方法
3.类方法
4.初始化器——不常用
5.析构器——不常用
协议中无法包含实例变量成员(实例变量是在m文件中)
协议中定义的属性本质上是访问器方法,编译器不会合成实例变量

使用协议

@interface ClassName : NSObject<ProtocolName>
在声明类文件时 ,在类名后面用<ProtocolName>
一个类遵守协议,需要实现协议约定的所有@required成员
<small>协议中的属性须在实现类的.h文件中申明(编译器合成实例变量需要,而方法可以省略)</small>
注意编译警告信息:
遵守协议后却没有实现必选协议方法时,会出现警告提示
协议类型变量被赋值非协议类型对象时,会出现警告提示

协议本质上是一种类型,可以作为声明类型,但不能创建实例

检查协议类型
使用conformToProtocol:检查对象是否实现了协议
if([obj conformToProtocol:@protocol(Aprotocol)])

OC中的协议就是相当于Java中的接口(抽象类),只不过OC中的名字更形象点,因为我们在学习Java中的接口时候,看可以知道其实接口就相当于一种契约(协议),给他的实现类打上标记了,当然这个活在Java5.0之后,被注解替代了,因为注解就是为了此功能诞生的。
协议就是定义了一组方法,然后让其他类去实现
下面来看代码:
WithProtocol.h

#import <Foundation/Foundation.h>  

@protocol WithProtocol <NSObject>

//默认是必须实现的

//必须实现
@required

  • (void)finshTask;
  • (void)dontLate;

//可选实现
@optional

  • (void)wearNeat;

@end

>
>这里就定义了一个协议WithProtocl
协议的定义格式:

@protocol 协议名 <父协议>
定义方法
@end

- 注:定义协议的关键字是@protocol,同时协议也是可以继承父协议的
>
协议中定义的方法还有两个修饰符:
@required:这个表示这个方法是其他类必须实现的,也是默认的值
@optional:这个表示这个方法对于其他类实现是可选的
这个就和类似与Java中的抽象类了,如果是abstract修饰的就必须实现,所以如果一个协议中没有@optional修饰的方法,那么这个协议就相当于Java中的接口了。
>
- 这里要注意的是,上面的代码中NSObject不是我们之前说的NSObject类了,而是NSObject协议,他也是OC中第一个协议,这个名字相同在OC中是没有关系的。
再看一下协议的使用:

>```
>**Student.h**
>#import <Foundation/Foundation.h>  
>  
>#import "WithProtocol.h"  
>  
>@interface Student : NSObject <WithProtocol>  
>  
>- (void)study;  
>  
>@end
>```  
- 使用协议很简单,直接在继承类(NSObject)后面 <协议名>即可
>

>```
>#import "Student.h"  
  
>@implementation Student   
- (void)study{  
    NSLog(@"study");  
}  
//直接在.m文件中实现即可,不需要在.h文件中再次定义  
#pragma mark - WithProtocol  
//一般协议的方法,在这里标记下,用途是在导航栏快速地定位到这个方法是协议里的,起到分类的作用
- (void)finshTask{  
    NSLog(@"完成任务");  
}  
>- (void)dontLate{  
//#warning 代码过几天在补充  
    NSLog(@"不迟到");  
}    
>- (void)wearNeat{  
    NSLog(@"穿戴整洁");  
}    
>@end 

类别 Categroy

类别支持在没有源代码的情况下,基于某些特定场合,为一个类增加功能
可以添加:1.类方法;2.实例方法;3.重写基类方法
不能添加:1.属性;2.实例变量;3.已存在的同名方法
命名规范:类名+扩展方法,如:NSString+Drawing.h/.m

使用类别:

1.使用场景:

  • 适合在没有源代码的情况下,向已经封装的类中添加方法
  • 为一个类在某些特殊场景下增加功能
  • 对于复杂的大型文件分割实现

2.添加类别:

  • 自己创建的类
  • 系统的类
  • 第三方库
BLNPoint.h
#import <Foundation/Foundation.h>
@interface BLNPoint : NSObject
{
   float _weight;
}

@property NSInteger x;
@property NSInteger y;
-(void)move;

@end

BLNPoint+Drawing.h
#import <Foundation/Foundation.h>
#import "BLNPoint.h"

@interface BLNPoint(Drawing)
-(void)draw;
//@property NSInteger weight;
-(void)setWeight:(NSInteger)weight;
-(NSInteger)weight;
@end

扩展Extension

扩展支持在编译时、有类的源代码的情况下,向类添加功能。可以将扩展看做匿名的类别
接口定义在.m文件中@implementation前声明,实现代码仍然在@implementation中实现
扩展支持添加以下成员:

  • 添加属性
  • 添加实例成员
  • 添加类方法
  • 添加实例方法
  • 改写属性的读写属性
@interface ClassName()
{
 声明定义
}
@end

@implementation ClassName
{
 具体实现
}
@end

使用扩展:

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

推荐阅读更多精彩内容