Objective C 学习笔记

前 言

终于还是选择了”挨踢”的路,经过一段时间的培训,本着自己的认识、分析和理解程度上不去做技术上的高手,记下笔记提高自己。

目 录

  • 第一讲 语言简介、类和对象、NSObeject、基础语法
  • 第二讲 方法(封装)、继承、多态
  • 第三讲 属性(property)、语法新特性
  • 第四讲 OC数据类之字符串(NSString、NSMutableString)、集合类之数组(NSArray、NSMutableArray)
  • 第五讲 OC集合类之字典(NSDictionary、NSMutableDictionary)、集(NSSet、NSMutableSet)
  • 拓展 NSValue\Copy\MutableCopy\NSRang
  • 第六讲 NSNumber NSNumberForMatter NSValue NSDate NSDateForMatter NSTimer等
  • 第七讲 内存管理
  • 第八讲 类目、延展、协议
  • 第九讲 单例、通知、代理引用传值
  • 第十讲 Block应用、RunTime讲解

第一讲 语言简介、类和对象、NSObeject、基础语法

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSLog(@"Hello, World!");
    }
    return 0;
}

import :(保证头文件只被包含一次)

1.检测重复,防止文件的重复拷贝

2.<> 导入系统头文件 “” 导入自定义头文件

3.Foundation是一个基本库,导入他才能使用NSLog();

4.导入Foundation的头文件( Foundation.h文件 )

@autoreleasepool//称之自动释放池

NSLog(@"Hello, World!");//类似于C语言的printf函数;

 1.NSLog添加了时间戳 :2016-05-20 19:44:10.366 OC第一讲[1441:158586] Hello, World!
 2.打印的时候多了一个@符号
 3.自动换行
类(class):对一类事物抽象的描述(抽象)
对象(object):从以类食物中具体刻画出来的一个实例(具体);

第二讲 方法(封装)、继承、多态

封装方法:封装可以隐藏实现细节,使得代码模块化
  封装:只要是对成员变量的封装,例如setget方法

