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。

代码如下所示:

 
  1. #import <Foundation/Foundation.h>
  2. @interface TRStudent : NSObject
  3. @property(nonatomic,assign)int age;
  4. @property(nonatomic,copy)NSString* name;
  5. @end

在上述代码中,以下代码:

 
  1. @property(nonatomic,assign)int age;

在TRStudent类中定义了一个是整型属性age,用于存储学生的年龄。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。

在上述代码中,以下代码:

  1. @property(nonatomic,copy)NSString* name;

在TRStudent类中定义了一个是NSString类的对象name,用于存储学生的姓名。它有两个参数,一个是nonatomic,另一个参数是copy,该参数一般用于NSObject类及其子类的对象,这些对象在赋值时实现深拷贝,即属性name指向的对象是赋值给它的对象的副本。

然后,在类TRStudent的实现部分,即在TRStudent.m文件中,重写description方法的实现,该方法用于在NSLog中用%@输出TRStudent类的对象值。

代码如下所示:

  1. #import "TRStudent.h"
  2. @implementation TRStudent
  3. -(NSString *)description{
  4. return [NSString stringWithFormat:@"name:%@ age:%d",self.name, self.age];
  5. }
  6. @end

步骤二:在主程序中创建三个学生对象

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRStudent.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. TRStudent* stu1 = [[TRStudent alloc]init];
  8. stu1.age = 18;
  9. stu1.name = @"zhangsan";
  10. TRStudent* stu2 = [[TRStudent alloc]init];
  11. stu2.age = 19;
  12. stu2.name = @"lisi";
  13. TRStudent* stu3 = [[TRStudent alloc]init];
  14. stu3.age = 20;
  15. stu3.name = @"wangwu";
  16. }
  17. return 0;
  18. }

步骤三:在主程序中创建排序Block

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRStudent.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. TRStudent* stu1 = [[TRStudent alloc]init];
  8. stu1.age = 18;
  9. stu1.name = @"zhangsan";
  10. TRStudent* stu2 = [[TRStudent alloc]init];
  11. stu2.age = 19;
  12. stu2.name = @"lisi";
  13. TRStudent* stu3 = [[TRStudent alloc]init];
  14. stu3.age = 20;
  15. stu3.name = @"wangwu";
  16. NSComparisonResult(^compare)(id stu1,id stu2);
  17. compare = ^(id stu1,id stu2)
  18. {
  19. //类型转换
  20. NSString* s1 = nil;
  21. if([stu1 isMemberOfClass:[TRStudent class]])
  22. {
  23. s1 = ((TRStudent*)stu1).name;
  24. }
  25. NSString* s2 = nil;
  26. if([stu2 isMemberOfClass:[TRStudent class]])
  27. {
  28. s2 = ((TRStudent*)stu2).name;
  29. }
  30. return [s1 compare:s2];
  31. };
  32. }
  33. return 0;
  34. }

上述代码中,以下代码:

  1. NSComparisonResult(^compare)(id stu1,id stu2);

声明了Block变量compare,其中NSComparisonResult为Block的返回值类型。^为Block类型说明符,就像定义指针时使用*号一样。(id stu1,id stu2)为Block的形式参数。

Block本质上是变量,但因为其存储的数据是一段代码,所以它有返回值类型和形式参数。

上述代码中,以下代码:

  1. compare = ^(id stu1,id stu2)
  2. {
  3. //类型转换
  4. NSString* s1 = nil;
  5. if([stu1 isMemberOfClass:[TRStudent class]])
  6. {
  7. s1 = ((TRStudent*)stu1).name;
  8. }
  9. NSString* s2 = nil;
  10. if([stu2 isMemberOfClass:[TRStudent class]])
  11. {
  12. s2 = ((TRStudent*)stu2).name;
  13. }
  14. return [s1 compare:s2];
  15. };

是实现了Block。以下语句:

  1. compare = ^(id stu1,id stu2)

是对Block变量compare的赋值,将一段代码赋值给这个变量。在这段代码中,以下代码:

  1. NSString* s1 = nil;
  2. if([stu1 isMemberOfClass:[TRStudent class]])
  3. {
  4. s1 = ((TRStudent*)stu1).name;
  5. }

