ARC以及 分类的使用

——————————————————————————————

  // 1) 创建自动释放池
  //使用注意事项
  Person *p = nil;
  p = [Person new];
  [p retain]; // 2
  [p release];
  // @autoreleasepool{    .......      }
  @autoreleasepool {
    //注意1: 并不是把代码放到自动释放池中,对像就能自动释放了
    //        p = [Person new];
    //注意2: 在自动释放池的外部发送autorelease消息
    //注意3: 如果想要把对象加入到自动释放池中,必须在
    // 自动释放池的内部调用 auturelease
    [p autorelease];
    //注意4: 自动释放池仅仅是在释放池结束的时候,向对象发送一次release
    //      对象不一定会被销毁
  } // [p release];   2-->1
  //    [p autorelease]; //在自动释放池外部调用了autorelease,不起作用
}

——————————————————————————————
+(instancetype)person{
    //创建person
    //加入到自动释放池
    //返回
    //self
    return [[[self alloc] init] autorelease];
}




 // stringWithFormat
    // [[[NSString alloc] init:@""] autorelease];
    NSString *str = [NSString stringWithFormat:@"xxxx"];
    //应用: Person 类定义一个快速创建对象的方法
    // Person *p = [Person alloc] init];    [p release];
    // Person *p = [Person person];
    // p 在堆区存放
    // p 不会存在内存泄露
    //实现步骤:
    // 1 定义类方法
    // 2 创建对象
    // 3 加入到自动释放池
    // person 是一个快速创建对象的方法
    //优点,可以帮我们创建对象,不需要再关心什么时候写release 或者 autorelease
    Person *p = [Person person]; //创建对象
    [p run];                     //对象创建成功,并且调用了run方法
    // person 从父类继承的
    //[Student person]; ---> Person
    //目标:[Student person]; ---> Student
    Student *stu = [Student person];
    [stu run]; //
    /// Users/apple/Desktop/课堂共享/就业班/01-OC加强/0601/code/OC8-ARC和分类的使用/3-【掌握】autorelease
    /// 的应用场景/main.m:44:19: Incompatible pointer types initializing
    /// 'NSString *' with an expression of type 'Student *'
    // NSString       Student
    //最好,编译的时候给个警告
    NSString *str2 = [Student person]; // +(id)person;
    NSLog(@"str2.length = %ld", str2.length);
    // id 不会有警告          作为返回值   定义变量     不能判断赋值类型
    // instancetype 有警告    只能作为方法的返回值      能判断赋值类型
    //
  }

——————————————————————————————
//创建一个对象
  Person *p = [Person new];
  // nil
  p = nil;
  NSLog(@"xxxxooooo");
}
void test2() {
  //创建一个对象
  Person *p = [Person new];
  // p1是一个局部的指针变量
  //局部变量的作用域:
  //从它定义的位置开始,到它所在的代码块的"}"结束
  Person *p1 = p;
  // nil
  p = nil;
  NSLog(@"xxxxooooo");
}
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    //创建一个对象
    //为什么p 没有赋值为nil也能够被释放
    //因为p是一个局部变量(存放在栈区),局部变量有作用域,出了作用域,就被销毁了
    //强弱指针
    //强指针: 默认的指针都是强指针
    //强指针,也可以使用 _ _strong 来修饰
    // p __strong 来修饰,所以,它使一个强指针
    __strong Person *p = [Person new];
    p.age = 18;
    NSLog(@"p.age = %d", p.age);
    //弱指针
    //弱指针:_ _weak修饰的指针,就是弱指针
    __weak Person *p1 = p;
    p = nil; // p被释放了,p1 被赋值为nil
    //报错?
    NSLog(@"xxxxxx p1.age = %d", p1.age);
  }
  return 0;

——————————————————————————————
 @property (nonatomic,weak) Dog *dog;
   
   @property做了三件事情
   1) 生成一个实例变量 _dog,加上weak,  __weak Dog *_dog;
 
   2) 生成_dog getset方法的声明
 
   3) 实现_dog getset方法
 
 
   @property (nonatomic,strong) Dog *dog;
 
 1) 生成一个实例变量 _dog,加上strong,  __strong Dog *_dog;
 
 2) 生成_dog getset方法的声明
 
 3) 实现_dog getset方法
解决 循环引用


