最近要着手ios的sdk,然而一点oc语言还没看过,于是乎拷贝一份网上别人的,自己抽时间看看,原文出处
http://blog.csdn.net/returningprodigal/article/details/51822101
OC语言
一、 OC入门
OC除了包含C所有的关键字外,还有本身特有的关键字,为了跟其他语言的关键字分开,这些关键字通常用@符号开头,例如:@interface、@implementation、@end、@protocal、@property、id、self、super…
OC中可以使用C中所有的数据结构,也包含了自身的特有的类型。例如:
NSInteger、NSUInteger、NSString、NSArray、NSRange
X-code常用快捷键
Command+shift+N 新建工程 Command+N 新建文件
Command+R 编译运行 Command+B 编译
Command+shift+K 清理缓存 Command+W 关闭窗口
Command+option+F 替换 Command+F 搜索
Command+shift+O 打开API文档
Ctrl+K 删除光标后的所有代码
Ctrl+D 删除光标后的第一个字符
调试时的快捷键:
fn+F6 跳过
fn+F7 跳入
fn+F8 跳出
X-code的插件XcodeKit可以实现复制当前行
Mac快捷键图例
⌘ Command shift ⌥ option/Alt
⌃ Ctrl/Control ↵ Enter/Return ⌫ Delete
⏏ Escape
Mac常用快捷键
Command+Q 关闭当前程序 Command+W 关闭当前窗口
Command+M 最小窗口 Command+Ctrl+F 最小化窗口
Command+Alt+Esc 打开强制退出窗口
Command+H 隐藏当前应用程序窗口
Command+Alt+Ctrl+关机按钮 退出所有程序后关机
二、 面向对象
实例化对象:Computer *computer = [[Computer alloc]init];
alloc:创建实例对象的方法,开辟内存空间保存对象的数据
init:初始化方法,完成对象的初始化,比如对属性赋初值
OC中的方法:
- (NSString *)setName:(NSString *)namewithAge:(int)age;
“-”:方法的类型,”-” 实例方法 “+” 类方法
“NSString *” 方法的返回值
“setName:” 方法的名称(包含冒号)
“(NSString *)name” 方法的参数
“withAge:” 方法的名称(包含冒号)
“(int)age” 方法的参数
代码规范:
l 类名:每个单词首字母大写,例如:Student
l 变量:首字母小写后面的单词首字母大写(驼峰标示) studentName
l 方法名称:和变量名称一样(驼峰标示)
l 字段、实例变量使用下划线开头
l 每个方法至少有一行间隔
.h文件用于声明属性和方法 .m文件用于实现方法
“+”类方法 “-”实例方法
类方法属于类本身,不属于具体的实例对象。使用”+”表示,调用的时候直接使用类名调用。
实例方法属于具体的实例对象,使用”-”表示,调用的时候需要实例化的具体对象名调用。
实例方法(对象方法)中调用类方法(静态方法) [类名 类方法名]
实例方法(对象方法)中调用实例方法(对象方法) [self 对象方法名]
类方法(静态方法)中调用实例方法(对象方法) 实例化对象[新对象 对象方法名]
类方法(静态方法)中调用类方法(静态方法) [self 类方法名]
重写父类方法:直接书写普通方法,只是方法名要与父类方法名相同。然后再写事件处理函数。
小技巧:快速敲出代码,如果方法在.h中声明了,敲出方法返回类型,在敲出方法名,便有提示。如果是重写父类方法,先直接敲方法名,就可看到提示。
代码例:
Car*myCar = [[Car alloc] init];
myCar.brand= @”奥迪”; 利用属性的set方法赋值
myCar->_output= 98.00; 利用->强制性赋值,但这个属性必须公开才可行
get/set方法定义
- (void)setName:(NSString*)name; 在.h文件中声明set方法
- (NSString*)name; 在.h文件中声明get方法
- (void)setName:(NSString *)name{ 在.m文件中实现set方法
_name = name;
}
- (NSString *)name{ 在.m文件中声明get方法
return _name;
}
set方法和get方法有两种方法调用,使用[]和”.”语法
[stu setName:@”小倩”];
stu.name= @”小倩”;
self、super关键字
OC中的self关键字代表着当前方法的调用,也就是说你要在当前类内部调用自己的方法时就用self关键字。
super关键字:OC中的super关键字表示当前类/对象的父类,在子类中使用其关键字调用父类的方法
注意点: 1、在实例方法中,self代表着”当前对象”
2、在类方法中,self代表着”当前类”
自定义初始化方法
OC提供的init方法没有提供参数的,只能对属性设置固定值。
自定义初始化方法必须以init开头,并且后面的单词首字母大写。
instancetype是返回值类型,表示当前的对象。
代码例如:
-(instancetype)initName:(NSString *)name{
self = [super init]; //先对父类进行初始化,因为每个OC的类都有自己的父类,首先保证父类初始化成功
if (self) { //判断self是否为nil(空),不为nil才对当前对象属性赋值
_name = name; //使用传入的值给属性赋值
}
return self; //返回当前实例对象
}
覆写description方法,description方法默认返回的是对象的地址
三、 面向对象的三大特性
l 封装
l 继承
l 多态
封装性:每个对象都把自己包含的信息(属性)和功能(方法)封闭起来,其他对象就没法访问和使用这个对象的属性和方法,这些方法和属性只能通过本类或者本类的实例来访问、使用。
继承性:一个类继承另外一个类后,这个类就可以使用它继承的类的所有非私有的属性和方法,通过继承创建的新类成为“子类”或者“派生类”。北京城的类称为“基类”、“父类”和“超类”。
我们通常把一类事物的共同特征(属性和方法)抽象成一个父类,子类继承父类后就拥有类的这些共同的特征了。
注意:找到两个事物的共同点、相同点,利用面向对象的三大特性解决问题。
Ø 方法覆写:当子类继承父类后,就包含了父类的方法,在子类中对这些继承下来的方法的扩展或者重新实现就是方法的重写(覆写)。
Ø 多态性:同一类事物的多种状态,在面向对象中,理解为接口的多种不同的实现方式即为多态。
Ø 允许将子类创建的实例对象的地址赋值给父类创建的引用(指针)
满足多态性的三个条件:
1. 必须要有类的继承
2. 必须要有方法的重写
3. 父类引用指向子类对象
四、 类之间的关系
类之间的关系:继承关系、关联关系(类似关系表)、依赖关系、聚合关系
关联关系:一个类的属性包含了另一个类的引用,有两种类型(单向关联、双向关联)
五、 属性权限关键字
@public(公开) @protected(继承、保护型) @private(私有)
Ø 类权限关键字只能用于修饰属性(实例变量),不能修饰方法。
关键字 |
当前类 |
子类 |
其他类 |
@public |
允许✓ |
✓ |
✓ |
@protected |
允许✓ |
✓ |
✗ |
@private |
允许✓ |
不允许✗ |
✗ |
默认的修饰符是@protected,一般省略。
六、 Foundation框架
(一)框架:编程语⾔言中的框架指的是集成的一些⽅方法类库,按照一定的结构组织起来提供给开发⼈人员使⽤用,从⽽而降低开发难度提⾼高开发效率。
Cocoa框架: Cocoa本身是一个框架的集合,它包含了众多⼦子框架,其中最重要的要数 “Foundation”和“UIKit”
Foundation框架: 是用于开发Mac OS / iOS程序的基本类库,包含字符串、数组、集合、字典、日期......这些用于数据处理的基础类。
(二)NSObject类
1. 重要知识点
Ø NSObject类是OC中所有类的基类,也就是说所有的OC类都直接或间接继承这个类。
Ø NSObject类是OC中所有类的基类,也就是说所有的OC类都直接或间接继承这个类。
2. NSObject常用方法:
Ø + (instancetype)alloc; // 创建对象方法
Ø (instancetype)init; // 初始化⽅方法
Ø -(id)performSelector:(SEL)aSelector; // 调⽤用没有参数的方法
Ø -(id)performSelector:(SEL)aSelector withObject:(id)object;// 调用带有一个参数的方法
Ø -(BOOL)isKindOfClass:(Class)aClass; // 判断一个类是否是某个类或者它的父类
Ø -(BOOL)isMemberOfClass:(Class)aClass; // 判断一个类是否是某个类
Ø -(BOOL)respondsToSelector:(SEL)aSelector;// 判断一个方法是否是现实了
Ø + (Class)superclass; // 获取一个类的父类
(三)NSString字符串
1. NSString对象的创建
Ø NSString *s1 = @"哈哈哈";
Ø NSString *s2 = [NSStringstringWithFormat:@"我是字符串 %@",s1];
Ø NSString *s3 = [[NSStringalloc] initWithFormat:@"qwe,%d,%@",12,s2 ];
2. 字符串的比较
a) - (BOOL)isEqualToString:(NSString *)aString; //比较内容是否相同
b) ”==”比较是否是同一个对象(地址是否相同)。例如:if(s1 == s2)
c) - (NSComparisonResult)compare:(NSString *)string; //比较字符串的升序还是降序,首先比较两个字符串的首字母的ASCII码大小,被比较的字符串首字母ASCII码大,则为升序,反之降序。相同则进行下一个字母的比较,知道最后一个,依然相同,则一样(NSOrderSame);
NSComparisonResult:NSOrderedAscending(升序)、NSOrderedDescending(降序)、NSOrderedSame(一样/相同)
3. 字符串的大小写转换:
Ø @property (readonly, copy)NSString *uppercaseString;
Ø @property (readonly, copy)NSString *lowercaseString;
Ø @property (readonly, copy)NSString *capitalizedString;
4. 字符串à基本数据类型
Ø @property (readonly) doubledoubleValue;
Ø @property (readonly) floatfloatValue;
Ø @property (readonly) intintValue;
Ø @property (readonly) NSIntegerintegerValue;
Ø @property (readonly) long longlongLongValue;
Ø @property (readonly) BOOLboolValue;
5. 基本数据类型à字符串
Ø +(instancetype)stringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);
6. 字符串的拼接(s1,s2,s3均为字符串)
Ø s3 = [NSStringstringWithFormat:@"%@ %@",s1,s2];
Ø s3 = [s1stringByAppendingString:s2];
Ø s3 = [s1stringByAppendingFormat:@"%@ %@",s2,@"---" ];
7. 字符串的查找和替换
Ø - (NSRange)rangeOfString:(NSString*)searchString;
NSNotFound:
if(r.location == NSNotFound){
//所需找的字符串没有找到
}
s3 = [s15stringByReplacingOccurrencesOfString:@"我" withString:@"ta"];
8. 字符串的截取
Ø - (NSString*)substringFromIndex:(NSUInteger)from;//取索引为from到结束的字符串
Ø - (NSString*)substringToIndex:(NSUInteger)to;//取从索引为0到索引为to的字符串
Ø - (NSString*)substringWithRange:(NSRange)range; //取指定范围内的字符串
Ø - (NSString*)characterAtIndex:(NSUInteger)index;//取指定索引位置的字符,也可为(char)用%c、%d都可输出。
9. 判断开头结尾
Ø - (BOOL)hasPrefix:(NSString*)str;//判断是否以某个字符串开头
Ø - (BOOL)hasSuffix:(NSString*)str;//判断是否以某个字符串结尾
(四)NSMutableString可变字符串
1. NSMutableString对象的创建
Ø NSMutableString *mms= @”224”;//错误,不能这样创建
Ø NSMutableString *mStr = [[NSMutableString alloc] initWithFormat:@”1234567”];
Ø NSMutableString *mStr1 = [[NSMutableString alloc] init];
Ø NSMutableString *mStr2 = [[NSMutableString alloc] initWithCapacity:10];//创建指定大小的字符串
2. NSMutableString常用方法
Ø insertString:atIndex: 在指定位置插入字符串
Ø deleteCharactersInRange: 删除指定位置的字符串
Ø appendString: 拼接指定字符串
Ø appendFormat: 接受格式符号的拼接
Ø setString: 设置字符串的内容
(五)NSNumber用于将节本数据类型保存为对象类型
3. 快捷创建方式
Ø NSNumber *num1 = @100;
Ø NSNumber *num2 = @34.1123;
Ø NSNumber *num3 = @NO;
Ø NSNumber *num4 = [[NSNumber alloc] initWithDouble:32.32133];
Ø NSNumber *num5 = [NSNumber numberWithBool:NO];
4. 转换为基本数据类型
Ø intValue NSNumber对象转换为整形
Ø doubleValue
Ø integerValue
(六)NSValue可以将结构体保存为对象类型
1. 注意:NSNumber 不能用于结构体的数据保存. NSValue可以将结构体保存为对象类型
2. 常用属性
Ø @property (readonly) NSPoint pointValue; NSValueà NSPoint
Ø @property (readonly) NSRange rangeValue; NSValueà NSRange
Ø @property (readonly)NSSize sizeValue;
Ø @property (readonly)NSRect rectValue;
Ø @property (readonly) NSEdgeInsets edgeInsetsValue;
3. 常用方法
Ø NSValue的实例方法 – getValue(void *)无返回值 NSValue à void *(任意指针类型) IOHIDDevicePlugIn.h
Ø + (NSValue*)valueWithRange:(NSRange)range; NSRangeà NSValue
Ø + (NSValue*)valueWithPoint:(NSPoint)point; NSPointà NSValue
Ø + (NSValue*)valueWithSize:(NSSize)size;
Ø + (NSValue*)valueWithRect:(NSRect)rect;
Ø + (NSValue *)valueWithEdgeInsets:(NSEdgeInsets)insets;
4. 封装自定义的结构为NSValue对象
struct Student
{
char*name;
int age;
long stuID;
}stu;
stu.name = "彭敬";
stu.age = 20;
stu.stuID = 201306181114;
char *StuType = @encode(structStudent);
NSValue *value_4 = [NSValuevalue:&stu withObjCType:StuType];
NSLog(@"%@",value_4);
5. 解析NSValue对象为结构体
struct Student stu_;
[value_4 getValue:&stu_];
NSString *stuName = [NSString stringWithUTF8String:stu_.name];
NSLog(@"%s",stu_.name);
NSLog(@"%@ %d %ld",stuName,stu_.age,stu_.stuID);
(七)NSArray类
1. 重点知识
Ø NSArray对象数组类型,只能存放对象类型,不能存放基本数据类型。如果要存放基本数据,只有通过NSNumber、NSString、NSValue
2. 创建方式
Ø NSArray *arr1 =[[NSArray alloc] init];
Ø NSArray *arr2 =[[NSArray alloc] initWithObjects:@"字符串",@"123",@100,nil];
Ø NSArray *arr3 =[[NSArray alloc] initWithArray:arr2];
Ø NSArray *arr4 = [NSArrayarrayWithObjects:@"字符串",@"123",@100,nil];
Ø +(instancetype)arrayWithObject:(ObjectType)anObject;
Person *per = [[Person alloc] init];
NSArray *arr5 = [NSArrayarrayWithObject:per];
Ø @[@””,…]
Person *perTest = [[Person alloc]init];
perTest.name = @"wo";
NSArray *arr6 = @[@"字符串",@"123",perTest,@100,@NO];
3. 常用属性
Ø @property (readonly) NSUInteger count;
Ø @property (nullable,nonatomic, readonly) ObjectType firstObject;
Ø @property (nullable,nonatomic, readonly) ObjectType lastObject;
4. 常用方法
Ø - (ObjectType)objectAtIndex:(NSUInteger)index; //根据下标获取元素
Ø - (NSUInteger)indexOfObject:(ObjectType)anObject; //获取指定元素所在的位置
Ø -(NSArray<ObjectType> *)arrayByAddingObject:(ObjectType)anObject; //在数组末尾添加一个元素
Ø - (NSArray<ObjectType> *)arrayByAddingObjectsFromArray:(NSArray<ObjectType>*)otherArray; //在数组末尾添加一个数组
Ø - (NSString *)componentsJoinedByString:(NSString *)separator; //用一个指定字符串把数组的所有元素连接成一个字符串
Ø - (BOOL)containsObject:(ObjectType)anObject; //判断数组中是否有指定对象
5. 注意:id为任意对象类型
6. 对象数组的遍历
a) 普通遍历(arr为对象数组 对象)
for(int i=0; i < arr6.count;i++)
{
NSLog(@"%@",arr6[i]);
}
b) 快速遍历
for(id i in arr6)
NSLog(@"%@",i);
c) 枚举遍历,把数组元素保存到枚举对象中
NSEnumerator *enumer = [arr6objectEnumerator];
id id_obj;
// nextObject 获取枚举对象中的下一个数据
while (id_obj = [enumernextObject]) {
NSLog(@"%@",id_obj);
}
d) block遍历
[arr6enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop){
NSLog(@"%ld:%@",idx,obj);
}];
(八)NSMutableArray(可变数组)
1. 重要知识
Ø 可以直接在原来的数组中操作(增删改查)不返回新的数组,不可变数组只能在最后添加元素
2. 可变数组的创建
Ø NSMutableArray *mArr1 =[[NSMutableArray alloc] init];
Ø NSMutableArray *mArr2 =[[NSMutableArray alloc] initWithObjects:@"123",@"字符串",nil];
Ø NSMutableArray *mArr3 =[NSMutableArray arrayWithObjects:@"123",@100, nil];
Ø NSMutableArray *mArr4 =[NSMutableArray arrayWithCapacity:10];
3. 常用方法
Ø - (void)addObject:(ObjectType)anObject; 在数组末尾添加一个元素
Ø -(void)addObjectsFromArray:(NSArray<ObjectType> *)otherArray; 在数组末尾添加一个数组
Ø -(void)exchangeObjectAtIndex:(NSUInteger)idx1withObjectAtIndex:(NSUInteger)idx2; 交换两个元素的位置
Ø - (void)removeLastObject; 移除最后一个元素
Ø -(void)removeObjectAtIndex:(NSUInteger)index; 根据索引移除元素
Ø - (void)removeAllObjects; 移除所有元素
Ø -(void)removeObject:(ObjectType)anObject inRange:(NSRange)range; 在range范围中移除指定元素
Ø -(void)removeObject:(ObjectType)anObject; 移除指定元素
(九)NSDictionary(不可变字典)
1. 重要知识点
a) 字典是一种键值一一对应(keyàvalue)的存储结构,一个键(key)对应一个值(value),不可能存在一个(key)对应两个值或者同一个值对应两个键(key)
b) 通过键去获取对应的值
c) 键和值都是对象类型,不能使用基本数据类型,键一般是NSString类型
2. 字典的创建
Ø NSDictionary *dic =[[NSDictionary alloc]initWithObjectsAndKeys:@"value",@"key",@"value1",@"key1",nil];
Ø NSDictionary *dic1 =[NSDictionarydictionaryWithObjectsAndKeys:@"val",@"k",@"val1",@"k1",nil];
Ø NSDictionary *dic2 =[NSDictionary dictionaryWithObjectsAndKeys:arr,@"key1" ,nil]; //arr是NSArray类型
Ø NSDictionary *dic3 =@{@"key1":@"val1",@"key2":@"val2",@"key3":@"val1"};
3. 常用属性
Ø @property (readonly)NSUInteger count; //获取字典中键值对的个数
Ø @property (readonly, copy)NSArray<KeyType> *allKeys; //获取所有的键
Ø @property (readonly, copy)NSArray<ObjectType> *allValues; //获取所有的值
4. 常用方法
Ø - (nullableObjectType)objectForKey:(KeyType)aKey; //根据键获取值
Ø - (NSArray<KeyType>*)allKeysForObject:(ObjectType)anObject; //获取所有值为anObject对应的键
(十)NSMutableDictionary(可变字典)
1. 创建
Ø NSMutableDictionary*mDic = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"val1",@"key1",@"val2",@"key2",nil];
Ø NSMutableDictionary*mDic1 = [NSMutableDictionarydictionaryWithObjectsAndKeys:@"val-1",@"key-1",@"val-2",@"key-2",nil];
2. 常用方法
Ø -(void)removeObjectForKey:(KeyType)aKey; //根据键移除元素
Ø -(void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey; //1、给字典添加元素;2、按照键来修改元素的值
Ø - (void)removeAllObjects; //移除所有元素
Ø -(void)removeObjectsForKeys:(NSArray<KeyType> *)keyArray; //根据键数组移除元素
Ø + (nullableNSMutableDictionary<KeyType, ObjectType>*)dictionaryWithContentsOfFile:(NSString *)path; //根据内容路径加载出字典对象,类方法
Ø + (nullableNSMutableDictionary<KeyType, ObjectType>*)dictionaryWithContentsOfURL:(NSURL *)url; //根据内容URL加载出字典对象,类方法
Ø - (nullableNSMutableDictionary<KeyType, ObjectType>*)initWithContentsOfFile:(NSString *)path; //根据内容路径加载出字典对象,实例方法
Ø - (nullable NSMutableDictionary<KeyType,ObjectType> *)initWithContentsOfURL:(NSURL *)url; //根据内容URL加载出字典对象,实例方法
3. 字典遍历(可变字典、不可变字典)(*mic 为可变字典)
a) 普通遍历
NSLog(@"第一种 普通遍历");
NSArray *arrKey = [mDic2allKeys];
for (int i=0;i<mDic2.count; i++) {
NSString *key = [arrKey objectAtIndex:i];
NSString *val = [mDic2 objectForKey:key];
NSLog(@"%@ = %@",key,val);
}
b) 快速遍历
NSLog(@"第二种 快速遍历");
for(id obj in mDic2)
{
//此处的obj为键
NSLog(@"%@ = %@",obj,[mDic2objectForKey:obj]);
}
c) 枚举遍历 keyEnumerator 拿到所有的key
NSEnumerator *enumer = [mDic2keyEnumerator];
id obj_;
NSLog(@"第三种 枚举类型遍历");
while (obj_ = [enumernextObject]) {
NSLog(@"%@ = %@",obj_,[mDic2objectForKey:obj_]);
}
d) block 遍历
NSLog(@"第四种,block遍历");
[mDic2enumerateKeysAndObjectsUsingBlock:^(id key,id val,BOOL *stop){
NSLog(@"%@ = %@",key,val);
}];
(十一) NSSet(不可变集合)
1. 集合跟数组最大的区别是
Ø 集合里面不能存在相同的元素,比如:@”a”,@”a”这样相同的字符是不可以一起保存到集合中,系统会自动保留唯一一个。
Ø 集合中的元素是无序的,即不可以使用set[2]这样的取值方式
2. 创建
Ø NSSet *set = [[NSSet alloc]init];
Ø NSSet *set1 = [[NSSet alloc]initWithObjects:@"123",@"字符串",@100, nil];
Ø NSSet *set2 = [[NSSet alloc]initWithArray:arr]; //arr是NSArray类型
Ø NSSet *set3 = [NSSetsetWithObjects:@"123",@100, nil];
3. 常用属性
Ø @property (readonly)NSUInteger count;
Ø @property (readonly, copy)NSArray<ObjectType> *allObjects;
4. 常用方法
Ø - (nullable ObjectType)member:(ObjectType)object; //指定输出元素,可以判断集合中是否有某元素
Ø -(BOOL)isEqualToSet:(NSSet<ObjectType> *)otherSet; //比较集合对象是否相同,返回布尔类型
Ø - (nullableObjectType)anyObject; //随机取得集合的任意一个元素
Ø - (NSSet<ObjectType>*)setByAddingObjectsFromSet:(NSSet<ObjectType> *)other; //给集合追加元素
Ø - (NSSet<ObjectType>*)setByAddingObjectsFromArray:(NSArray<ObjectType> *)other; //两个集合的并集,返回一个新的集合
(十二) NSMutableSet(可变集合)
一、 创建
Ø NSMutableSet *mSet =[[NSMutableSet alloc]initWithObjects:@"1",@"2",@"-",@100, nil];
Ø NSMutableSet *mSet1 = [NSMutableSetsetWithObjects:@"ha",@21,@NO,@"1",@"2", nil];
5. 常用方法
Ø -(void)addObject:(ObjectType)object; //无序添加一个元素
Ø -(void)addObjectsFromArray:(NSArray<ObjectType> *)array; //将数组中的每个元素添加到集合中
Ø -(void)intersectSet:(NSSet<ObjectType> *)otherSet; //求两个集合的交集
Ø - (void)minusSet:(NSSet<ObjectType>*)otherSet; //求两个集合的差集,集合中减去公共部分
Ø -(void)unionSet:(NSSet<ObjectType> *)otherSet; //求两个集合的并集,并保存到当前集合中去
Ø -(void)setSet:(NSSet<ObjectType> *)otherSet; //将otherSet集合中的元素替换当前集合的元素
Ø -(void)removeObject:(ObjectType)object; //移除指定的元素
Ø - (void)removeAllObjects; //移除集合中所有元素
6. 集合遍历(*mSet为集合对象)
a) 快速遍历
for(id obj in mSet3){
NSLog(@"%@",obj);
}
b) 利用枚举遍历
NSEnumerator *enumer = [mSet3 objectEnumerator];
id obj1;
while (obj1 = [enumer nextObject]) {
NSLog(@"-- %@",obj1);
}
c) block 遍历
[mSet3enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
NSLog(@"值: %@",obj);
}];
(十三) NSDate日期类
1. 获取当前时间,获取的0失去的时间跟北京时间相差8小时
NSDate *currDate = [NSDate date];// GMT 格林威治时间(世界标准时间)
2. 常见属性
Ø@property (readonly)NSTimeInterval timeIntervalSinceNow; //距离当前时间的秒数
Ø@property (readonly)NSTimeInterval timeIntervalSince1970; //当前时间到1970-1-1的秒数
Ø@property (readonly)NSTimeInterval timeIntervalSinceReferenceDate; //当前时间到2000-1-1的秒数
3. 常用方法
Ø - (instancetype)dateByAddingTimeInterval:(NSTimeInterval)ti; //追加/添加秒数/时间戳(可为正数,也可为负数)
Ø - (BOOL)isEqualToDate:(NSDate *)otherDate; //比较两个日期是否相同
Ø - (NSComparisonResult)compare:(NSDate *)other; //比较两个日期,升序、相同、降序
Ø + (NSDate *)distantFuture; //未来的一个时间 4001-01-01
Ø + (NSDate *)distantPast; //远古的一个时间 0001-12-30
Ø + (instancetype)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs; //距离当前时间的秒数
Ø + (instancetype)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti; //距离当前时间的秒数
Ø + (instancetype)dateWithTimeIntervalSince1970:(NSTimeInterval)secs; //当前时间到1970-1-1的秒数,返回NSDate
4. 计算北京时区的时间
NSDate *currDate = [NSDate date];//GMT 格林威治时间(世界标准时间)
NSTimeInterval interval2 = [[NSTimeZone systemTimeZone] secondsFromGMT];//0时区与系统时间相差的秒数
NSLog(@"%lf",interval2);
NSDate *date2 = [currDate dateByAddingTimeInterval:interval2];
NSLog(@"date2: %@",date2);
5. 时间格式化(将日期类型转化为时间字符串)
NSDate *dateNow = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
dateFormat.dateFormat = @"yyyy年M月d日 HH:mm:ss";
// stringFromDate 将日期类型格式化,转为NSString类型
NSString *strDateFormated = [dateFormat stringFromDate:dateNow];
NSLog(@"strDateFormated: %@",strDateFormated);
yyyy |
MM |
dd |
HH |
mm |
ss |
EEEE |
年 |
月 |
日 |
时 |
分 |
秒 |
星期 |
“M”与”MM”的区别:M – 7月 MM – 07月,其他符号类似
6. 将时间字符串转化为日期类型,可以实现自定义日期
dateFormat.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];// 默认使用0时区,所以需要时区的转换
NSDate *dateNow_ = [dateFormat dateFromString:strDateFormated];
七、 类目/延展/协议
(一)类目(分类)
1. 重要知识
Ø 类目(Category)是用于对原有类的方法的扩展,这些类包括系统类和自定义类。
Ø 如果扩展的方法名跟原有类的方法名一样,则会覆盖原有的方法
Ø 类目可以对类的方法进行扩展,但不能扩展实例变量、属性。如果非要扩展,可以定义get/set方法,但其本质不是扩展了属性,只是扩展的是方法,而这个方法可以有点语法调用。给人的感觉是扩展了属性。例如:
@property(nonatomic,assign)float button
这样写,不会产生_button,并需要重写get/set方法,否则报错。
2. 类目方法的应用
Ø 类目是对现有的类进行延展,可以扩展Cocoa touch框架中的类,在类目中增加的方法会被子类继承,而且在运行时跟其他的方法没有区别。
Ø 作为子类的替代手段,不需要定义和使用一个子类,可以通过类目直接向已有的类里增加方法
Ø 对类中的方法的归纳,利用Categoty把一个庞大的类划分为小块来分别进行开发,从而更好地对垒中的方法进行了更新和维护。
3. 创建方式
Ø 创建文件(Command+N)à obejective-c File à FileType: Category ,Class: ,File: ;à 会产生.h.m两个文件,名称为“扩展类名”+“File名称(扩展方法名)” à 在类目.h文件中声明要扩展的方法,例如:
@interface NSString(VerifyEmail)
- (BOOL)verifyEmail;
@end
à 在 .m文件中实现扩展的方法
(二)延展(匿名的类目)
作用:在.m文件中,用于声明类的私有方法和私有变量/属性;
注意:延展中定义的方法,即为私有方法,此私有方法必须实现,如果方法缺乏实现代码,则编译器会报警告。
例如:
@interface ViewController ()
@property (nonatomic, assign) int count;
- (void)test;
@end
(三)协议(用于两个类之间的通信(数据传递))
1. 重要知识
用于声明一组方法,这些方法在当前类(协议本身的类)中不去实现,儿时由签订协议的另外的类实现,这些方法分为必须实现(@required)和可选实现(@optional)两类。
代码例:(在.h文件中声明协议)
@protocol CollegeProtocol <NSObject>
@optional
- (void)readBook;//读书
@required
- (void)attendClass;//上课
@end
2. 注意
协议本身是声明协议方法,自己不去实现,这些方法由签订了这个协议的类去实现。
@property(nonatmic, weak) id<bindUserInfo> delegate; //签订协议的属性要由weak修饰
(四)代理设计模式(利用协议)
当一个类要去完成某一个功能,但是这个类本身没法自己去完成,那这种情况下只能委托别的类帮助完成。在OC中这种使用协议达到类与类之间的通讯方式,就是代理(委托)设计模式。
八、 内存管理(MRC和ARC)
(一)内存管理
Ø OC中创建的对象保存在内存的堆区,堆区内存的开辟和释放是要进行管理的,OC有两种管理内存的方式:手动管理(MRC)和自动管理(ARC)
Ø RetainCount:引用计数
Ø 手动管理(MRC):所谓手动管理就是由编写者自己去负责开辟空间和释放内存空间,管理内存的关键字:alloc, retain, copy, mutableCopy, release, autorelease
Ø 黄金法则:对于一个对象使用了alloc, retain, copy, mutableCopy,那么一定要对应使用release, autorelease
(二)@property关键字
1. @property关键字的作用:自动为属性生成get/set方法
2. @property中的参数(MRC下):
其中参数主要分为三类:
参数 |
默认值 |
取值范围 |
读写属性 |
readwrite |
readwrite、readonly |
setter语义 |
assign |
assign、retain、copy |
原子性(是否上同步锁) |
natomicity |
natomicity、nonatomicity |
Øretain: 只能使用在MRC模式下. 当属性的类型是1个OC对象的时候,除了循环引用之外,全部都是使用retain。
Øassign: 既可以用在MRC中,也可以用在ARC之中, 在MRC模式中和ARC模式下. 当属性的类型是1个非OC对象类型的时候. 使用assign在MRC模式下,如果出现循环引用. 一端使用retain 一端使用assign
Østrong: 只能使用在ARC模式下,当属性的类型是1个OC对象的时候,除了循环引用之外,全部都是使用strong
Øweak: 只能使用在ARC模式下,当出现循环引用的时候. 一端使用strong 一端使用weak
Øreadwrite: 可以使用在ARC模式和MRC模式下,代表同时生成属性的getter、setter
Øreadonly: 可以使用在ARC模式和MRC模式下 代表只成属性的getter
Ø修改生成的getter setter的名字: 在ARC和MRC中都可以使用.
Ø@property参数: 在MRC中使用retain的 用strong来代替就可以了.
(三)ARC
Ø ARC(自动应用计数),是iOS5所引入的管理内存的技术
Ø 使用ARC非常简单,只需要像往常那样编写代码,只不过永不写retain、release和autorelease三个关键字。当ARC开启时,编译器将自动在代码合适的地方插入retain、release、autorelease
Ø ARC的一个管理规则:只要某个对象被任一strong指针指向,那么它将不会被销毁,如果对象没有被任何strong指针指向,那么就将被销毁
(四)strong、weak关键字
Ø __strong强引用:强引用指向对象后就会持有了这个对象(相当于MRC中的retain),这个对象的引用计数+1。默认的引用都是强引用。
Ø __weak弱引用:不会持有对象(相当于assign),引用计数不会+1
Ø 循环引用就是两个对象相互持有,从而导致两个对象最后都没释放,引起内存泄露。在编写时不会报错,编译时也不会报错。
九、 谓词/KVC/KVO
(一)谓词
1. 重要知识
Ø Cocoa框架中的NSPredicate用于数组元素查询,原理和用法类似于SQL中的where,作用相当于数据库的过滤
Ø 对数组、集合操作,也可对可变数组、可变集合操作,但要覆盖原来的数组、集合。
2. 创建
NSPredicate *predicate = [NSPredicate predicateWithFormat:@”name == %@”,str];
3. 查询(arr为数组),mArrStu为可变数组
NSArray arr = [mArrStu filteredArrayUsingPredicate:predicate];
Ø ==,>=, >, <, <=
Ø between, in, contains(大小写都可)
Ø beginswith, endswith
Ø like *:替代一个、零个、多个字符; ?:替代一个字符
Ø [c] 查询中的格式字符可为大小写
例如:
“age >= 25” “age between {21,32}” “age contains[c] ‘a’” “name beginswith[c] ‘s’”
(二)KVC(适用NSObject,NSArray,NSDictionary,NSSet,NSOrderedSet)
1. 重要知识
Ø KVC通过实例变量的名称直接给实例变量赋值
Ø setValue: forKey: 设置
Ø valueForKey: 取值
Ø 如果实例变量有get/set方法,则优先调用get/set方法给实例变量赋值,如果没有则通过KVC赋值
Ø setValue: forKeyPath: 键路径设值
Ø valueForKeyPath: 键路径取值
Ø KVC可以给私有属性/变量赋值
Ø KVC的寻找方式:à _name à isName à name à isName。name、_name、isName、_isName都会被视为是成员变量name
Ø 代码示例:
//通过键设置
Student *stu = [[Student alloc] init];
[stu setValue:@"张三"forKey:@"name"];
[stu setValue:@"23.12" forKey:@"age"];
//通过键路径设值
Book *book = [[Book alloc] init];
[book setValue:@"《硅谷传奇》"forKey:@"bookName"];
[book setValue:@"54.9" forKey:@"price"];
[stu setValue:bookforKey:@"book"];
2. KVC计算
@count |
@sum |
@max |
@min |
@avg |
求个数 |
求和 |
求最大值 |
求最小值 |
求平均值 |
代码示例:
[stuvalueForKeyPath:@"arrBook.@count"] intValue];
[stu valueForKeyPath:@"arrBook.@sum.price"] floatValue];
(三)KVO(监听器)
1. 一个雷监听另一个类的属性,当属性改变,则触发监听器设定的方法。最终实现类与类之间的通讯(数据传递)
2. KVO监听的注意事项
Ø 当要用KVO监听一个属性时,这个属性一定先要有初始值,不能为nil
Ø 添加监听的时候,会调用“被监听对象”的“被监听的属性”的get方法。结合1.2的用法:别用来给属性赋初值
Ø 被监听者必须是属性或者成员变量,并且KeyPath中每个元素必须是属性或者成员变量
Ø 谁添加监听,谁去移除监听。一般在viewWillAppear中添加监听,在viewDidDisappear中移除监听
Ø 监听的属性是对象时时,只有对象被重新赋值新对象才会触发监听
Ø KVO监听原理:[self addObserver:self forKeyPath:@”name”options:… context:nil];
forKeyPath参数可以为变量/属性,也可以为变量/属性的路径。要监听则要获取这个变量/属性。获取时,实际上是利用KVC寻找方式找到这个属性所对应的成员变量或者直接就是成员变量。KVC的寻找方式:à _name àisName à name à isName。name、_name、isName、_isName都会被视为是成员变量name
3. KVO的创建
[self.useraddObserver:self forKeyPath:@"userName"options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOldcontext:NULL];
//监听器所设定的事件处理方法
- (void)observeValueForKeyPath:(NSString *)keyPath[ja1] ofObject:(id)object[ja2] change:(NSDictionary<NSString *,id> *)change[ja3] context:(void *)context[ja4] {
//通过change获取属性的新旧值:
//change[@”new”] change[@”old”]
}
4. 触发KVO方式
Ø 要使用KVC赋值
Ø 要使用set方法赋值。直接个属性的赋值是不能触发KVO,例如:_userName = @”tens”;
5. 注意
Ø 使用完后要移除监听,否则运行时会报错
-(void)dealloc{
[self.userremoveObserver:self forKeyPath:@"userName"];
}
十、 设计模式
(一)类之间的通讯方式(数据传递)
代理设计模式 |
一对一 |
一个类只能委托一个对象去完成一件事情 |
KVO(监听) |
一对多 |
一个类可以监听多个类 |
单例模式 |
公共 |
所有类共用这个对象 |
通知中心 |
一对多 |
一个对象可以通知多个对象 |
(二)单例模式
User.m代码如下:
@implementation User
static User *user = nil; //定义静态的变量,保证对象在程序生命周期中不被销毁
+ (instancetype)shareUser{
if(!user) { //创建一个实例对象,当为nil时再创建否则返回原来的值,从而保证始终是同一个实例对象
user = [[User alloc]init];
}
return user;
}
//覆盖allocWithZone: 避免使用alloc创建新的实例对象
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
if(!user) {
user = [superallocWithZone:zone];
}
return user;
}
//覆盖copyWithZone: 避免使用copy复制出新的实例对象
- (id)copyWithZone:(NSZone *)zone{
return user;
}
@end
Ø alloc方法:开辟空间
Ø init方法:对创建出来的父类对象属性初始化,以及当前对象的属性进行初始化
(三)通知中心
Ø 当一个类发送一个消息/通知,则其他监听了这个通知的类,会触发其设定的方法,从而执行设定的方法进行处理
Ø 通知中心的使用
//发送通知
NSDictionary *dic =@{@"1":@"哥哥",@"2":@"姐姐"};
[[NSNotificationCenterdefaultCenter] postNotificationName:@"登陆消息"object:@"登陆成功" userInfo:dic];
//监听通知
[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(pay:) name:@"登陆消息" object:nil];
//通知处理方法
- (void)pay:(NSNotification*)notification{
NSLog(@"%@ %@",notification.name, notification.object);
}
//移除通知
- (void)dealloc{
[[NSNotificationCenterdefaultCenter] removeObserver:self]; //移除所有通知
[[NSNotificationCenter defaultCenter] removeObserver:selfforKeyPath:@"登录消息"];//移除指定名称的通知
}