是对形参stu1的类型检查,如果stu1是TRStudent类的对象,则将stu1中的name属性值赋值给s1。

步骤四:在主程序中对创建的数组排序

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRStudent.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. TRStudent* stu1 = [[TRStudent alloc]init];
  8. stu1.age = 18;
  9. stu1.name = @"zhangsan";
  10. TRStudent* stu2 = [[TRStudent alloc]init];
  11. stu2.age = 19;
  12. stu2.name = @"lisi";
  13. TRStudent* stu3 = [[TRStudent alloc]init];
  14. stu3.age = 20;
  15. stu3.name = @"wangwu";
  16. NSComparisonResult(^compare)(id stu1,id stu2);
  17. compare = ^(id stu1,id stu2)
  18. {
  19. //类型转换
  20. NSString* s1 = nil;
  21. if([stu1 isMemberOfClass:[TRStudent class]])
  22. {
  23. s1 = ((TRStudent*)stu1).name;
  24. }
  25. NSString* s2 = nil;
  26. if([stu2 isMemberOfClass:[TRStudent class]])
  27. {
  28. s2 = ((TRStudent*)stu2).name;
  29. }
  30. return [s1 compare:s2];
  31. };
  32. NSArray* array = @[stu1,stu2,stu3];
  33. NSLog(@"array:%@",array);
  34. NSArray* array2 = [array sortedArrayUsingComparator:compare];
  35. NSLog(@"array2:%@", array2);
  36. }
  37. return 0;
  38. }

上述代码中,以下代码:

  1. NSArray* array = @[stu1,stu2,stu3];
  2. NSLog(@"array:%@",array);

用三个学生对象创建一个数组array。

上述代码中,以下代码:

  1. NSArray* array2 = [array sortedArrayUsingComparator:compare];

向数组对象array发送NSArray类的方法sortedArrayUsingComparator:消息,使用Block变量compare作为实参,传递一个排序方法,在该消息内对数组内的所有数组元素进行排序,并将排序的结果生成一个新的数组返回。

1.4 完整代码

本案例中,类TRStudent声明,即TRStudent.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface TRStudent : NSObject
  3. @property(nonatomic,assign)int age;
  4. @property(nonatomic,copy)NSString* name;
  5. @end

类TRStudent实现,即TRStudent.m文件,完整代码如下所示:

  1. #import "TRStudent.h"
  2. @implementation TRStudent
  3. -(NSString *)description{
  4. return [NSString stringWithFormat:@"age:%d name:%@",self.age,self.name];
  5. }
  6. @end

主程序,即main.m,完整代码如下所示:

 
  1. #import <Foundation/Foundation.h>
  2. #import "TRStudent.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. TRStudent* stu1 = [[TRStudent alloc]init];
  8. stu1.age = 18;
  9. stu1.name = @"zhangsan";
  10. TRStudent* stu2 = [[TRStudent alloc]init];
  11. stu2.age = 19;
  12. stu2.name = @"lisi";
  13. TRStudent* stu3 = [[TRStudent alloc]init];
  14. stu3.age = 20;
  15. stu3.name = @"wangwu";
  16. NSComparisonResult(^compare)(id stu1,id stu2);
  17. compare = ^(id stu1,id stu2)
  18. {
  19. //类型转换
  20. NSString* s1 = nil;
  21. if([stu1 isMemberOfClass:[TRStudent class]])
  22. {
  23. s1 = ((TRStudent*)stu1).name;
  24. }
  25. NSString* s2 = nil;
  26. if([stu2 isMemberOfClass:[TRStudent class]])
  27. {
  28. s2 = ((TRStudent*)stu2).name;
  29. }
  30. return [s1 compare:s2];
  31. };
  32. NSArray* array = @[stu1,stu2,stu3];
  33. NSLog(@"array:%@",array);
  34. NSArray* array2 = [array sortedArrayUsingComparator:compare];
  35. NSLog(@"array2:%@", array2);
  36. }
  37. return 0;
  38. }