——————————分类$————————————————————
分类
 分类:类别/类目
    作用:在不修改原类的情况下,给类增加新的功能
    好处: 1)团队协作    2)方法归类

    使用流程:
      1) 声明一个分类
         格式:
         //含义 给类扩展一个分类,分类名称是"分类名"
         @interface 类名(分类名)
           //新增的方法的声明列表
         @end
         //Person  base
         // eat  run

         //Person扩展了一个分类,分类名称是base
         //扩展了 eatrun的功能
         @interface Person (base)
         -(void)eat;
         -(void)run;
         @end

      2) 实现一个分类
         格式:
         @implementation 类名(分类名)
          //方法的实现
         @end
         @implementation Person(base)
         -(void)eat{
           NSLog(@"人在吃东西");
         }
         -(void)run{
           NSLog(@"人在跑步");
         }
         @end

      3) 使用分类

         如果分类的文件是单独的,使用之前,必须要导入分类的头文件




      //扩展  play 分类
      //  playlol   playdota
      //扩展  study 分类
      // studyC    studyIOS
——————————————————————————————
 分类的使用注意事项
 
  1) 分类主要是用于在不修改原类的情况下,给类增加新的方法,不能增加实例变量
 
  2) @property int age; 在分类中,编译不会报错,使用的时候,会报错
 
  3) 分类中可以使用原类中的实例变量
 
  4) 当分类中存在和原类同名的方法,优先执行分类的
 
  //   很多分类存在同名的方法?   到底执行那个?
  //   执行的是最后一个编译的分类文件的同名方法
 
  //   怎么看最后一个编译的?
 */

——————————————————————————————
 非正式协议:
        非正式协议和 正式协议(下次课),是两码事
        NSObject 或者 NSObject子类(Foundation 框架提供的类) 增加分类
        NSObject + eat
        NSString + count
        NSObject
         eat
          |
          |
        Person
    注意:
       非正式协议,一般原类不进行实现,而是有它的子类进行实现

——————————————————————————————
               分类                  类的延展(扩展)
相同点:
         可以增加新的方法              可以增加新的方法
 
不同点:
         不可以增加实例变量            可以增加实例变量
         必须得有分类的名称            一定不能有分类的名称
 




——————block————————————————————————
   block 是什么东西?
         代码块类型
    int a;
   可以使用block类型,来定义该类型的变量
    使用的格式:
    1) 最简单的形式
       返回值类型 (^block变量名)(参数列表) = ^(参数列表){    ....块的语句;   };
       使用block的格式:
       block变量名(实参列表);
       void (^myblock)();
       //定义block类型的变量,变量名是myblock
       //代码块返回值 void
       //代码块么有参数

    2) 没有返回值,但是有参数的block
       void (^myblock2)(int a,int b) = ^(int a,int b){
           NSLog(@"a + b = %d",a+b);
       };


 */
#import <Foundation/Foundation.h>
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    // 1)block的最简单的形式
    //没有返回值,没有参数
    void (^myblock)();
    //block变量赋值
    myblock = ^() {
      NSLog(@"我是代码块的内容");
      int a = 10;
      NSLog(@"a = %d", a);
      //.....
    };
    //使用block变量
    myblock();
    // 2)定义一个有参数,没有返回值的block
    // block变量名是 myblock2
    //也可以写成:void (^myblock2)(int ,int ),只要写参数的类型和个数
    void (^myblock2)(int a, int b) = ^(int a, int b) {
      NSLog(@"a + b = %d", a + b);
    };
    //        void (^myblock2)(int a,int b) ;
    //
    //        myblock2 = ^(int a,int b){
    //
    //            NSLog(@"a + b = %d",a+b);
    //
    //        };
    //使用有参数的block
    myblock2(10, 20);
    // 3)有参数,有返回值的block
    //返回两个数的最大值
    int (^myblock3)(int, int) = ^(int a, int b) {
      return a > b ? a : b;
    };
    //定义变量 接收代码块执行完成后的返回值
    int max = myblock3(34, 88);
    NSLog(@"max = %d", max);
    //给变量重新赋值
    myblock3 = ^(int a, int b) {
      NSLog(@"xxxxxx");
      return a + b;
    };
    int sum = myblock3(23, 30);
    NSLog(@"sum = %d", sum);
  }
  return 0;
}

