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框架的使用,可能知识有点多,但需要多巩固练习,争取熟记下这些框架的内容。

     

     

     

  • 相关阅读:
    20121010 闲的慌的日子
    九月,桂花飘香的季节
    win7下控件(ActiveX)注册错误(0x80040200) 修正
    C#多线程技术(一)
    C#多线程技术(二)
    C++沉思录摘录(OOP部分)
    SVM入门教程
    是IE的bug还是Windows的bug?
    inno setup安装时不需要开始菜单项
    django本地局域网访问
  • 原文地址:https://www.cnblogs.com/twcblog/p/4455168.html
Copyright © 2011-2022 走看看