Runtime 、 Block的更多相关文章

  1. iOS开发——OC基础-ARC、BLOCK、协议

    一.ARC ARC 是一种编译器特性!而不是IOS运行时特性,和JAVA中得垃圾回收机制完全不一样ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的 ...

  2. display:inline、block、inline-block 的区别

    一.块级元素 与  行级元素 要理解display:inline.block.inline-block的区别,需要先了解HTML中的块级(block)元素和行级(inline)元素的特点,行内元素也叫 ...

  3. 理解display:inline、block、inline-block

    要理解display:inline.block.inline-block的区别,需要先了解HTML中的块级(block)元素和行级(inline)元素的特点,行内元素也叫内联元素. 块级元素 总是另起 ...

  4. (8/18)重学Standford_iOS7开发_协议、block、动画_课程笔记

    第八课: 1.协议 另一种安全处理id类型的方式如:id <MyProtocol> obj a.声明 //协议一般放于.h文件中或者在类的.h文件中 @protocol Foo <X ...

  5. HTML5 display:inline、block、inline-block的区别--备用

    display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...

  6. display:inline、block、inline-block的区别(转)

    display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...

  7. 回传值(代理、通知、block)

    回传值问题,一直都是困扰初学者的问题,今写者 代理.通知.block 三者的回传值做了一个小小的总结, Main.storyboard 视图: 通过代码分别创建三个代表 代理.通知.block 的按钮 ...

  8. 04-Foundation-NSSet、NSDictionary、block

    目录: 一.NSSet集合 二.NSDictionary字典 三.block代码块 回到顶部 一.NSSet集合 1 NSSet是一个无序的,管理对个对象的集合类,最大特点是集合中不允许出现重复对象, ...

  9. 包建强的培训课程(12):iOS深入学习(内存管理、Block和GCD等)

    @import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=Syn ...

随机推荐

  1. 转:PHP Composer 管理工具的介绍 这个相对清晰点

    转自:http://www.aichengxu.com/view/14872 一.PHP的一些臭历史 Dependency Manager For PHP,Composer.在Composer还没诞生 ...

  2. eclipse 连接 mysql

    1.下载驱动. 2.eclipse->add extend jars -> 添加驱动. 3.测试: 在mysql 建立数据库和表,在eclipse 里对数据库进行操作. 代码: mysql ...

  3. 常用HTML转义字符,

    HTML字符实体(Character Entities),转义字符串(Escape Sequence) 为什么要用转义字符串? HTML中<,>,&等有特殊含义(<,> ...

  4. 胡扯两句——CDQ分治

    之前听大神讲过CDQ分治大概是个什么东西,但是一直还没有真正去搞过.今天稍微看了一下,写点自己的理解. 首先CDQ分治有两个条件. 条件1:可以分成两个独立互不影响的问题(这里的"独立&qu ...

  5. Hduacm—5497

    #include <cstring> #include <cstdio> #include <iostream> using namespace std; type ...

  6. POJ 1068 Parencodings 模拟 难度:0

    http://poj.org/problem?id=1068 #include<cstdio> #include <cstring> using namespace std; ...

  7. 二模 (7) day1

    第一题: 题目大意: 给出数轴上N棵树的坐标和高度,如果两棵树之间的距离小于其中一颗树的高度,那么就有树会被挡住.因此要把一些树砍矮一点.求砍树的总高度最小值. N<=100000; 解题过程: ...

  8. 常州培训 day1 解题报告

    第一题:(骗分容易,AC难.) 题目大意: 给出一个字符串,找出满足条件A的区间的个数.A:字符A,B,C的出现次数相同. 都出现0次也算,区间的长度可以是0(就是只有一个数).30% |S| ≤ 1 ...

  9. visual studio 2013连接Oracle 11g并获取数据:(二:实现)

    1.VS中新建一个winform窗体 (1)一个按钮 (2)一个数据表格视图(在里面显示得到的数据表) 2.双击按钮进入代码 (1)添加 using System.Data.OracleClient; ...

  10. Pjax的使用

    什么是pjax? 现在很多网站( facebook,  twitter)都支持这样的一种浏览方式, 当你点击一个站内的链接的时候, 不是做页面跳转, 而是只是站内页面刷新. 这样的用户体验, 比起整个 ...