set方法的作用:提供一个方法给外界设置成员变量
    命名规范:
    1.方法必须set开头
    2.set后面跟上成员变量的名称(去掉下划线,成员变量的首字母大写
    3.返回值一定是void
    4.一定要接收一个参数,而且参数和成员变量类型一致
    5.形式参数的名称不能和成员变量一样

get方法的作用:返回对象内部成员变量的值
    命名规范:
    1.方法名和去掉下划线的成员变量名一样
    2.不能添加get关键字
    3.肯定有返回值,而且返回值的类型和成员变量的类型一致
    4.不接受任何参数
继承:可以扩展已存在的代码模块(类)
  1.抽取重复的代码
  2.建立类与类之间的关系
  3.子类阔以拥有父类的所有变量和方法
封装、继承的的目的都是为了——代码重用
多态:实现接口重用,为了类在继承和派生的时候,保证使用”家谱”中任意一类实例的某一属性时的正确调用

说明: DOG 继承于 Animal (Animal 拥有eat的属性、DOG 拥有run的属性)

#pragma mark --多态
        Animal *animal = [[DOG alloc]init];
        [animal eat];//调用方法会检测对象的真实形象 
        //1.父类的指针可以指向子类的对象,但是不能指向子类的对象
        //2.父类类型的变量不能调用子类的方法
/* 多态: 不同对象对同一消息的不同反应 */
//强转
        DOG *dog = (DOG *)animal;
        [dog run];
//索引找到 继承父类的方法
//如果父类定义的方法,在子类可以不用写,如在DOG类能调用Animal类中的run
**************************************************************
#import <Foundation/Foundation.h>

@interface Animal : NSObject
- (void) eat;
@end
*************************************************************
#import "Animal.h"

@interface DOG : Animal
-(void)run;

@end  
*************************************************************
@implementation DOG
-(void)eat{
 NSLog(@"dog love bone");
}
-(void)run{
 NSLog(@"I can run");
}

@end
注意:子类需重新实现父类的方法,并覆盖父类以前的做法,需要重写Setter方法

1.父类方法必须声明

2.调用方法的时候,子类优先找当前类的方法,如果找不到则寻找父类的方法

3.缺点:耦合性太高

继承使用的场合:
当A类完全拥有或者部分拥有B类中的属性和方法,可以让B类继承

 -(void)sayHi{
    [super sayHi];//直接调用父类中的某个方法
    NSLog(@"I am a stduent,my name is %@",_name);
}
    super作用:
        1.直接调用父类的方法
        2.super在对象方法中,那么就会调用父类中的对象方法,在父类中,会调用父类的方法
        3.使用场合:子类重写父类的方法同时想保留父类的一些行为
        [super 方法名]//调用父类方法

     self的用法:
        1.谁点用了当前方法,self就代表谁
        2.self在对象方法中就代表当前对象
        3.self在类方法中,代表当前类
        [self 方法名] //调用对象方法
实例化方法和类方法(便利构造)

‘_’(减号开头)实例化方法

1.只能由对象调用
2.对象方法中能访问当前对象的成员变量

‘+’(加号开头)类方法

1.只能由类调用
2.类方法中不能访问成员变量

类方法的使用场合(注:类方法可以和实例方法同名)

1.不依赖对象,执行效率高
2.当方法内部不许需要成员变量的时候,阔以使用类方法

第三讲 属性(property)、语法新特性

iOS 4.4之前,只会帮助setter和getter方法的声明
在头文件中声明 @property NSString *name;

属性:在iOS5之前写属性
1.先写出带下划线的成员变量
2.使用@property关键字匹配一个不带下划线的与成员变量同名的属性
3.使用@synthesize将成员变量和属性进行合并
//@synthesize name = _name;

@property (nonatomic, strong) <#NSString#> *<#NSString#>;
 属性优点:  
    1.自动声明一个带下划线的成员变量
    2.自动声明和实现成员变量对应的setter和getter方法

第一类:内存管理相关
    assign:缺省值,修饰基本数据类型和delegate
    retain:对象类型 在MRC手动管理内存
     copy:对象类型 (在遵守<NSCopying>情况下)
第二类:线程相关
     atomic:关心线程安全,通常用于多线程中
    nonatomic:不用去关心线程安全,通常用于单线程
第三类:
    readwrite:读写
    readonly:只读,只提供getter方法,不提供setter方法
第四类:
    nullable:表明这个属性的值可以为nil,对应swift中name?
     nonull:不为nil,如果传一个nil的指针,将会收到编译器的警告
     null_resettable:stter 可以为空
     null_unspecified:是否为nil不确定
//@property (nonatomic, strong, nullable) NSString *name;
//nullable 只要属性加了这个关键字,以后相同类型的属性都需要加这个关键字

 stter ,getter = 重新定义setter和getter的方法名。

第四讲 OC数据类之字符串(NSString、NSMutableString)、集合类之数组(NSArray、NSMutableArray)

  • pragma mark –NSString
        //字符串创建
        /* 1.stringWithFormat 2.stringWithString 3.stringWithCharacter:lenth */
        NSString *string = [[NSString alloc] init];//不推荐使用
        NSString *string1 = [[NSString alloc] initWithFormat:@"jack %@", string];

        NSString *string2 = [NSString stringWithFormat:@"123%@",string1];
        NSLog(@"%@",string2);

        ===============================================================

        //字符串的拼接
        /* 1.stringByAppendingString 2.stringByAppendingFormat */
        NSString *string = @"123";
        NSString *string2 = @"456";

        NSString *string3 = [string stringByAppendingString:string2];

        NSLog(@"%@", string3);

        string3 = [string3 stringByAppendingFormat:@"%@", string3];

        NSLog(@"%@", string3);

        ===============================================================

        //字符串的截取
        /* *subStringFromIndex; index为截取的开始位置的下标 *subStringToIndex; *subStringWithRange; */

        NSString *string = @"abcde";
        //练习:将“abcde”中的de去掉
        //string = [string substringToIndex:3];
        NSString *string2 = [string substringToIndex:2];
        NSString *string3 = [string substringFromIndex:4];
        string = [string2 stringByAppendingFormat:@"%@",string3];
        NSLog(@"%@", string);

        //练习:“hello word”的字符串通过截取变成“hd”
        NSString *string4 = @"hello word";

        string4 = [[string4 substringToIndex:1] stringByAppendingFormat:@"%@",[string4 substringFromIndex:string4.length - 1]];
        NSLog(@"%@", string4);

        ===============================================================

        //字符串查询(查找字符串cd)
        NSString *string = @"abcde";
        NSRange range =[string rangeOfString:@"cd"];
        if (range.location == NSNotFound && range.length ==0)
        {
             NSLog(@"Not Found!");
        }else{
            NSLog(@"Found the string!");
        }
        BOOL result = [string containsString:@"cd"];
        if (result == YES) {
              NSLog(@"Result=%hhd Found the string!",result);
        }

        ===============================================================

        NSString *str = @"baidu.com";
        // 查询前缀
        if ([str hasPrefix:@"http://"]) {
            NSLog(@"str has prefix 'http://'.");
        }else {
            NSLog(@"str has not prefix 'http://'.");
        }

        // 查询后缀
        if ([str hasSuffix:@"com"]) {
            NSLog(@"str has suffix 'com'.");
        }else {
            NSLog(@"str has not suffix 'com'.");
        }

       ===============================================================

        //字符串替换(替换cd改成CD)
        NSString *string = @"abcdecd";
        NSString *stringResult = [string stringByReplacingCharactersInRange:NSMakeRange(2, 2) withString:@"CD"];//根据范围替换
        NSLog(@"%@",stringResult);

        NSString *stringResult1 = [string stringByReplacingOccurrencesOfString:@"cd" withString:@"CD"];//全部替换
        NSLog(@"%@",stringResult1);

        ===============================================================
        // 字符串比较

          /* * 字符串比较: * isEqualToString: 判断字符串是否相同 * compare: 字符串比较 * compare: option: 字符串比较(可定义比较模式) */


        NSString *string = [NSString stringWithFormat:@"1232"];
        NSString *string1 = [NSString stringWithFormat:@"1234"];
        // 法一:
        BOOL resultString = [string isEqualToString:string1];
        if (resultString == 1) {
            NSLog(@"the same");
        }
        // 法二:
       NSComparisonResult result = [string compare:string1 options:NSNumericSearch | NSCaseInsensitiveSearch];
        if (result == NSOrderedAscending)//升序
        {
                NSLog(@"srtring1 is bigger than string!!");
        }else if (result == NSOrderedDescending)//降序
        {
                NSLog(@"srtring is bigger than string1!!");
        }else//相等
        {
                NSLog(@"the same!!");
        }
         ===============================================================
         // NSComparisonResult:比较结果枚举类型,NSStringCompareOptions比较策略枚举类型
         // NSNumericSearch :比较字符串长度
         // NSCaseInsensitiveSearch: 大小写不敏感比较
         // NSLiteralSearch : 完全比较,比较大小写

            string1 = [NSString stringWithFormat:@"1234"];
         string2 = [NSString stringWithFormat:@"123"];

         NSComparisonResult result = [string1 compare:string2 options:NSNumericSearch | NSCaseInsensitiveSearch];

         if (result == NSOrderedSame) {
             NSLog(@"the strigns are same.");
         }else if (result == NSOrderedAscending) {
             NSLog(@"string1 is less than string2.");
         }else if (result == NSOrderedDescending) {
             NSLog(@"string1 is bigger than string2.");
         }

        ===============================================================
        /* 1.length:获取长度 2.integerValue,floatValue,doubleValue:简单数据类型的转换 3.uppercaseString,lowercaseString,capitalzedString:字符串大小写转换 */
        ===============================================================
        //数值转换
        int a =234;
        NSString *numberString = [NSString stringWithFormat:@"%d",a];
        int number = [numberString intValue];
        NSInteger number2 = [numberString integerValue];
        float number3 = [numberString floatValue];
        double number4 = [numberString doubleValue];

        ===============================================================
        // 大小写转换
        NSString *string = @"hello word";
        NSLog(@" string = %@",string);
        NSString *string1 = [string uppercaseString];
        NSLog(@"string1 = %@",string1);
        NSString *string2 = [string1 lowercaseString];
        NSLog(@"string2 = %@",string2);
        NSString *string3 =[string capitalizedString];//单词首字母大写
        NSLog(@"string3 = %@",string3);
  • pragma mark –NSMutableString可变字符串
      //增、删、改、插
        NSMutableString *string = [NSMutableString stringWithFormat:@"123"];
        [string appendFormat:@"456"];//拼接
        NSLog(@"%@",string);
        [string appendString:string];
        NSLog(@"%@",string);//123456123456

        [string insertString:@"a" atIndex:3];//在某个下标位置插入字符
        NSLog(@"%@",string);
        [string deleteCharactersInRange:NSMakeRange(4, 3)];//删除
        NSLog(@"%@",string);

        [string replaceCharactersInRange:NSMakeRange(0, 3) withString:@"ABC"];//更改
        NSLog(@"%@",string);
  • pragma mark –NSArray
//C语言
//int a[5] = {1,2,3,4,5};//相同类型集合

        //oc语言数组
        //数组初始化
        //一般初始化方式
        NSArray *array = [[NSArray alloc]initWithObjects:@"123",@(34),@"567", nil];
        //便利初始化
        NSArray *array1 = [NSArray arrayWithObject:@"jack"];//一个对象自动添加nil
        NSArray *array2 = [NSArray arrayWithObjects:@"tom",@(123) ,nil];
        //快速初始化(ios5以上)
        NSArray *array3 = @[@"2",@"5",@"nice"];//对象自动添加nil
         数组取值:
         //objectAtIndex: //取出某一下标对应的元素
         //lastObject: //取出最后一个元素
         //firstObject: //取出第一个元素

        NSArray *array = [NSArray arrayWithObjects:@"1",[NSString stringWithFormat:@"2"],[NSNumber numberWithInt:3], nil];
        NSLog(@"%@",array);//数组外层有小括号
        id object = [array objectAtIndex:1];//NSString *string = [array objectAtIndex:1]

        id firstObject = [array firstObject];
        NSLog(@"firstObject:%@",firstObject);
        id lastObject = [array lastObject];
        NSLog(@"lastObject:%@",lastObject);
        NSLog(@"object:%@",object);

        NSArray<NSString *> *strings = @[@"1",@"2",@"3"];
        NSLog(@"%@",strings);
        NSLog(@"%ld",strings.firstObject.length);
        NSDictionary<NSString *,NSNumber *> *dict =@{@"a":@(1),@"b":@(2),@"c":@(3)};
        NSLog(@"%@",dict);

  • pragma mark –NSMutableArray
        NSMutableArray ->数组运算: *增   *删  *改  *查  *排序
         ===============================================================

         NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"4", nil];
        //增加:addObject:(一定不能添加一个空对象)
        [mutableArray addObject:@"5"];
        //删除
        [mutableArray removeObject:@"4"];//删除4这个对象
        [mutableArray removeObjectAtIndex:2];//删除下标对象
        //查
        NSInteger index = [mutableArray indexOfObject:@"2"];
        //修改
        [mutableArray replaceObjectAtIndex:2 withObject:@"30"];
        //排序
        [mutableArray sortedArrayUsingSelector:@selector(compare:)];


         ===============================================================

        NSArray *array = [NSArray arrayWithObjects:@"1",@"13",@"4",@"56", nil];
        NSLog(@"%@",array);
        //增加元素
        NSArray *newArray = [array arrayByAddingObject:@"23"];
        NSLog(@"%@",newArray);
        //查找某一个元素坐在的下标
        NSInteger index = [array indexOfObject:@"56"];
        NSLog(@"%d",(int)index);
        //排序 sortedArrayUsingSelector
        //方法选择器+方法 :@selector(compare:)
        NSArray *sorteArray = [array sortedArrayUsingSelector:@selector(compare:)];
        NSLog(@"%@",sorteArray)

         ===============================================================

        //3种便利数组元素方式
        //getter和点语法都阔以

        //循环便利
        for (int i = 0 ; i<array.count; i++) {
            NSLog(@"循环便利:%@",[sorteArray objectAtIndex:i]);
        }

        //快速枚举 for-in 适用于不需要知道元素下标
        for (NSString *string in sorteArray) {
            NSLog(@"快速枚举:%@",string);
        }

        //block enumerateObjectsUsingBlock 两次回车符 可以将一串代码作为值
        [sorteArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            //obj:返回的下标对应的参数
            //idx:下标位置
            NSLog(@"block:%@ index:%lu",obj,idx);
            if (idx == 2)//下标等于2中断循环
            {
                *stop = YES;
            }
        }];

        ===============================================================
        //Array数组元素排序(排序条件)
        //声明数组有年龄和姓名
        // 1. (排序条件)
        NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"_age" ascending:YES];//按年龄排
        NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//按名字排
        // 2. 先按年龄排,再按名字排
        [Array sortUsingDescriptors:@[sortDescriptor1,sortDescriptor2]];
    //练习:
        NSArray *array1 = [NSArray arrayWithObjects:@"123",@"234",@"78",nil];
        NSLog(@"array1 = %@",array1);
        NSArray *array2 = [NSArray arrayWithObject:array1];
        NSLog(@"array2 = %@",array2);
        NSArray *array3 = [NSArray arrayWithObjects:@"789",array2, nil];
        NSLog(@"array3 = %@",array3);
        NSLog(@"%@",array3[0]);
        NSLog(@"%@",array3[1][0][2]);//从array3种取出array1的第2个元素

        array3 = ( 789, ((123,234,78)))

        ===============================================================
     //练习:举例 @[@"1",@"2",@"3",@"4",@"5"] 移除数组中大于3的元素

        NSArray *array = @[@"1",@"2",@"3",@"4",@"5"];
        NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
        NSMutableArray *removeArray = [[NSMutableArray alloc]init];//用来记录要被删的元素
       // 在遍历集合的时候不能对集合的对象元素进行改变
        for (NSString *string in array) {
            if ([string integerValue] > 3) {
                [removeArray addObject:string];
            }
        }
        [mutableArray removeObjectsInArray:removeArray];
        NSLog(@"%@",mutableArray);


        ===============================================================
    //练习: 
        NSString *string = @"123-456-789-000";
        NSArray *array =[string componentsSeparatedByString:@"-"];
        NSLog(@"%@",array);
        //(123,456,789,000)

        string =[array componentsJoinedByString:@"+"];
        NSLog(@"%@",string);
        //123+456+789+000

      ===============================================================
    //练习: 对一个已知的NSMutableArray数组进行冒泡排序 
       NSMutableArray *array = [NSMutableArray arrayWithObjects:@"7",@"3",@"5",@"2",@"4",@"6",@"1", nil];
        for (int i = 0; i<array.count-1; i++)
        {
            for (int j = 0; j <array.count-1-i; j++)
            {
                if ([array[j] integerValue] > [array[j+1] integerValue]  )
                {
                    [array exchangeObjectAtIndex:j withObjectAtIndex:j+1];
                      NSInteger num = [array[j] integerValue];
                      NSInteger num1 = [array[j+1] integerValue];
                      if (num >num1)
                       {
                          [array exchangeObjectAtIndex:j withObjectAtIndex:j+1];
                         }
            }
        }NSLog(@"%@",array);

第五讲 OC集合类之字典(NSDictionary、NSMutableDictionary)、集(NSSet、NSMutableSet

  • pragma mark –NSDictionary
        /* 字典以键值对的方式进行存储,无序 例如:key ->value 初始化方式: */

         //一般初始化:alloc + initWithObjectsandKeys

        NSDictionary *dictionary = [[NSDictionary alloc]initWithObjectsAndKeys:@"first",@(1),@(2),@"second",@(4),@"four",nil];
        NSLog(@"%@",dictionary);

        //便利初始化:dictionaryWithObjectAndKeys
        //便利构造(ios5)----快速构造方式,成对出现:前键 后值 返回的是不可变字典
        NSDictionary *newdictionary = @{@"fist":@(1),@"second":@(2)};
        NSLog(@"%@",newdictionary);

        /* 字典的常规方法 1.查询某个对象:ObjectForKey: 2.取出所有键值:allkeys 3.取出所有value:allValues数组 */

        //1.查
        NSString *string = [dictionary  objectForKey:@"first"];//取出key做对应的对象
        NSLog(@"%@",string);

        //2.字典里面所有键的集合
        NSArray *keys = [newdictionary allKeys];
        NSLog(@"%@",keys);

        //3.取出所有的值
        NSArray *value = [newdictionary allValues];
        NSLog(@"%@",value);

         ===============================================================
            字典的遍历练习
         ===============================================================
         NSDictionary *dictionary = @{@"name":@"jack",@"age":@(18),@"height":@"188",@"code":@"1555",@"sex":@"男"};

        //for循环 取出所有的KEY值
        NSArray *key = [dictionary allKeys];
        for (int i = 0; i < key.count; i++) {
            //1.取出键值
            NSString *keyString = key[i];
            NSString *value = [dictionary objectForKey:keyString];
            //NSString *value = dictionary[keyString];
        }
        NSLog(@"key1:%@",key);

        //for-in遍历
        for(NSString *key in dictionary){
            NSLog(@"key2:%@",[dictionary objectForKey:key]);
        }

       // key position -- value @{@"1":@"北京",@"2":@"重庆",@"3":@"成都"}
       // dictionary[@"position"][@"3"];
  • pragma mark –NSMutableDictionary
        /*
         *增:setObject:forkey
         *删:removeObjectforKey
         *查:objectForKey
         *改:setObject:forkey 覆盖指定key对应的值
         */

        NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc]init];
        //增:
        [mutableDict setObject:@"jack" forKey:@"name"];
        [mutableDict setObject:@"56" forKey:@"age"];
        [mutableDict setObject:@"188" forKey:@"height"];
        //删
        [mutableDict removeAllObjects];//删除所有
        [mutableDict removeObjectForKey:1];//删除KEY值对应的value key值也就不存在了
        //查找
        NSString *string = [mutableDict objectForKey:@"age"];
        //改:
        [mutableDict setObject:@"45" forKey:@"age"];
  • pragma mark –NSSet
  • NSSet简介

    • NSSet对象中不能存放重复对象,如果出现重复,最终只会保留一个,NSSet也常用来清除其他集合中的重复对象。

    • 集,类似数组,但区别于数组,其特点是:无序不重复;

    • 集分为可变集 NSSet 与不可变集 NSMutableSet;

  • 初始化

 // 1、alloc + init
        - (instancetype)initWithObjects:(ObjectType)firstObj, ... ;

