Objective-c高级复习
第一章 Foundation框架介绍
Foundation.framework是iOS开发的核心框架之
第二章
一、NSNumber OC的数字类型(存储C语言中简单的基本数据类型)
C语言中简单的基本数据类型:int、float、double、char、bool
C语言中复杂的基本数据类型:enum、struct、*p(NSValue)
1 创建对象(将C->OC)
1.1 使用常量的方式创建NSNumber对象
NSNumber *number1 = @69;
float num1 = 99.8f;
NSNumber *number2 = @(num1);
1.2 使用静态(类)方法创建NSNumber对象(常用)
NSNumber *number3 = [NSNumber numberWithInteger:110];
BOOL flag1 = YES;
NSNumber *number4 = [NSNumber numberWithBool:flag1];
1.3 使用初始化方法创建NSNumber对象
NSNumber *number5 = [[NSNumber alloc] initWithInteger:110];
2 使用
2.1 将NSNumber对象转换为C语言基本数据类型
float num2 = [number2 floatValue];
BOOL flag2 = [number4 boolValue];
2.2 将NSNumber对象转换为NSString对象
NSString *string = [number5 stringValue];
2.3 判断两个NSNumber对象值是否相等
if ([number3 isEqualToNumber:number5]) {
NSLog(@”相等”);
}else{
NSLog(@”不等”);
}
2.4 比较两个NSNumber对象值的大小
NSNumber *number6 = [NSNumber numberWithInteger:100];
NSNumber *number7 = [NSNumber numberWithInteger:100];
NSComparisonResult 枚举
NSOrderedAscending = -1L, 升序
NSOrderedSame, 相同
NSOrderedDescending 降序
NSComparisonResult result = [number6 compare:number7];//100 90
注意:
1.使用常量的方式创建NSNumber对象,不需要管理内存(系统对NSNumber的引用计数做了特殊处理)
2.使用静态方法创建NSNumber对象,不需要管理内存(通过静态方法创建的对象,系统会将对象的所有权交给自动释放池进行管理)
3.使用初始化方法创建NSNumber对象,不需要管理内存(系统对NSNumber的引用计数做了特殊处理)
4.一般使用静态方法来创建NSNumber对象,不使用初始化方法
5.判断两个NSNumber是否相等使用isEqualToNumber:方法,判断两个NSNumber的大小使用compare:方法
二、NSString 不可变字符串
1 创建
1.1 使用常量方式创建NSString对象 (C -> OC)
NSString *string1 = Objective @” -C”;
1.2 使用静态(类)方法创建NSString对象
char *s = “iOS”;
NSString *string2 = [NSString stringWithCString:s encoding:NSUTF8StringEncoding];
NSString *string3 = [NSString stringWithFormat:@”%s%i%@”,s,9,@”手机操作系统”];格式化字符串 (常用)
1.3 使用初始化方法创建NSString对象
NSString *string4 = [[NSString alloc] initWithString:@”Objective-C 2.0”];
NSString *str = [[NSString alloc] initWithData:[NSData data] encoding:NSUTF8StringEncoding];
2 常用使用
2.1 获取字符串的长度
NSString *string5 = @”hello world!”;
NSUInteger len = [string5 length];
2.2 根据下标获取指定单个字符
unichar ch = [string5 characterAtIndex:2];
3 判断字符串
3.1 判断两个字符串是否相等
isEqualToString:
3.2 判断字符串是否以指定内容开头
hasPrefix:
3.3 判断字符串是否以指定内容结尾
hasSuffix:
4.字符串大小写的转换
4.1 小写转大写
NSString *string11 = [string10 uppercaseString];
4.2 大写转小写
NSString *string12 = [string10 lowercaseString];
4.3 首字母大写
NSString *string13 = [string10 capitalizedString];
5.截取字符串
NSString *string14 = @”Today is qixi day”;
5.1 截取字符串从指定位置到末尾(包含指定位置)
NSString *string15 = [string14 substringFromIndex:5];
5.2 截取字符串从开始位置到指定位置(不包含指定位置)
NSString *string16 = [string14 substringToIndex:5];
5.3 截取指定范围的字符串
NSString *string17 = [[string14 substringFromIndex:9] substringToIndex:4];
NSRange 结构体 表示范围(location 位置 length 长度)
NSRange range = NSMakeRange(9, 4);
NSString *string18 = [string14 substringWithRange:range];
6 分割字符串
NSString *string19 = @”范菲菲\n方芳芳 傅芬芳 凤飞飞”;
6.1 按指定字符串进行字符串分割
NSArray *array1 = [string19 componentsSeparatedByString:@” “];
6.2 按指定字符集合进行字符串分割
NSCharacterSet 字符集合对象
whitespaceCharacterSet 空格
newlineCharacterSet 换行
whitespaceAndNewlineCharacterSet 空格+换行
NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSArray *array2 = [string19 componentsSeparatedByCharactersInSet:set];
7 去字符串首尾的空格和换行
NSString *string20 = @” whitespaceCharacterSet \n newlineCharacterSet \n”;
NSString *string21 = [string20 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
8 替换字符串
NSString *string22 = @”one two three four five three”;
8.1 替换指定字符串
NSString *string23 = [string22 stringByReplacingOccurrencesOfString:@”o” withString:@”@”];
8.2 替换指定范围的字符串
string22 = [string22 stringByReplacingCharactersInRange:NSMakeRange(8, 5) withString:@”eight”];
9 查找字符串位置
NSString *string24 = @”one four two three four five”;
NSRange range2 = [string24 rangeOfString:@”four”];
if (range2.length>0||range2.location != NSNotFound)
10 追加字符串
NSString *string25 = @”Today is”;
10.1 追加指定字符串
NSString *string26 = [string25 stringByAppendingString:@” Hot Day!”];
10.2 追加格式化的字符串
NSString *string27 = [string26 stringByAppendingFormat:@”–%i”,2015];
10.3 追加文件路径
path = [path stringByAppendingPathComponent:@”apple”];
10.4 追加文件后缀
path = [path stringByAppendingPathExtension:@”txt”];
11 将字符串转换为C语言的基本类型
NSString *string28 = @”9.9…99”;
CGFloat num1 = [string28 doubleValue]; 9.9
NSInteger num2 = [string28 integerValue]; 9
12 文件读写
12.1 写文件
参数:
file : 写入文件的路径
atomically : 是否考虑线程安全(默认:NO)
encoding : 编码集(默认:NSUTF8StringEncoding)
error : 错误
返回值:
YES 写入成功
NO 写入失败
BOOL flag = [content writeToFile:path1 atomically:NO encoding:NSUTF8StringEncoding error:nil];
12.2 读取文件
NSString *content = [NSString stringWithContentsOfFile:path1 encoding:NSUTF8StringEncoding error:nil];
NSMutableString的用法
1 创建对象
1.1 使用类方法创建
NSMutableString *string2 = [NSMutableString stringWithCapacity:0];
NSMutableString *string3 = [NSMutableString stringWithFormat:@”%i”,100];
1.2 使用初始化方法创建 (常用)
NSMutableString *string4 = [[NSMutableString alloc] initWithCapacity:0];
2 使用
2.1 设置字符串
[string4 setString:@”apple”];
2.2 插入字符串
[string4 insertString:@”android ” atIndex:0];
2.3 追加字符串
[string4 appendString:@” windowsPhone”];
[string4 appendFormat:@”%i-%i”,9,9];
2.4 删除
[string4 deleteCharactersInRange:NSMakeRange(0, 8)];
2.5 替换
[string4 replaceCharactersInRange:NSMakeRange(0,5) withString:@”苹果”];
注意:
1.创建NSMutableString一般不使用常量赋值的方式(不能使用子类指针指向父类的成员)
2.一般常用初始化方法创建NSMutableString对象
3.NSMutableString继承自NSString(NSMutableString拥有NSString的所有方法)
四、NSArray 不可变数组
1.1 常量方式
NSArray *array1 = @[@”oooopppp”,@8989,[NSNull null]];
1.2 类方法
NSArray *array2 = [NSArray arrayWithObjects:@”1”,@”2”,@1,@2, nil];
NSArray *array3 = [NSArray arrayWithArray:array1];
NSArray *array4 = [NSArray arrayWithContentsOfFile:path];
1.3 初始化
NSArray *array3 = [[NSArray alloc] initWithObjects:@”january”,@”february”,@”march”,@”april”,@”may”,@”june”,@”july”,@”auguest”,@”september”,@”octomber”,@”november”,@”december”, nil];
2 使用常用方法
2.1 得到数组个数
NSUInteger count = [array3 count];
2.2 根据下标获取元素
id obj1 = [array3 objectAtIndex:7];
3 遍历数组的三种方式
3.1 for循环
for (int i=0; i<count; i++) {
NSString *s = [[array3 objectAtIndex:i] capitalizedString];
}
3.2 枚举(NSEnumerator)
将数组转换为枚举对象
NSEnumerator *em1 = [array3 objectEnumerator];
id obj2;
while (obj2 = [em1 nextObject]) {
if ([obj2 isEqualToString:@”auguest”]) {
NSLog(@”当前是八月份”);
break;
}
}
反转枚举
NSEnumerator *em2 = [array3 reverseObjectEnumerator];
id obj3;
while (obj3 = [em2 nextObject]) {
NSLog(@”obj3:%@”,[obj3 uppercaseString]);
}
3.3 快速枚举(前提:数组中元素类型一致,不需使用下标)
for (NSString *s in array3) {
NSLog(@”s:%@”,s);
}
4 获取数组的最后一个元素
NSString *string1 = [array3 lastObject];
NSString *string2 = [array3 objectAtIndex:[array3 count]-1];
5.判断指定元素在原数组中是否存在
if ([array3 containsObject:@”may”]) {
NSLog(@”YES”);
}else{
NSLog(@”NO”);
}
6.获取元素在数组中的下标
NSUInteger index = [array3 indexOfObject:@”auguest”];
7.连接数组
NSString *string3 = [array3 componentsJoinedByString:@”|”];
8.追加数组
NSArray *array4 = [array3 arrayByAddingObject:@”十三月”];
NSArray *array5 = [array3 arrayByAddingObjectsFromArray:array1];
9.排序
NSString排序:按照字符串的ASCII进行升序排序
NSNumber排序:按照对象值的大小进行升序排序
NSArray *array8 = [array6 sortedArrayUsingSelector:@selector(compare:)];
10 读写文件(数组以plist文件形式进行文件存储)
10.1 写文件
NSString *path = [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@”apple”] stringByAppendingPathExtension:@”plist”];
[array6 writeToFile:path atomically:NO];
10.2 读文件
NSArray *array10 = [NSArray arrayWithContentsOfFile:path];
五、NSMutableArray 可变数组
1 创建
1.1 类方法
NSMutableArray *array1 = [NSMutableArray arrayWithCapacity:0];
NSMutableArray *array2 = [NSMutableArray arrayWithObjects:@”two”,@”three”,@”five”,@”four”,@”six”,@”eight”, nil];
1.2 初始化方法
NSMutableArray *array3 = [[NSMutableArray alloc] initWithCapacity:0];
2 操作
2.1 添加元素
[array3 addObject:@”one”];
[array3 addObjectsFromArray:array2];
2.2 插入元素
[array3 insertObject:@”zero” atIndex:0];
2.3 替换
[array3 replaceObjectAtIndex:2 withObject:@”2”];
2.4 交换元素的位置
[array3 exchangeObjectAtIndex:0 withObjectAtIndex:array3.count-1];
2.5 排序
[array3 sortUsingSelector:@selector(compare:)];
3 移除
3.1 根据下标移除元素
[array3 removeObjectAtIndex:0];
3.2 移除指定元素
[array3 removeObject:@”four”];
3.3 移除最后一个元素
[array3 removeLastObject];
3.4 移除指定区域的元素
NSRange range1 = NSMakeRange(1, 2);
[array3 removeObjectsInRange:range1];
NSNull、nil、Nil、NULL的区别
1.NSNull:在集合中表示空对象([NSNull null])
NSArray *ay = [NSArray arrayWithObjects:@”aa”,@28,[NSNull null],@”bvb”,nil];
2.nil : 表示空的OC实例对象,表示集合的结束
id obj = nil;
3.Nil : 表示空的OC类对象
Class cls = Nil;
4.NULL C语言的空指针
六、NSDictionary 字典、词典(java:Hashmap)
键值对
1 创建对象
1.1 常量
NSDictionary *dic1 = @{@”key1” : @”value1”,@”key2”:@”value2”};
1.2 类方法
NSDictionary *dic2 = [NSDictionary dictionaryWithObjectsAndKeys:@”v1”,@”k1”,@”v2”,@”k2”,@”v3”,@”k3”, nil];
NSArray *keys = [NSArray arrayWithObjects:@”k1”,@”k2”,@”k3”, nil];
NSArray *objects = [NSArray arrayWithObjects:@”v1”,@”v2”,@”v3”, nil];
NSDictionary *dic3 = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
1.3 初始化
NSDictionary *dic4 = [[NSDictionary alloc] initWithDictionary:dic1];
NSDictionary *dic4 = [[NSDictionary alloc] initWithObjectsAndKeys:@”范菲菲”,@”key1”,@”傅芬芳”,@”key2”,@”凤飞飞”,@”key3”, nil];
2 常用方法的使用
2.1 得到字典中键值对的个数
NSUInteger count = [dic4 count];
2.2 根据键获取值
NSString *key = @”key3”;
NSString *obj = [dic4 objectForKey:key];
2.3 枚举(得到所有的键)
NSEnumerator *em = [dic4 keyEnumerator];
//NSEnumerator *em = [dic4 objectEnumerator];枚举所有的值(少用)
id obj2;
while (obj2 = [em nextObject]) {
NSLog(@”%@->%@”,obj2,[dic4 objectForKey:obj2]);
}
NSArray *ks = [[dic4 allKeys] sortedArrayUsingSelector:@selector(compare:)];
//NSArray *ks = [dic4 keysSortedByValueUsingSelector:@selector(compare:)];
//NSArray *vs = [dic4 allValues];//得到所有的值(少用)
for (NSString *s in ks){
NSLog(@”%@->%@”,s,[dic4 objectForKey:s]);
}
2.4 判断两个字典是否相等
if ([dic3 isEqualToDictionary:dic2]) {
NSLog(@”same”);
}else{
NSLog(@”diff”);
}
2.5 读写文件
操作路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@”apple.plist”];
写文件
if([dic4 writeToFile:path atomically:NO]){
NSLog(@”write success”);
}else{
NSLog(@”failed”);
}
读文件
NSDictionary *dic5 = [NSDictionary dictionaryWithContentsOfFile:path];
注意:
1.NSDictionary只能存储OC类型的对象
2.在NSDictionary中键值是一一对应的(一个键对应一个值)
3.在NSDictionary中,键是唯一的(不能重复)使用NSString表示,值可以重复
4.在NSDictionary中,只能使用键访问值
5.NSDictionary是一个无序的集合(不能使用下标访问元素)
七、NSMutableDictionary 可变字典
1.创建
NSMutableDictionary *dic1 = [NSMutableDictionary dictionaryWithObjectsAndKeys:@”范菲菲”,@”key1”,@”傅芬芳”,@”key2”,@”凤飞飞”,@”key3”, nil];
NSMutableDictionary *dic2 = [[NSMutableDictionary alloc] initWithCapacity:10];
2 使用
2.1 添加
[dic2 addEntriesFromDictionary:dic1];
2.2 设置方法(如果key存在则修改,如果不存在则添加)
[dic2 setObject:@”apple” forKey:@”key2”];
[dic2 setObject:@”android” forKey:@”key5”];
2.3 根据key移除指定元素
[dic2 removeObjectForKey:@”key3”];
2.4 根据key的数组移除元素
NSArray *keys = @[@”key1”,@”key5”];
[dic2 removeObjectsForKeys:keys];
2.5 移除所有元素
[dic2 removeAllObjects];
任务:
1.使用isEqualToArray: 、isEqualToDictionary:方法
2.练习NSDictionary、NSMutableDicationary
3.自学NSSet、NSMutableSet
第四章 内存管理 MRC(手动引用计数)
1.内存
组成:代码区、数据区
数据区4个组成:
常量区
全局、静态区
栈区 先进后出(成员变量、局部变量、参数等)
堆区 无序(通过malloc、alloc创建的对象)
int num = 10;
NSObject *obj = [[NSObject alloc] init];
注意:
内存管理只需管理堆区的内存
2.指针
作用:用于存储对象在内存中的首地址
地址->值
0x1111FFFAAA22->二进制
3.引用计数 retainCount
函数:
alloc:设置对象引用计数为1
retain:引用计数+1
release:引用计数立即-1
autorelease:引用计数延迟-1
dealloc:引用计数为0时,系统自动调用销毁对象
4.自动释放池 NSAutoreleasePool
编译指令:@autorelease{}
5.属性的内存管理
assign、copy、retain
assign C语言类型
copy NSString
retain OC对象
6.深拷贝与浅拷贝
深拷贝:复制对象本身(复制内存)->copy
浅拷贝:复制引用指针(复制变量)->assign/retain
注意:
OC的内存管理是基于对象的引用计数
第五章 ARC 自动引用计数
全称:Autoamtic Reference Counting
作用:
1.成员变量->编译器会在dealloc方法中为它添加release操作
2.局部变量->编译器会在方法结束之前为它添加release操作
3.返回值->编译器会在return之前为它添加autorelease操作
1.将MRC代码转换为ARC代码
1.1 手动操作
选中项目->Build Settings->ALL->Apple LLVM compiler 4.1 - Language -> Objective-C Autoamtic Reference Counting -> YES ->将源码中出现retain/release/autorelease/dealloc的代码删除掉
1.2 自动操作
菜单->Edit->Refactor->Convert To Objective-C ARC
2.在ARC中使用MRC的代码
选中项目->Build Phases->Compile Sources->Compiler Flags->-fno-objc-arc
3.强引用(strong)与弱引用(weak)
3.1 属性中的用法
assign: 用于C语言类型
copy:用于NSString
strong:用于所有OC对象
weak:用于id类型对象
@property (nonatomic,assign)NSInteger num; (默认)
@property (nonatomic,copy)NSString *str;
@property (nonatomic,strong)NSObject *obj;
@property (nonatomic,weak)id delegate;
3.2 变量中的用法
__strong 用于所有OC对象 (默认)
__weak 用于id类型对象
注意:
1.MRC与ARC的内存管理原则是一致,都是基于对象的引用计数。
2.ARC中将内存管理交给编译器完成
3.strong和weak只能作用在OC对象的属性上
第六章 归档和序列化,解档和反序列化
一、NSData 字节对象
二、NSKeyedArchiver 归档对象
1.归档单个对象操作
NSArray *array = @[@”方法”,@”333”,@88,@YES];
BOOL flag = [NSKeyedArchiver archiveRootObject:array toFile:path];
2.归档多个对象操作
2.1 指定归档文件的路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@”file.archiver”];
2.2 创建一个可变的字节对象
NSMutableData *data = [NSMutableData data];
2.3 创建归档对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
2.4 归档指定对象
[archiver encodeInteger:88 forKey:@”tmep_integer”];
[archiver encodeObject:@”黄鑫” forKey:@”temp_string”];
[archiver encodeObject:@[@”apple”,@”banana”,@”xigua”] forKey:@”temp_array”];
2.5 结束归档(将指定对象转换为字节对象存入data中)
[archiver finishEncoding];
2.6 将字节对象写入文件
[data writeToFile:path atomically:NO];
三、NSKeyedUnArchvier 解档对象
- 解档单个对象操作
NSString *path3 = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@”file4.txt”];
通过NSKeyedUnarchiver解档对象
id obj = [NSKeyedUnarchiver unarchiveObjectWithFile:path3];
2.解档多个对象操作
2.1 路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@”file.archiver”];
2.2 读取文件
NSData *data = [NSData dataWithContentsOfFile:path];
2.3 创建解档对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
2.4 根据键解档指定对象
NSInteger age = [unarchiver decodeIntegerForKey:@”tmep_integer”];
NSString *name = [unarchiver decodeObjectForKey:@”temp_string”];
NSArray *array = [unarchiver decodeObjectForKey:@”temp_array”];
2.5 结束解档
[unarchiver finishDecoding];
四、NSCoding协议
解档方法
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
_age = [aDecoder decodeIntegerForKey:AGE];
_name = [[aDecoder decodeObjectForKey:NAME] copy];
//_obj = [[aDecoder decodeObjectForKey:OBJ] copy];
}
return self;
}
归档方法
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeInteger:_age forKey:AGE];
[aCoder encodeObject:_name forKey:NAME];
//[aCoder encodeObject:_obj forKey:OBJ];
}
五、NSCoping 协议
复制方法
- (id)copyWithZone:(NSZone *)zone{
Student *stu = [[[self class] allocWithZone:zone] init];
stu.age = _age;
stu.name = [_name copyWithZone:zone];
return stu;
}
第八章 多线程
线程、进程、应用程序之间的关系
应用程序:存储在硬盘中的程序
进程:存储在内存中的(是应用程序在内存中的体现)
线程:线程是进程中的基本单位
注意:
1.进程之间是相互对立的存在
2.进程是由多个线程共同操作完成
3.iOS中的main函数启动主线程,默认所有的操作都运行在主线程上
4.线程是按照时间顺序执行的(同一时间只能执行一个事情)
一、启动线程的方式
1.使用NSThread自动启动自定义线程
[NSThread detachNewThreadSelector:@selector(run1) toTarget:self withObject:nil];
2.使用NSThread手动启动自定义线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run2) object:nil];
启动线程
[thread start];
3.自动启动一个后台(异步)线程
[self performSelectorInBackground:@selector(run3) withObject:nil];
4.NSTimer 定时器
4.1 创建一个定时器
timeInterval:时间间隔
target:目标
selector:选择器方法
userInfo:参数
repeats:是否重复
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(showTime:) userInfo:nil repeats:YES];
4.2 销毁定时器
[timer invalidate];
4.3 在指定时间销毁定时器
[timer setFireDate:[date dateByAddingTimeInterval:10]];
5.GCD
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。
创建一个异步线程
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//访问网络图片
NSURL *url = [NSURL URLWithString:@"http://desk.fd.zol-img.com.cn/g5/M00/02/07/ChMkJlXmaS2IHn4OAACKArgFkSwAACJjgHi-dUAAIoa000.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data];
//回到主线程,更新UI
dispatch_async(dispatch_get_main_queue(), ^{
UIImageView *imgView = (UIImageView *)[self.view viewWithTag:10];
imgView.image = img;
});
});
二、线程之间的通信
实现通信:回到主线程,更新UI
[self performSelectorOnMainThread:@selector(updateLbl2) withObject:nil waitUntilDone:YES];
1.主线程又叫UI线程(作用:负责界面展示) ->只有主线程能够操作界面
2.线程与线程之间数据是共享的
三、 NSCondition 琐
作用:用于处理多线程中线程安全
1.创建
NSCondition *condition = [[NSCondition alloc] init];
2.加锁
[condition lock];
3.线程的操作
…..
4.解锁
[condition unlock];