————————typedef——block————————————————————
void test() { NSLog(@"I 'm Test!"); }
//函数指针的回顾
void test2() {
  //        test();
  //定义函数指针
  void (*p)(); // p就是一个指向返回值是void 类型,没有参数的函数指针
  p = test;
  // p(); // 用函数指针,间接的调用了test函数
  // 指向返回值是void类型,并且没有参数的函数指针,起个别名 p1
  typedef void (*p1)();
  p1 pp; // pp就是 p 一样的,都是指向返回值是void 类型,没有参数的函数指针
  pp = test;
  pp();
}
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    //定义一个 没有返回值,没有参数的blockb变量
    void (^myblock)(); //
    myblock = ^{
      NSLog(@"I'm  block");
    };
    myblock();
    // 1)typedef 给无参无返回值block起别名
    typedef void (^myblock2)(); // myblock2 是一个类型
    myblock2 b2; // b2是一个没有返回值,没有参数的block变量
    //block变量赋值
    b2 = ^{
      NSLog(@"I'm bande");
    };
    //使用block
    b2();
    // 2)给有参无返回值的block起个别名
    //给返回值是void并且有两个整型参数的block起个别名
    typedef void (^blockType1)(int, int);
    // blockType1 是一个类型
    blockType1 bt1;
    bt1 = ^(int a, int b) {
      NSLog(@"a + b = %d", a + b);
    };
    bt1(23, 12);
    // 3) 给有参有返回值的block起别名
    typedef int (^blockType2)(int, int);
    //blockType2类型定义一个变量bt2 并且初始化
    blockType2 bt2 = ^(int x, int y) {
      return x > y ? x : y;
    };
    int max = bt2(23, 45);
    NSLog(@"max = %d", max);
  }
  return 0;

——————————————block————————————————
void test() {
  //存在内存的栈区,因为是一个局部变量
  int m = 10;
  NSLog(@"block之前:m = %d,addr = %p", m, &m);
  //定义一个block变量
  void (^myblock)() = ^{
    //思考:block的内部能不能访问外部的m?
    //思考:此时block内部的 m 地址和 外部的m第地址一样吗?
    //注意:
    // 1) 此时 block 内部的m 外部的m是两个不同的变量
    //    当我们定义block的时候,系统会自动把block外部的变量copy到堆区
    // 2) 注意copy的使用是使用了const,所以,block的内部不能修改在堆区的常量值
    // 思考:为什么要以const的形式拷贝?
    // 原则: 我们一般不再block内部,修改外部的值,也是增强代码的可读性和易维护性
    //            m = 1000;
    NSLog(@"in block,m = %d,addr = %p", m, &m);
  };
  m = 20; //m重新赋值了
  NSLog(@"block之后:m = %d,addr = %p", m, &m);
  myblock();
}
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    //存在内存的栈区,因为是一个局部变量
    __block int m = 10;
    // __block 是告诉编译器 可以做一个忽略,可以在block中修改外部变量的值
    // block外部的变量的指向发生改变:指向堆区的变量
    NSLog(@"block之前:m = %d,addr = %p", m, &m);
    //定义一个block变量
    void (^myblock)() = ^{
      //
      m = 1000;
      // NSLog(@"m = %d",m);  //1000
      NSLog(@"in block,m = %d,addr = %p", m, &m);
    };
    myblock();
    m = 20; //m重新赋值了
    NSLog(@"block之后:m = %d,addr = %p", m, &m);
    // NSLog(@"m = %d",m);
  }
  return 0;



——————————————————————————————
// block作为函数的参数使用
// wrok有一个参数,无参无返回值block类型的,workBlock是一个变量名
void work(void (^workBlock)()) {
  NSLog(@"起床");
  NSLog(@"刷牙");
  NSLog(@"去车站");
  NSLog(@"坐车");
  //执行block的代码段
  workBlock();
  //    NSLog(@"了解项目");
  //    NSLog(@"找美女聊项目");
  NSLog(@"去车站");
  NSLog(@"坐车回家");
  NSLog(@"吃饭");
  NSLog(@"睡觉");
}
void workDay(int n) {
  //定义新的类型
  typedef void (^blockType)();
  //定义block的变量
  blockType w;
  switch (n) {
  case 1:
    w = ^{
      NSLog(@"了解项目");
    };
    break;
  case 2:
    w = ^{
      NSLog(@"分析项目");
    };
    break;
  case 3:
    w = ^{
      NSLog(@"编写代码");
    };
    break;
  case 4:
    w = ^{
      NSLog(@"调试项目");
    };
    break;
  case 5:
    w = ^{
      NSLog(@"离职");
    };
    break;
  default:
    break;
  }
  //调用work的方法
  work(w);
}
// void day1(){
//
//    NSLog(@"起床");
//    NSLog(@"刷牙");
//    NSLog(@"去车站");
//    NSLog(@"坐车");
//
//    NSLog(@"了解项目");
//    NSLog(@"找美女聊项目");
//
//    NSLog(@"去车站");
//    NSLog(@"坐车回家");
//    NSLog(@"吃饭");
//    NSLog(@"睡觉");
//
//}
//
//
// void day2(){
//
//    NSLog(@"起床");
//    NSLog(@"刷牙");
//    NSLog(@"去车站");
//    NSLog(@"坐车");
//
//    NSLog(@"分析项目");
//
//    NSLog(@"去车站");
//    NSLog(@"坐车回家");
//    NSLog(@"吃饭");
//    NSLog(@"睡觉");
//
//}
//
// void day3(){
//
//    NSLog(@"起床");
//    NSLog(@"刷牙");
//    NSLog(@"去车站");
//    NSLog(@"坐车");
//
//    NSLog(@"写代码");
//
//    NSLog(@"去车站");
//    NSLog(@"坐车回家");
//    NSLog(@"吃饭");
//    NSLog(@"睡觉");
//
//}
//
// void day4(){
//
//    NSLog(@"起床");
//    NSLog(@"刷牙");
//    NSLog(@"去车站");
//    NSLog(@"坐车");
//
//    NSLog(@"调试项目");
//
//    NSLog(@"去车站");
//    NSLog(@"坐车回家");
//    NSLog(@"吃饭");
//    NSLog(@"睡觉");
//
//}
//
// void day5(){
//
//    NSLog(@"起床");
//    NSLog(@"刷牙");
//    NSLog(@"去车站");
//    NSLog(@"坐车");
//
//    NSLog(@"离职");
//
//    NSLog(@"去车站");
//    NSLog(@"坐车回家");
//    NSLog(@"吃饭");
//    NSLog(@"睡觉");
//
//}
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    //        day1();
    //        day2();
    //        day3();
    //        day4();
    //        day5();
    //
    //        work(^{
    //            NSLog(@"了解项目");
    //            NSLog(@"找美女聊项目");
    //            NSLog(@"约会吧");
    //        });
    for (int i = 1; i <= 5; i++) {
      workDay(i);
    }
  }
  return 0;
}
——————————————————————————————
 block类型作为函数的返回值
 //错误用法:
 void(^block)() test(){


 }
 //解决方法:
 typedef void(^blockType)();
 //blockType 是一个无参无返回值的block类型

 */