// 2、遍历构造
        + (instancetype)setWithObjects:(ObjectType)firstObj, ...;

 ```
 * 常用方法
 ```
1、获取元素个数
- (NSUInteger)count;

2、获取任意元素
- (nullable ObjectType)anyObject;

3、获取所有元素
@property (readonly, copy) NSArray<ObjectType> *allObjects;

4、查询是否包含某一元素
- (BOOL)containsObject:(ObjectType)anObject; 
 ```

 * ___pragma mark --NSMutableSet___
 * 常用方法

// 1、添加元素
- (void)addObject:(ObjectType)object;

// 2、删除元素
- (void)removeObject:(ObjectType)object;

拓展 NSValue\Copy\MutableCopy\NSRang

  • pragma mark –NSValue

    • 数值对象,用于复杂数据类型的对象化封装,如结构体;

    • NSValue 对自定义结构体类型的初始化

 // 1、结构体类型声明
        typedef struct {
             char name[81];
             int  age;  
        }Person;
// 2、声明结构体变量并初始化

        Person person = {"Charles", 21};
// 3、封装

        NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];
// 4、解封装

        Person newPerson;
        [value getValue:&newPerson];
        NSLog(@"<%p 姓名:%s 年龄:%d>", &newPerson, newPerson.name, newPerson.age);

 ``` 
  简单结构体类型转换为对象类型
    //便利结构初始化
    NSValue *Value = [NSValue valueWithPoint:NSMakePoint(4, 5)];
    NSLog(@"%@",Value);
    //打印:NSPoint: {4, 5}

    NSValue *sizeValue = [NSValue valueWithSize:NSMakeSize(34, 568)];
    NSLog(@"%@",sizeValue);
    //打印:NSSize: {34, 568}


    NSValue *rectValue = [NSValue valueWithRect:NSMakeRect(3, 5, 6, 678)];
    NSLog(@"%@",rectValue);
    //打印:NSRect: {{3, 5}, {6, 678}}


    //便利解封装
    NSPoint point = [Value pointValue ];
    NSString *str1 = NSStringFromPoint(point);
    NSLog(@"point is %@",str1);

    NSSize size = [sizeValue sizeValue];
    NSString *str2 = NSStringFromSize(size);
    NSLog(@"point is %@",str2);

    NSRect rect = [rectValue rectValue];
    NSString *str3 = NSStringFromRect(rect);
    NSLog(@"point is %@",str3);
  • pragma mark –Copy
        NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
        NSArray *newArray = [array copy];
        NSLog(@"%p %p",array,newArray);
        //结论:copy对于不可变对象,是指针复制,也成为浅复制

        NSMutableString *mutableString = [NSMutableString stringWithFormat:@"34"];
        NSMutableString *newMutableStr =[mutableString copy];
        NSLog(@"%p %p",mutableString,newMutableStr);
        //结论:copy作为可变对象,是内容复制,也成为深复制。但是复制之后的字符串变成了一个不可变的字符串;
  • pragma mark –MutableCopy
        NSMutableArray *mutableArray = [@[@"123",@"456"] mutableCopy];
        [mutableArray addObject:@"789"];
        //NSLog(@"%@",mutableArray);

        NSString *string = [NSString stringWithFormat:@"AAA"];
        //NSString *newStr = [string mutableCopy];
        NSMutableString *newStr = [string mutableCopy];
        [newStr appendFormat:@"BBB"];
        NSLog(@"%p %p",string,newStr);

        NSMutableString *newStr2 = [newStr copy];

