Runtime 、 Block
1 使用Block方式,对学生对象进行排序。
1.1 问题
在iOS4.0+ 和Mac OS X 10.6+ 中添加了Block概念,以对C语言进行扩展。在Block中可以定义参数列表、返回类型,还可以获取被定义在的作用域内的局部变量的值,并且能修改使用__block修饰的局部变量的值。
Block本质上是一个变量,该变量中存储的数据是一段函数体。
1.2 方案
本案例要求定义一个学生类TRSTudent,然后创建该类的三个对象。用这三个对象建立一个数组,使用Block变量对这个数组排序。并将排序结果输出到控制台上。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义类TRStudent
首先,在Day05工程中新添加TRStudent.h文件,用于定义新的类TRStudent。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface TRStudent : NSObject
- @property(nonatomic,assign)int age;
- @property(nonatomic,copy)NSString* name;
- @end
在上述代码中,以下代码:
- @property(nonatomic,assign)int age;
在TRStudent类中定义了一个是整型属性age,用于存储学生的年龄。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。
在上述代码中,以下代码:
- @property(nonatomic,copy)NSString* name;
在TRStudent类中定义了一个是NSString类的对象name,用于存储学生的姓名。它有两个参数,一个是nonatomic,另一个参数是copy,该参数一般用于NSObject类及其子类的对象,这些对象在赋值时实现深拷贝,即属性name指向的对象是赋值给它的对象的副本。
然后,在类TRStudent的实现部分,即在TRStudent.m文件中,重写description方法的实现,该方法用于在NSLog中用%@输出TRStudent类的对象值。
代码如下所示:
- #import "TRStudent.h"
- @implementation TRStudent
- -(NSString *)description{
- return [NSString stringWithFormat:@"name:%@ age:%d",self.name, self.age];
- }
- @end
步骤二:在主程序中创建三个学生对象
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRStudent.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRStudent* stu1 = [[TRStudent alloc]init];
- stu1.age = 18;
- stu1.name = @"zhangsan";
- TRStudent* stu2 = [[TRStudent alloc]init];
- stu2.age = 19;
- stu2.name = @"lisi";
- TRStudent* stu3 = [[TRStudent alloc]init];
- stu3.age = 20;
- stu3.name = @"wangwu";
- }
- return 0;
- }
步骤三:在主程序中创建排序Block
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRStudent.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRStudent* stu1 = [[TRStudent alloc]init];
- stu1.age = 18;
- stu1.name = @"zhangsan";
- TRStudent* stu2 = [[TRStudent alloc]init];
- stu2.age = 19;
- stu2.name = @"lisi";
- TRStudent* stu3 = [[TRStudent alloc]init];
- stu3.age = 20;
- stu3.name = @"wangwu";
- NSComparisonResult(^compare)(id stu1,id stu2);
- compare = ^(id stu1,id stu2)
- {
- //类型转换
- NSString* s1 = nil;
- if([stu1 isMemberOfClass:[TRStudent class]])
- {
- s1 = ((TRStudent*)stu1).name;
- }
- NSString* s2 = nil;
- if([stu2 isMemberOfClass:[TRStudent class]])
- {
- s2 = ((TRStudent*)stu2).name;
- }
- return [s1 compare:s2];
- };
- }
- return 0;
- }
上述代码中,以下代码:
- NSComparisonResult(^compare)(id stu1,id stu2);
声明了Block变量compare,其中NSComparisonResult为Block的返回值类型。^为Block类型说明符,就像定义指针时使用*号一样。(id stu1,id stu2)为Block的形式参数。
Block本质上是变量,但因为其存储的数据是一段代码,所以它有返回值类型和形式参数。
上述代码中,以下代码:
- compare = ^(id stu1,id stu2)
- {
- //类型转换
- NSString* s1 = nil;
- if([stu1 isMemberOfClass:[TRStudent class]])
- {
- s1 = ((TRStudent*)stu1).name;
- }
- NSString* s2 = nil;
- if([stu2 isMemberOfClass:[TRStudent class]])
- {
- s2 = ((TRStudent*)stu2).name;
- }
- return [s1 compare:s2];
- };
是实现了Block。以下语句:
- compare = ^(id stu1,id stu2)
是对Block变量compare的赋值,将一段代码赋值给这个变量。在这段代码中,以下代码:
- NSString* s1 = nil;
- if([stu1 isMemberOfClass:[TRStudent class]])
- {
- s1 = ((TRStudent*)stu1).name;
- }
是对形参stu1的类型检查,如果stu1是TRStudent类的对象,则将stu1中的name属性值赋值给s1。
步骤四:在主程序中对创建的数组排序
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRStudent.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRStudent* stu1 = [[TRStudent alloc]init];
- stu1.age = 18;
- stu1.name = @"zhangsan";
- TRStudent* stu2 = [[TRStudent alloc]init];
- stu2.age = 19;
- stu2.name = @"lisi";
- TRStudent* stu3 = [[TRStudent alloc]init];
- stu3.age = 20;
- stu3.name = @"wangwu";
- NSComparisonResult(^compare)(id stu1,id stu2);
- compare = ^(id stu1,id stu2)
- {
- //类型转换
- NSString* s1 = nil;
- if([stu1 isMemberOfClass:[TRStudent class]])
- {
- s1 = ((TRStudent*)stu1).name;
- }
- NSString* s2 = nil;
- if([stu2 isMemberOfClass:[TRStudent class]])
- {
- s2 = ((TRStudent*)stu2).name;
- }
- return [s1 compare:s2];
- };
- NSArray* array = @[stu1,stu2,stu3];
- NSLog(@"array:%@",array);
- NSArray* array2 = [array sortedArrayUsingComparator:compare];
- NSLog(@"array2:%@", array2);
- }
- return 0;
- }
上述代码中,以下代码:
- NSArray* array = @[stu1,stu2,stu3];
- NSLog(@"array:%@",array);
用三个学生对象创建一个数组array。
上述代码中,以下代码:
- NSArray* array2 = [array sortedArrayUsingComparator:compare];
向数组对象array发送NSArray类的方法sortedArrayUsingComparator:消息,使用Block变量compare作为实参,传递一个排序方法,在该消息内对数组内的所有数组元素进行排序,并将排序的结果生成一个新的数组返回。
1.4 完整代码
本案例中,类TRStudent声明,即TRStudent.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface TRStudent : NSObject
- @property(nonatomic,assign)int age;
- @property(nonatomic,copy)NSString* name;
- @end
类TRStudent实现,即TRStudent.m文件,完整代码如下所示:
- #import "TRStudent.h"
- @implementation TRStudent
- -(NSString *)description{
- return [NSString stringWithFormat:@"age:%d name:%@",self.age,self.name];
- }
- @end
主程序,即main.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRStudent.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRStudent* stu1 = [[TRStudent alloc]init];
- stu1.age = 18;
- stu1.name = @"zhangsan";
- TRStudent* stu2 = [[TRStudent alloc]init];
- stu2.age = 19;
- stu2.name = @"lisi";
- TRStudent* stu3 = [[TRStudent alloc]init];
- stu3.age = 20;
- stu3.name = @"wangwu";
- NSComparisonResult(^compare)(id stu1,id stu2);
- compare = ^(id stu1,id stu2)
- {
- //类型转换
- NSString* s1 = nil;
- if([stu1 isMemberOfClass:[TRStudent class]])
- {
- s1 = ((TRStudent*)stu1).name;
- }
- NSString* s2 = nil;
- if([stu2 isMemberOfClass:[TRStudent class]])
- {
- s2 = ((TRStudent*)stu2).name;
- }
- return [s1 compare:s2];
- };
- NSArray* array = @[stu1,stu2,stu3];
- NSLog(@"array:%@",array);
- NSArray* array2 = [array sortedArrayUsingComparator:compare];
- NSLog(@"array2:%@", array2);
- }
- return 0;
- }
Runtime 、 Block的更多相关文章
- iOS开发——OC基础-ARC、BLOCK、协议
一.ARC ARC 是一种编译器特性!而不是IOS运行时特性,和JAVA中得垃圾回收机制完全不一样ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的 ...
- display:inline、block、inline-block 的区别
一.块级元素 与 行级元素 要理解display:inline.block.inline-block的区别,需要先了解HTML中的块级(block)元素和行级(inline)元素的特点,行内元素也叫 ...
- 理解display:inline、block、inline-block
要理解display:inline.block.inline-block的区别,需要先了解HTML中的块级(block)元素和行级(inline)元素的特点,行内元素也叫内联元素. 块级元素 总是另起 ...
- (8/18)重学Standford_iOS7开发_协议、block、动画_课程笔记
第八课: 1.协议 另一种安全处理id类型的方式如:id <MyProtocol> obj a.声明 //协议一般放于.h文件中或者在类的.h文件中 @protocol Foo <X ...
- HTML5 display:inline、block、inline-block的区别--备用
display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...
- display:inline、block、inline-block的区别(转)
display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...
- 回传值(代理、通知、block)
回传值问题,一直都是困扰初学者的问题,今写者 代理.通知.block 三者的回传值做了一个小小的总结, Main.storyboard 视图: 通过代码分别创建三个代表 代理.通知.block 的按钮 ...
- 04-Foundation-NSSet、NSDictionary、block
目录: 一.NSSet集合 二.NSDictionary字典 三.block代码块 回到顶部 一.NSSet集合 1 NSSet是一个无序的,管理对个对象的集合类,最大特点是集合中不允许出现重复对象, ...
- 包建强的培训课程(12):iOS深入学习(内存管理、Block和GCD等)
@import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=Syn ...
随机推荐
- 解决一个报表EdmFunction报错问题
最近测试组提了一个bug,说是某个报表点击查询报错,查看错误log,错误信息如下. 类型"Ticket.Data.SqlFuns"上指定的方法"Boolean C ...
- 使用C#下载网络文件
下载 /// <summary> /// 下载文件 /// </summary> /// <param name="URL">下载文件地址< ...
- hadoop集群配置实例
1)ssh配置 http://allthingshadoop.com/2010/04/20/hadoop-cluster-setup-ssh-key-authentication/ 2) 修改打开文件 ...
- Oracle连接出现TNS:no listener或者ORA-12514: TNS:listener does not currently know
1.Message 850 not found; No message file for product=network, facility=NL 提示框:TNS:no listener 解决办法: ...
- partition by
在row_number() over()中的over使用,其后需要配合order by ROW_NUMBER () over (partition by username order by i ...
- ARM安装ROS- indigo
Ubuntu ARM install of ROS Indigo 溪西创客小屋 There are currently builds of ROS for Ubuntu Trusty armhf. T ...
- CRF条件随机场简介
CRF(Conditional Random Field) 条件随机场是近几年自然语言处理领域常用的算法之一,常用于句法分析.命名实体识别.词性标注等.在我看来,CRF就像一个反向的隐马尔可夫模型(H ...
- C# 小规模查找集合性能测试
项目中包含浮点运算,大概每秒 20 - 100 万左右. 其计算结果每秒只包含1000个左右. 因此大量运算是重复性的.程序运行时,cpu 在 3% - 10% 浮动.打算将结果缓存.根据键值索值. ...
- C++-什么时候需要在类的构造函数中使用初始化列表
1,如果基类没有default构造函数,则意味着其不能自己初始化.如果其被派生,派生类的构造函数要负责调用基类的构造函数,并传递给它需要的参数.下例中Base 2,如果类成员没有默认构造函数.下例中E ...
- POJ 2992 求组合数的因子个数
求C(n,k)的因子个数 C(n,k) = (n*(n-1)*...*(n-k+1))/(1*2*...*k) = p1^k1 * p2^k2 * ... * pt^kt 这里只要计算出分子中素数因子 ...