#import <Foundation/Foundation.h>
// blockType 是一个无参无返回值的block类型
typedef void (^blockType)();
int sum(int x, int y) {
  //返回的是一个整型值
  return x + y;
}
// void(^block)() test(){
//
//
//
//}
// test函数需要返回一个 无参 无返回值的一个代码块
blockType test() {
  //定义一个blockType类型的变量 bt
  blockType bt = ^{
    NSLog(@"I'm  bt block");
  };
  //bt变量值返回
  return bt;
}
typedef int (^blockType2)(int, int);
//定义返回值是 一个 有参数有返回值的类型的block 的函数
blockType2 test2() {
  return ^(int a, int b) {
    return a + b;
  };
}
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    //        int s = sum(34, 12);
    //        NSLog(@"s = %d",s);
    //定义blockType类型的block变量 b2
    blockType b2 = test(); // b2存得就是test返回的那个代码块
    //使用block
    b2();
    blockType2 bb = test2();
    /**
     *  bb = ^(int a,int b){
               return a+b;
         };
     */
    int ss = bb(10, 20);
    NSLog(@"ss = %d", ss);
  }
  return 0;
}

——————————————————————————————
#import "Person.h"
//定义新的类型
typedef void (^blockType)();
// block作为函数的参数使用
// wrok有一个参数,无参无返回值block类型的,workBlock是一个变量名
// work(2)
void work(int n) {
  NSLog(@"起床");
  NSLog(@"刷牙");
  NSLog(@"去车站");
  NSLog(@"坐车");
  //执行block的代码段
  // workBlock();
  //    NSLog(@"了解项目");
  //    NSLog(@"找美女聊项目");
  blockType workDay(int n);
  //调用workDay 并且定义blockType类型的 变量bt接收函数的返回值
  blockType bt = workDay(n);
  bt();
  NSLog(@"去车站");
  NSLog(@"坐车回家");
  NSLog(@"吃饭");
  NSLog(@"睡觉");
}
blockType workDay(int n) {
  //定义block的变量
  blockType w;
  switch (n) {
  case 1:
    w = ^{
      NSLog(@"了解项目");
    };
    break;
  case 2:
    w = ^{
      NSLog(@"分析项目");
    };
    break;
  case 3:
    w = ^{
      NSLog(@"编写代码");
    };
    break;
  case 4:
    w = ^{
      NSLog(@"调试项目");
    };
    break;
  case 5:
    w = ^{
      NSLog(@"离职");
    };
    break;
  default:
    break;
  }
  //调用work的方法
  // work(w);
  return w;
}
int main(int argc, const char *argv[]) {
  @autoreleasepool {
    //        for(int i=1;i<=5;i++){
    //
    //            work(i);
    //
    //        }
    Person *p = [Person new];
    [p test:^{
      NSLog(@"xxxxxx");
    }];
    blockType b1 = [p test2];
    b1();
    [p test3:^{
      NSLog(@"test3");
    }];
  }
  return 0;
}
———————————————————




———————————


——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————




——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————




——————————————————————————————

——————————————————————————————

——————————————————————————————




——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值