// mutableCopy:对于可变或者不可变对象mutableCopy都是深复制(开辟新的内存,内容复制),且开辟的新内容都是可变的
        NSMutableString *str = [@"123" mutableCopy];
  • pragma mark –NSRange
    • C 语言使用结构体、指针和数组来构造复杂的数据类型,而结构体和指针在iOS编程中至关重要,Cococa为我们准备了与字符串操作有关的结构体NSRange:
// NSRange:用来表示相关事物的范围 
typedef struct _NSRange 
{ 
    unsigned int location;     //location表示起始位置
    unsigned int length;       //length表示长度
 }
 ```

* NSRange有三种创建方式:

比如要得到字符串@“helloRIMIOnline”中@“Online”字符串,需要一个起始位置为9,6个长度的范围,它可以有三种方式创建:

它可以有三种方式创建:

  • 第一种调用函数可以这么写:
    NSRange range = NSMakeRange (9,6);

  • 第二种直接给成员赋值:
    NSRange range;
    range.location = 9;
    range.length = 6;

  • 第三种应用C语言的聚合结构赋值机制:
    NSRange range = {9,6};

第六讲 NSNumber NSNumberForMatter NSValue NSDate NSDateForMatter NSTimer等

  • pragma mark –NSNumber

  • 数值对象,用于简单数据类型的对象化封装,继承与 NSValue;

  • NSNumber的初始化

        NSNumber *number1 = [NSNumber numberWithInt:5];
        NSNumber *number2 = [NSNumber numberWithFloat:5];
        NSNumber *number3 = [NSNumber numberWithDouble:5.0f];
  • NSNumber 比较
    NSNumber *number = @(10);
    NSNumber *antherNumber = @(10);

// 1、判断是否相等
    BOOL isEqual = [number isEqualToNumber:antherNumber];

// 2、比较大小
    NSComparisonResult result = [number compare:antherNumber];

    // NSOrderedAscending(-1):升序
    // NSOrderedSame(0) :相等
    // NSOrderedDescending(1):降序

    if (result == NSOrderedAscending) {
        NSLog(@"number < antherNumber");
    }else if (result == 0) {
        NSLog(@"number = antherNumber");
    }else {
        NSLog(@"number > antherNumber");
    }
        NSNumber *number = [NSNumber numberWithInt:4];
        NSLog(@"%@",number);//4
        //便利写法
        NSNumber *floatNumber = @(4.6);
        NSLog(@"%@",floatNumber);//保留有效位数 4.6
        CGFloat num = floatNumber.floatValue;
        NSLog(@"%f",num); //4.6

        NSNumber *number1 = [NSNumber numberWithFloat:3.05];
        NSLog(@"%@",number1);//3.05
  • pragma mark –NSNumberFormatter

  • 使用 NSNumberFormatter 对 NSNumber 与 NSString 相互转化

  • NSNumberFormatterStyle

    1、NSNumberFormatterScientificStyle: 1.23456E5
    2、NSNumberFormatterPercentStyle: 12,345,600%
    3、NSNumberFormatterCurrencyStyle: ¥ 123,456.00
    4、NSNumberFormatterDecimalStyle: 123,456
    5、NSNumberFormatterNoStyle: 123456
    ===========================================================

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSNumber *number = @(12345);
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];

        // 设置样式 
        [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];

        // 据样式将 number 转换成字符串
        NSString *numberString = [formatter stringFromNumber:number];

        NSLog(@"number string = %@", numberString); // 输出 number string = ¥ 123,45.00
    }
    return 0;
}
        NSNumber *number = @(123456);//将数字转换成文字
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
        formatter.numberStyle = kCFNumberFormatterSpellOutStyle;
        NSString *string = [formatter stringFromNumber:number];
        NSLog(@"%@",string);//十二万三千四百五十六
  • pragma mark –NSValue

  • 数值对象,用于复杂数据类型的对象化封装,如结构体;


// 1、结构体类型声明

    typedef struct {
        char name[81];
         int  age;  
    }Person;

// 2、声明结构体变量并初始化

    Person person = {"Charles", 21};

// 3、封装

    NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];

// 4、解封装

    Person newPerson;
    [value getValue:&newPerson];
    NSLog(@"<%p 姓名:%s 年龄:%d>", &newPerson, newPerson.name, newPerson.age);
  • pragma mark –NSdDate
//区别:NSData
         /* * NSDate 的初始化 * date 获取当前系统时间,默认为格林威治时间,比北京时间早8小时 * dateWithTimeInterval:3600 sinceDate: 使用一个传入的时间作为参照,加上偏移时间间隔(秒) * dateWithTimeIntervalSince1970: 使用1970-01-01的时间作为参照,加上偏移时间间隔(秒) * dateWithTimeIntervalSinceNow: 使用当前的时间作为参照,加上偏移的时间间隔(秒) * dateWithTimeIntervalSinceReferenceDate: 使用2001-01-01的时间作为参照,加上偏移的时间间隔(秒) */

        //NSDate的初始化
        NSDate *date = [NSDate date];
        NSLog(@"date=%@",date);//date=2016-05-21 09:40:55 +0000 

        //传入的日期加上偏移量(时区+8)
        NSDate *date1 = [NSDate dateWithTimeInterval:3600*8 sinceDate:date];
        NSLog(@"date1=%@",date1);//date1=2016-05-21 17:40:55 +0000

        //以2001-1-1时间作为参照,在加上偏移量
        date1 = [NSDate dateWithTimeIntervalSinceReferenceDate:7200];
        NSLog(@"date1=%@",date1);//date1=2001-01-01 02:00:00 +0000 

        //使用date获取时间间隔
        NSTimeInterval time = [date timeIntervalSinceDate:date1];
        NSLog(@"time=%lf",time);
        time = [date timeIntervalSince1970];
        time = [date timeIntervalSinceReferenceDate];
        time = [date timeIntervalSinceNow];

        //NSDate的的比较

        NSComparisonResult result = [date compare:date1];
        NSLog(@"%ld",(long)result);
        BOOL result1 = [date isEqual:date1];
        NSLog(@"%d",result1);

        //比较2个日期,返回较小的那个
        NSDate *earlierDate = [date earlierDate:date1];
        NSLog(@"%ld",(long)earlierDate);

       //比较2个日期,返回较小那个
        NSDate *laterDate = [date laterDate:date];
        NSLog(@"%ld",(long)laterDate);
  • pragma mark –NSDateFormatter
        NSDate *date = [NSDate date];
        NSLog(@"初始化:%@",date);

        NSDateFormatter *formatter = [[NSDateFormatter alloc]init];//创建一个格式转换器对象
        [formatter setDateFormat:@"yyyy年mm月dd日 hh:mm:ss"];//设置自定义格式
        [formatter setDateStyle:NSDateFormatterMediumStyle];//系统定义日期样式
        [formatter setTimeStyle:NSDateFormatterMediumStyle];//系统定义时间样式

        NSString *dateString = [formatter stringFromDate:date];//自定义
        NSLog(@"dateString1 : %@",dateString);

        //类方法 获取当地时间字符串
        dateString = [NSDateFormatter localizedStringFromDate:date
                                                    dateStyle:NSDateFormatterMediumStyle
                                                    timeStyle:NSDateFormatterMediumStyle];
          NSLog(@"dateString2 : %@",dateString);
        //获取当前时区
        NSTimeZone *zone = [NSTimeZone systemTimeZone];
        NSInteger interval =[zone secondsFromGMTForDate:date];
        date = [date dateByAddingTimeInterval:interval];
        NSLog(@"当前时区:%@",date);

=============================打印输出结果==================================
2016-05-21 17:51:08.623 3.24练习[7214:232131] 初始化:2016-05-21 09:51:08 +0000
2016-05-21 17:51:08.624 3.24练习[7214:232131] dateString1 : 2016521日 下午5:51:08
2016-05-21 17:51:08.624 3.24练习[7214:232131] dateString2 : 2016521日 下午5:51:08
2016-05-21 17:51:08.624 3.24练习[7214:232131] 当前时区:2016-05-21 17:51:08 +0000
  • 通过NSCalendar类来创建日期
    NSDateComponents * comp = [[NSDateComponents alloc]init];
    [comp setYear:1993]; // 设置年
    [comp setMonth:7];  // 设置月
    [comp setDay:16]; // 设置日

    [comp setHour:9]; // 设置时
    [comp setMinute:14]; // 设置分
    [comp setSecond:0];// 设置秒

    NSCalendar * myCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    NSDate * myDate = [myCal dateFromComponents:comp];

    NSLog(@"%@", myDate);

第七讲 内存管理

  • pragma mark –普通情况下的内存管理
        Person *person = [[Person alloc]init];
        NSLog(@"%ld",[person retainCount]);//1
        // retainCount 用来记录对象的引用计数,所以不会对对象的引用计数产生影响
        [person retain];//2
        NSLog(@"%ld",[person retainCount]);
        [person release];//1
        NSLog(@"%ld",[person retainCount]);
        [person release];// 0 延时调用
        NSLog(@"%ld",[person retainCount]);//1?
        [person release];
  • pragma mark –自定义初始化中的内存管理
        //内存管理原则
        //1.谁alloc 谁release;
        //2.每一个alloc 对应一个release;
        NSString *name = [[NSString alloc]initWithFormat:@"rimi"];
        Person *person = [[Person alloc]initWithName:name code:@"234" age:34];
        [name release];
        [person release];
        NSLog(@"%ld",[name retainCount]);
        NSLog(@"%ld",[person retainCount]);
  • pragma mark –set方法中的内存管理
         BOOK *book1 = [[BOOK alloc]init];//1
        Person *person = [[Person alloc]init];

        [person setBook:book1];//2
        [person setBook:book1];//3

        BOOK *book2 = [[BOOK alloc]init];
        [person setBook:book2];

        [book1 release];//1
        NSLog(@"book1=%ld",[book1 retainCount]);
        [person release];//0
        NSLog(@"book2=%ld",[book2 retainCount]);
        NSLog(@"person=%ld",[person retainCount]);

        NSMutableString *mutable = [[NSMutableString alloc]initWithFormat:@"123"];
        //NSString *string = [mutable retain]; //retain关键字赋值指针 内容不变
        NSString *string = [mutable copy];//copy关键字赋值内容
        [mutable appendFormat:@"456"];
        NSLog(@"%@ %@",mutable,string);
  • pragma mark –便利构造中的内存管理
        NSString *name = [NSString stringWithFormat:@"123"];
        Person *person = [Person personWithName:name code:@"123" age:34];
        //[person release];//错误 便利构造方法初始化对象 应减少一次release 因为在内方法中alloc已经对应一个autorelease
        //[name release];//错误
        NSArray *array = [NSArray arrayWithObjects:@"1",@"2",nil];//便利构造方法不需要释放

    //Autorelease 的基本方法
        //1.会将对象放在自动释放池中
        //2.当自动释放池被销毁的时候,会对池中所有的对象进行一次release
        //3.刚调用Autorelease的时候,引用计数是不会发生改变的
        //4.Autorelease好处 不用关心对象被销毁的时间
        //5.Autorelease一般用在内存较小的时候

        //特别注意:便利构造方法初始化对象 应减少一次release 因为在内方法中alloc已经对应一个autorelease
  • pragma mark –集合类中的内存管理
     //一个对象加入到数组中 retaincount+1 不影响集合类的retaincount

        Person *person1 = [[Person alloc]init];
        NSArray *array = [NSArray arrayWithObjects:person1, nil];
        NSLog(@"person1 retainCount = %ld",[person1 retainCount]);
        NSLog(@"array retainCount = %ld",[array retainCount]);

        [array retain];
        NSLog(@"array retainCount = %ld",[array retainCount]);
    //数组中的retaincount+1 不影响数组中的元素
        [array release];
        NSLog(@"array retainCount = %ld",[array retainCount]);

        =====================================================================

        //当集合对象的呗销毁的时候,集合类的元素会进行一次release操作:releasecount-1
        Person *person1 = [[Person alloc]init];
        NSArray *array = [[NSArray alloc]initWithObjects:person1, nil];

        [array retain];
        [array release];
         //[person1 release];
        NSLog(@"array retainCount = %ld",[array retainCount]);
        NSLog(@"person1 retainCount = %ld",[person1 retainCount]);
  • pragma mark –循环引用(dog类)
        /* 1.循环引用解决方案 使用@class 关键字导入类,如果需要导入类的属性或者方法,在实现的。m文件里导入该类的头文件; 2.将其中的一个对象改为弱引用,dealloc方法不在释放该对象 */
        Person *per1 = [[Person alloc]init];//1
        Dog *dog1 = [[Dog alloc]init];//1
        per1.dog = dog1;//2
        dog1.person = per1;//2

        [per1 release]; //per1=1 dog1=2
        NSLog(@"per1 = %ld dog1 = %ld",[per1 retainCount],[dog1 retainCount]);
        [dog1 release];
        NSLog(@"per1 = %ld dog1 =%ld",[per1 retainCount],[dog1 retainCount]);
  • pragma mark –异常情况
        //1.混乱释放
        Person *person1 = [[Person alloc]init];
        Person *person2 = person1;
        //[person2 release];//错误 不遵守内存管理原则
        [person1 release]; //谁创建 谁release

  =====================================================================

        //2.内存泄露
        Person *per1 = [[Person alloc]init];
        Person *per2 = [[[Person alloc]init]autorelease];
        per2 = per1;
        [per1 release];
        //[per2 release];//错误 造成过度释放 解决办法:增加自动释放

  ===================================================================

        //3.过度释放
        Person *person = [Person personWithName:@"rimi" code:@"1001" age:23];
        //[person release]; 错误 便利构造的对象不需要多余的release

  =====================================================================

        //4. nil 对象的引用计数为0
        Person *pernson = nil;
        NSLog(@"%ld",[pernson retainCount]);

  =====================================================================

        //5.常量对象的引用计数为无穷
        NSString *string = @"123";
        NSString *string1 = [NSString stringWithString:string];
        NSLog(@"%ld",[string1 retainCount]);

第八讲 类目、延展、协议

暂无

第九讲 单例、通知、代理引用传值

  • 单例
        //单例在程序的运行中只会被分配一次
        //可以在程序的任何一个地方都可以访问和修改它
        //单例的生命周期和程序的生命周期一样的
        //单例是用类方法创建 

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

        [userDefaults setObject:@"no" forKey:@"取消"];//存储

         NSString *string = [userDefaults objectForKey:@"取消"];
        NSLog(@"---%@",string);

        if ([string isEqualToString:@"yes"])
        {
            [userDefaults setObject:@"no" forKey:@"取消"];
        }
        else
        {
            [userDefaults setObject:@"yes" forKey:@"登录"];
        }
        NSLog(@"%@",[userDefaults objectForKey:@"登录"]);
        [userDefaults synchronize];//数据持久化

        //单例可以在程序的任何一个地方都可以访问和修改它
        [[NSUserDefaults standardUserDefaults]setObject:@"tom" forKey:@"name"];//存储
        [[NSUserDefaults standardUserDefaults]removeObjectForKey:@"name"];//删除
        [userDefaults synchronize];//数据持久化


        // NSUserDefaults 不能存储自定义对象 
  • 单例的实现举例
        // 简单单例的实现举例,创建一个Teacher单例 
        // 单例必须类方法创建
         Teacher *teacher = [Teacher defaultTeacher];
        第一步:在Teacher.h文件声明
        @interface Teacher : NSObject<NSCopying>//单例完整
        +(Teacher *)defaultTeacher;
        @end

        第二步:在Teacher.m文件实现
        //简单单例的实现 (保证对象的唯一性)
        //~~~~~~~~~~~~ 方法① ~~~~~~~~~~~~~~~~~~~~~~~~~~~
        static Teacher *teacher = nil;
        +(Teacher *)defaultTeacher
        {
          if (!teacher)
            {
                teacher = [[Teacher alloc]init];
                //(保证对象只被初始化一次)
            }
            return teacher;
        }

        //~~~~~~~~~~~~ 方法② ~~~~~~~~~~~~~~~~~~~~~~~~~~~
        static dispatch_once_t onceToken;
        static Teacher *teacher;
        +(Teacher *)defaultTeacher
        {
        _dispatch_once(&onceToken, ^{
            teacher = [[Teacher alloc]init];
        });
        return teacher;
        }

        //~~~~~~~~~~~~ 方法③ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
        static bool token = NO;
        static Teacher *teacher;
        +(Teacher *)defaultTeacher
        {
         if (!token) {
             token = YES;
                teacher = [[Teacher alloc]init];
            }

         return teacher;
        }

        //~~~~~~~~~~~~ 方法④ 完成单例的实现 ~~~~~~~~~~~~~~~
        /* 自定义单例创建完整方法: 1.遵守<NSCopying>协议 2.覆写copyWithZone:(NSZone *)zone/retain/release/autorelease/retainCount方法 */

        static Teacher *teacher;
        +(instancetype)allocWithZone:(struct _NSZone *)zone{
         @synchronized(self) {
                if (!teacher) {
                     teacher = [super allocWithZone:zone];
                    return teacher;
                }
                return nil;
            }
        }

        -(id)copyWithZone:(NSZone *)zone
        {
             return self;
        }

        -(instancetype)retain
        {
             return self;
        }

        -(instancetype)autorelease;
        {
            return self;
        }

        - (oneway void)release
        {

        }

        -(NSUInteger)retainCount
        {
             return NSUIntegerMax;
        }
  • 通知
发送通知

第一步:通知声明 声明两个字符串(示例)
        extern NSString *const TeacherAskQuestionNotification;
        extern NSString *const TeacherAskQuestionUserInfokey;
第二步:通知赋值
        NSString *const TeacherAskQuestionNotification = @"TeacherAskQuestionNotification";
        NSString *const TeacherAskQuestionUserInfoKey = @"TeacherAskQuestionUserInfoKey";
第三步:发送通知
    //postNotificationName:通知的名称
    //object:通知的发送者
    //userInfo:发送的信息,是以字典的方式发送
    [[NSNotificationCenter defaultCenter]postNotificationName:TeacherAskQuestionNotification//发送通知的名称(声明)
                                                       object:self//发送通知的对象
                                                     userInfo:@{TeacherAskQuestionUserInfoKey:question}];                                                 
===============================================================================
接收通知:

第一步:注册观察者,接收通知
        - (instancetype)initWithName:(NSString *)name
        {
             self = [super init];
                if (self) {
                _name =[name copy];
                //addObserver:观察者
                //selector:接受到通知之后 回调的方法(需要执行的方法)
                //name:通知的名称
                //object:设置为空
                [[NSNotificationCenter defaultCenter]addObserver:self
                                                selector:@selector(studentHasReceiveQuestion:)
                                                    name:TeacherAskQuestionNotification
                                                  object:nil];

    }
    return self;
}

第二步:接收到通知之后,回调的方法
        -(void)studentHasReceiveQuestion:(NSNotification *)notification{

            //获取老师发送的问题 通知发送的内容
             NSString *question = [notification.userInfo objectForKey:TeacherAskQuestionUserInfokey];
            NSLog(@"student name '%@' receive this question %@",_name,question);

            //回答老师的问题
            if (self.delegate && [self.delegate respondsToSelector:@selector(student:didFinishAnswerWithQuestionWithResult:)]) {
            [self.delegate student:self didFinishAnswerWithQuestionWithResult:_name];

            }
        }
第三步://移除通知
        - (void)dealloc
        {
            // ARC MRC都需要移除通知
            [[NSNotificationCenter defaultCenter]removeObserver:self];

            [_name release];
            [super dealloc];
        }
  • 代理、协议
 第一步:在.h文件定义协议的名字和方法(示例)
        @class DetailViewController;
        // 定义协议头
        @protocol DetailViewControllerDelegate <NSObject>
        // 协议方法(必须执行)
        @optional
        - (void)detailViewController:(DetailViewController *)Vc didClickButtonWithColor:(UIColor *)color;
        @end

 第二步:在.h文件定义协议代理的属性(用于关联代理)定义一个遵守协议的属性,称之为代理
        @property (nonatomic, weak) id<DetailViewControllerDelegate> btnDelegate;

 第三步:在.m文件实现给协议代理发送消息
        - (void)clickBtn:(UIButton *)btn {
            NSLog(@"%@",btn.backgroundColor);
        // 先要判断代理是否实现了协议方法
        if ([self.btnDelegate respondsToSelector:@selector(detailViewController:didClickButtonWithColor:)]) {
        // 有实现才正式发送消息给代理
        [self.btnDelegate detailViewController:self didClickButtonWithColor:btn.backgroundColor];
    }
        // 返回
        [self dismissViewControllerAnimated:YES completion:nil];
}
        ===============================================================================

代理的第一步:遵守协议
            @interface ViewController ()<DetailViewControllerDelegate>

代理的第二步:获得委托方(将自己作为委托方的代理)
        - (void)clickedNextBtn {
            NSLog(@"跳转到下一页");
            // 初始化控制器
            DetailViewController *detailVc = [[DetailViewController alloc] init];

            // 设置当前控制器为代理
            detailVc.btnDelegate = self;

            // 设置模态跳转动画模式
            detailVc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
            // 显示活动指示器
            [self.activityView startAnimating];
            // 模拟延时
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            // 模态跳转
             [self presentViewController:detailVc animated:YES completion:nil];

            // 跳转后关掉活动指示器
            [self.activityView stopAnimating];
            });
        }

代理的第三步:实现代理方法,获得参数 
        - (void)detailViewController:(DetailViewController *)Vc didClickButtonWithColor:(UIColor *)color {
         // 使用传回的颜色设置当前控制器视图的背景色
         self.view.backgroundColor = color;
        }

第十讲 Block应用、RunTime讲解

*___Block应用_

        ---------------------------------------------
        返回值类型   函数名    参数类型      调用
         void     (^print)    ()    =   ^(){}
        ---------------------------------------------

         --------------------------------------------
         //无返回值 无参数类型
         void (^print)()=^(){
            NSLog(@"I am student!");
        };
        print();//调用Block

        //打印:I am student!

        --------------------------------------------
       //定义一个block变量
        void (^printLines)(int number)=^(int number)
        {
            for (int i = 0; i<number; i++)
            {
                NSLog(@"----------------");
            }
        };
         printLines(5);

       //打印:五条线

       --------------------------------------------
       //练习:block计算2个数的和
        int (^sum1)(int,int)= ^(int a,int b)
        {
            return a+b;
        };
        NSLog(@"sum = %d",sum1(5,6));

      //打印:sum = 11

      --------------------------------------------
      //练习:指向函数的指针 (对比block) 注意此处sum的调用
        int (*p)(int,int) = sum;
        int number = p(4,5);
        NSLog(@"number: %d",number);


  • block访问外部变量
        //1.对于基本数据类型,调用的时候是拷贝的,可以访问外部变量,但是不能修改局部变量
        //2.若需要修改局部变量 应该加一个 __block关键字

        __block int number = 12; //__block关键字 表示同一个地址内存
         //int number = 12; // 两个number的地址不一样

        //定义一个变量
        void (^block)();// =12;
        block = ^(){
            number = 15;
            NSLog(@"number = %d",number);
        };// =15
        NSLog(@"block调用之前 number= %d",number);//=12

        number = 18;
        NSLog(@"18 => %d",number);//=18

        //调用block
        block();
        NSLog(@"block调用之后 number= %d",number);//15
        number = 28;
        NSLog(@" number= %d",number);        
  • block对于对象类型
        //相当于指针复制,指向同一块内部
        NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",nil];
        void (^myBlock)()=^(){
            [array addObject:@"4"];
            NSLog(@"myBlock 里面的%@",array);
        };
        //先为array增接一个元素
        [array addObject:@"6"];
        NSLog(@"%@",array);
        myBlock();
        NSLog(@"myBlock 调用后之后的值%@",array);
  • 引用Block传值
参考BlockDemo\OC阶段最后一讲
  • RunTime

    相关练习参考OC阶段第十讲课

    RunTime简称运行时,就是系统在运行的时候的一些机制,是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。 在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 比如说,下面一个创建对象的方法中, 举例: OC : [[MJPerson alloc] init] runtime : objc_msgSend(objc_msgSend(“MJPerson” , “alloc”), “init”)
    在程序运行过程中, 可以动态创建一个类(比如KVO的底层实现),可以动态地为某个类添加属性\方法, 修改属性值\方法,可以遍历一个类的所有成员变量(属性)\所有方法

你可能感兴趣的:(语言)