zoukankan      html  css  js  c++  java
  • block、protocol和Foundation

     

      上一章我们学习了OC内存管理的相关知识,了解了OC程序在运行中对象及变量是如何释放以达到不占用内存的效果。本章我们来学习OC的block,protocol协议和Foundation框架。

    第一讲     block

    1. block简介

      block封装了一段代码,可以在任何时候执行

      block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。

      苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多

    2. block的定义

      block的标志:^,block是用来保存一段代码

      block跟函数很像:

      1.可以保存代码

      2.有返回值

      3.有形参

      4.调用方式一样

    1> 如何定义block变量

     int (^sumBlock)(int, int);  // 带参数

     void (^myBlock)();          // 不带参数

     

     2> 如何利用block封装代码

     ^(int a, int b) {     // 带参数a和b

       return a - b;

     };

     ^() {         // 不带参数

       NSLog(@"----------");

     };

     ^ {       // 不带参数并且省略小括号()

       NSLog(@"----------");

     };

    3.  block访问外面变量

       * block内部可以访问外面的变量

       * 默认情况下,block内部不能修改外面的局部变量

       * 给局部变量加上__block关键字,这个局部变量就可以在block内部修改

    4. 利用typedef定义block类型

     typedef int (^MyBlock)(int, int);

     // 以后就可以利用MyBlock这种类型来定义block变量

     MyBlock block;

     MyBlock b1, b2;

     

     b1 = ^(int a, int b) {

     return a - b;

     };

     

     MyBlock b3 = ^(int a, int b) {

     return a - b;

     };

    下面我们通过代码来学习一下block跟局部变量之间的关系:

     1 void test()
     2 {
     3     int a = 10;
     4     __block int b = 20;
     5     
     6     void (^block)();
     7     
     8     block = ^{
     9         // block内部可以访问外面的变量
    10         //NSLog(@"a = %d", a);
    11         
    12         // 默认情况下,block内部不能修改外面的局部变量
    13         // a = 20;
    14         
    15         // 给局部变量加上__block关键字,这个局部变量就可以在block内部修改
    16         b = 25;
    17     };  
    18     block();
    19 }

    第二讲     protocol协议

    一、 protocol协议

    1. 协议的基本用途

      *可以用来声明一大堆方法(不能声明成员变量)

      *只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明

      *只要父类遵守了某个协议,就相当于子类也遵守了

    2. 协议的定义

     @protocol 协议名称 <NSObject>  //遵守基协议

      // 方法声明列表....

     @end

    3. 如何遵守协议

      1> 类遵守协议

    *只要某个类遵守了协议,就拥有了这个协议中得所有方法声明,父类遵守,子类完全遵守。

     @interface 类名 : 父类名 <协议名称1, 协议名称2>

     @end

      2> 协议遵守协议

    *一个协议可以遵守其他多个协议,多个协议之间用逗号 , 隔开

    *一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明

     @protocol 协议名称 <其他协议名称1, 其他协议名称2>

     @end

    4. 协议中方法声明的关键字

    协议中有2个关键字可以控制方法是否要实现(默认是@required),在大多数情况下,用途在于程序员之间的交流

      1> @required (默认)

      要求实现,如果没有实现,会发出警告

      2> @optional

      不要求实现,怎样不会有警告

    5. 定义一个变量的时候,限制这个变量保存的对象遵守某个协议

     类名<协议名称> *变量名;

     id<协议名称> 变量名;

     NSObject<MyProtocol> *obj;

     id<MyProtocol> obj2;

     

     

     如果没有遵守对应的协议,编译器会警告

    6. @property中声明的属性也可用做一个遵守协议的限制

     @property (nonatomic, strong) 类名<协议名称> *属性名;

     @property (nonatomic, strong) id<协议名称> 属性名;

     @property (nonatomic, strong) Dog<MyProtocol> *dog;

     @property (nonatomic, strong) id<MyProtocol> dog2;

    7. 协议可用定义在单独.h文件中,也可用定义在某个类中

     1> 如果这个协议只用在某个类中,应该把协议定义在该类中

     2> 如果这个协议用在很多类中,就应该定义在单独文件中

    8. 分类可用定义在单独.h和.m文件中,也可用定义在原来类中

     1> 一般情况下,都是定义在单独文件

     2> 定义在原来类中的分类,只要求能看懂语法

    9. 基协议

      *NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它

      *其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议

      *NSObject协议中声明很多最基本的方法,比如description、retain、release等

      *建议每个新的协议都要遵守NSObject协议

    二、 代理设计模式

    1. 设计原理

      有些麻烦的事情不想自己亲自做,就可以找个人帮忙做,即交给代理对象去做

    2. 设计原则

      *首先得拥有某个代理对象属性

      *其次要很清楚代理有哪些方法

      *最后要保证能解耦

    3. 实现方案

      *定义一个protocol,在其中声明一些和代理沟通的方法

      *拥有一个代理属性id<protocol> delegate

      *让代理遵守protocol

    第三讲     Foundation框架

     

    Foundation框架中包含了很多开发常用的数据类型,结构体、枚举等。下面列举出常用的结构体。

    一、 Foundation框架-结构体

    1. NSRange(location length)表示范围

    创建变量的三种方式

     

      NSRange r1 = {1,2}; // 可读性差

     

      NSRange r2 = {.location = 1,length = 2}; // 代码冗长

     

      NSRange r3 = NSMakeRange(1,2); // Foundation自带函数,常用

    查找字符串的范围

     

      NSString *str = @”jack andy”;

     

      NSRange r = [str rangeOfString:@”rose”];

     

    // 找不到,location=NSNotFound=-1;length=0.

    2. NSPoint/CGPoint表示坐标

     

    NSPoint p1 = CGPointMake(1,2)//常用

     

    CGPoint p2 = NSMakePoint(1,2)

    3. NSSize/CGSize表示UI元素的的尺寸(宽度,高度)

     

    NSSize s1 = CGSizeMake(100, 50);

     

    NSSize s2 = NSMakeSize(100, 50);

     

    CGSize s3 = NSMakeSize(200, 60);

    4. NSRect/CGrect(CGPoint CGsize)UI元素的位置和尺寸

     

    CGRect r1 = CGRectMake(0, 0, 100, 50);

    CGRect r2 = { {0, 0}, {100, 90}};

     

    CGRect r3 = {p1, s2};

     

          CGPointZero == CGPointMake(0,0);//原点

     

          // 利用框架中函数将结构体转为字符串

     

          NSString *str = NSStringFromPoint(p1);

    二、 Foundation框架-字符串

    1. NSString:不可变字符串

    (1)创建字符串的六种形式

      *NSString *s1 = @"jack";

      *NSString *s2 = [[NSString alloc] initWithString:@"jack"];

      *NSString *s3 = [[NSString alloc] initWithFormat:@"age is %d", 10]; 

     

    // C字符串 --> OC字符串

      *NSString *s4 = [[NSString alloc] initWithUTF8String:"jack"];

     

    // OC字符串 --> C字符串

      *const char *cs = [s4 UTF8String];

      *NSUTF8StringEncoding 用到中文就可以用这种编码

     

    NSString *s5 =[[NSString alloc] initWithComtentsOfFile:@”文件路径” encoding:NSUTF8StringEncoding error:nil];

     

        // URL : 资源路径

     

        // 协议头:// 路径

     

        // file://

     

        // ftp://

     

    NSURL *url = [[NSURL alloc] initWithString:@”file://文件路径”] 

     

    NSURL *url = [NSURL fileURLWithPath:@”文件路径”];

     

    NSString *s6 = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

     

    [NSURL URLWithString:(NSString *)]; // 一般都会有个类方法跟对象方法配对,类方法通常以类名开头

    (2)字符串的导入导出

    // 字符串的导出

      [@”haha” writeToFile:@”文件路径” atomically:YES NSUTF8StringEncoding error:nil];

      NSString *str = @”haha123”;

      NSURL *url = [NSURL fileURLWithPath:@”文件路径”];

      [str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];

    2. NSMutableString:可变字符串

     

      NSMutableString *s1 = [NSMutableString stringWithFormat:@"Hello my Kitty "];

     

    // 拼接内容到s1的后面

     

      [s1 appendString:@" ohoh"]; 

     

    // 获取my的范围

     

    // 一个获取范围,一个进行删除

     

      NSRange range = [s1 rangeOfString:@"my"];

     

      [s1 deleteCharactersInRange:range];//删除my之后的字符串

    // 不可变字符串实现拼接成新的字符串    

     

      NSString *s2 = [NSString stringWithFormat:@"Hello Kitty"];

     

    // s2的内容拷贝一份,加上字符串返回新的字符串

      NSString *s3 = [s2 stringByAppendingString:@" oh my god"];

    三、 Foundation框架-集合

    1. NSArray和NSMutableArray

      1>NSArray是OC中使用的数组,只能存放OC对象,不能存放非OC对象类型,如int、struct、enum等等

    创建OC数组:

      NSArray *array1 = [NSArray arrayWithObject:@”jack”];//单个元素

    // 多个元素,结尾必须以nil结尾

      NSArray *array2 = [NSArray arrayWithObjects:@”jack”,@”andy”,nil];

    // 快速创建一个OC数组

      NSArray *array3 = @[@”jack”,@”andy”];

    // 访问OC数组元素和C语言一样

      array2[0] ;

    // 获取数组元素的个数

      array.count;

      2>NSArray的遍历              

     1 #import "Person.h"
     2 
     3 int main()
     4 {
     5       Person *p = [[Person alloc] init];
     6 
     7       NSArray *array = @[p, @"jack", @"andy"];
     8 
     9       // for循环快速遍历数组元素
    10      // id obj代表着数组中的每一个元素
    11       for (id obj in array)
    12       {
    13          // 快速找出obj元素在数组中的位置
    14          NSUInteger i = [array indexOfObject:obj];
    15 
    16          NSLog(@"%ld - %@", i, obj);
    17       }
    18       // 使用block遍历
    19       // 每遍历一个元素,就会调用一次block,并把当前元素的索引位置当作参数传给block
    20      [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
    21           NSLog(@"%ld - %@", idx, obj);
    22 
    23          if (idx == 0)
    24          {
    25                // 停止遍历
    26                *stop = YES;
    27          }
    28      }];
    29       return 0;
    30 }

      3>NSMutableArray

      NSMutableArray *array = [NSMutableArray arrayWithObjects:@"haha", @"andy", nil];

    // 添加元素

      [array addObject:@"Kitty"];

    // 删除元素

      [array removeAllObjects];

    // 删除指定的对象

      [array removeObject:@"haha"];

    // 删除指定索引的元素

      [array removeObjectAtIndex:1];

    // 错误写法

      [array addObject:nil];

    // @[]只能创建不可变数组NSArray

      NSMutableArray *array = @[@”andy”];// 错

    2. NSSet和NSMutableSet

      1>NSSet

      NSSet *s = [NSSet set];

    // 创建多元素NSSet

      NSSet *s1 =[NSSet setWithObjects:@”jack”,@”andy”,nil];

    // 随机取出一个元素

      NSString *s2 = [s1 anyObject];

      2>NSMutableSet

      NSMutableSet *s = [NSMutableSet set];

    // 添加元素

      [s addObject:@”haha”];

    // 删除指定元素

      [s removeObject:(id)];

      3>NSSet和NSArray

    都是集合,都能存放多个对象

    都只能存放OC对象

    本身不可变,都有一个可变的子类

    不同:NSSet无序,NSArray有序

    3. NSDictionary和NSM

      根据key找到value。里面存储的东西都是键值对。

      1>NSDictionaryutableDictionary

    // 创建字典

      NSDictionary *dict = [NSDictionary dictionaryWithObject:@”jack” forKey:@”name”];

    // 快速创建字典

      NSDictionary *dict = @{@”name”:@”jack”};

    // 访问

    // 根据key获取对应的值

      id obj = [dict objectForKey:@”name”];

    // 快速访问

      id obj = dict [@”name”];

    // 添加、移除键值对

      [dict setObject:@”jack” forKey:@”name”];

      [dict removeObjectForKey:(id)];

      2>遍历

    NSDictionary的遍历和上面提到的NSArray的遍历是一样的,可以通过for循环和block遍历,下面我只写一下block遍历。

      [dict enumerateKeysAndObjectsUsingBlock:

        ^(id key, id obj, BOOL *stop) {

        NSLog(@"%@ - %@", key, obj);

             // *stop = YES;

      }];

      注意:字典不允许有相同的key,但允许有相同的value,字典也是无序的。

      3>NSMutableDictionary

    创建、访问等和父类一样,唯一要注意的地方是下面这个:

                 //返回的是NSDictionary类型的

      NSMutableDictionary *dict = @{@"name" : @"jack"};

      [dict setObject:@"rose" forKey:@"name"];

    四、 NSNumber、NSDate、NSValue

    1. NSNumber

    将基本数据类型包装成对象

      NSNumber *num = [NSNumber numberWithInt:25];

      NSDictionary *dict =@{@”age”: num};

      NSNumber *num1 = dict[@”age”];

      int a = [num2 intValue];

     

    编译器特性:自动将基本数据类型包装成对象

    NSArray *aray = @{@”age”:@20};

    @’A’ ;//NSNumber对象 @(age)

    @”A”;//NSString对象

    2. NSValue

    NSNumber继承自NSValue。

    // 结构体--->OC对象

    CGPoint p = CGPointMake(10, 10);

    // 将结构体转为Value对象

    NSValue *value = [NSValue valueWithPoint:p];

    // 将value转为对应的结构体

    // [value pointValue];

    NSArray *array = @[value ];

    3. NSDate

    // 创建一个时间对象

    NSDate *date = [NSDate date];

    // 打印出的时候是0时区的时间(北京-东8区)

    NSLog(@"%@", date);

    NSDate *date2 = [NSDate dateWithTimeInterval:5 sinceDate:date];

    // 从1970开始走过的秒数

    NSTimeInterval seconds = [date2 timeIntervalSince1970];

    // [date2 timeIntervalSinceNow];

     

    //日期格式化

      NSString *time = @"2015/4/10 23:11";

      NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

    //y年M月d日 24时m分

      formatter.dateFormat = @"yyyy/MM/dd HH:mm";

      NSDate *date = [formatter dateFromString:time];

    本章学习总结:

      本章的主要学习了block,protocol协议和Foundation框架,其中重点是Foundation框架。需要我们平时多加练习,慢慢领会,因为Foundation是我们今后开发中非常重要的框架,必须我们熟练的掌握。

      本章主要分为三讲内容,第一讲主要学习了block,要掌握定义block变量,和利用block封装代码,熟练掌握block的基本定义规范以及使用。第二讲我们主要学习了protocol协议,要掌握协议的定义和如何遵守协议,协议方法声明的两个关键字要知道怎么使用。第三讲主要学习了Foundation框架,也是本章最重要的内容,总结了结构体、字符串、集合等不同的Foundation框架的使用,可能知识有点多,但需要多巩固练习,争取熟记下这些框架的内容。

     

     

     

  • 相关阅读:
    HDU 1863 畅通工程(Kruskal)
    HDU 1879 继续畅通工程(Kruskra)
    HDU 1102 Constructing Roads(Kruskal)
    POJ 3150 Cellular Automaton(矩阵快速幂)
    POJ 3070 Fibonacci(矩阵快速幂)
    ZOJ 1648 Circuit Board(计算几何)
    ZOJ 3498 Javabeans
    ZOJ 3490 String Successor(模拟)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
  • 原文地址:https://www.cnblogs.com/twcblog/p/4455168.html
Copyright © 2011-2022 走看看