zoukankan      html  css  js  c++  java
  • 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。

    代码如下所示:

     
    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. }
  • 相关阅读:
    Java_swing控件实例
    java_泛型 TreeSet 判断hashcode/length(升序排列)
    java_泛型(设置通配符下限)
    java_泛型(构造器)部分实例
    子类可以继承的同时实现接口
    继承类的线程写法
    匿名内部类的线程写法
    接口作为参数并用参数变量可以调用接口中的方法------------------需要多练习
    类可以作为参数类型,参数的变量还能调用作为参数类型的方法--------------需要多练习
    接口和类
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049294.html
Copyright © 2011-2022 走看看