oc学习笔记



1. 面向对象的思想


    面向过程:注重实现功能的步骤;

    面向对象:注重的是功能,该事物有没有该功能,只要获得该事物就会具有该功能;

                        角色的转换,由执行者 - - - >  控制者

       类: 模具- 模型(提取一个类,创建一个类)根据自己开发需求,抽取一些属性;类的建立,

                方便以后对此类的使用,不只局限于当前文件之中;考虑需求的变更


                提供了属性,修改实例对象的参数;

                方法,让实例对象,完成某些功能;类方法:不需要创建对象,节省内存;

               

                方法:谁清楚,谁执行;

                :类方法不能访问成员变量-(只有对象方法才可以访问成员变量)

                        类名:前缀+大写+驼峰


    对象:根据 类 提供的模具(属性,方法)创建 对应的实际事物



2.创建对象:


   @interface

   @end

   用于声明: 声明成员变量 (可有可无)

                        声明实例方法  (可又可无 类方法,对象方法。注意分号)

                        声明成员变量的值域:@public @private @protected(默认)

     方法创建:       -/+       (void)      person     :    (int)       age

     对应的作用:    方法类型     返回类型    方法名   继承  参数类型   参数名


   @implementation

   @end

    类名 * 对象名 =[[]];(新建对象)            对象名字(栈)--指向-->新建对象(保存地址)

    对象名:对新建对象起名,并且记录新建对象的指针,用指针访问的时候 不能直接访问,

                   直接可以访问是@public

                  @private  只能在中访问;类对象访问不了,不能直接访问;一般在类中的方法实现set 和  

                                     get 相当于点语法

                   @protect  类和子类访问;


3.方法的实现


    用类可以创建一个对象

    person *p=[person alloc];  创建空间

    p=[p init];                               初始化

    以上方法可以  等同   person *p=[[person alloc] init ];

                              等同   person *p=[person new];



      表达式或者消息机制: [对象/类   方法名 : 参数........ ]

                                      等同[对象的执行者     行为/功能]

      类 *对象名=[创建对象/初始化];

      person *p=[[person alloc]init ];


      p是person类 对象 存放的是 person类的 地址;存在这指向关系;(也就是两份空间)


     用p可以访问 对象的成员变量

      p->_age;  (直接访问,不需要set和get,注意权限)

      p.age;      (set和get访问)

      self.age;   (self区别,看方法类型;set和get)

      _age;        (直接访问,本类中使用)


    isa指针,是对象指向类的方法列表


     注意:类的设计(枚举 结构体);

     匿名对象:每次用会alloc 以为这创建一个新对象;

对象-类 作为参数的本质:




注意:  当自定义对象,作为成员变量

                 A类是B类,的成员变量

                成员变量 意味保存  A类型的地址  仅仅指向关系

                外界访问,使用成员变量A,传递地址 或 自身已经有指向地址;不会自动开辟内存;

    

                  在实际应用中,会有一个变量,不断指向创建的对象的地址,每次加载数组中;

                  或者说,每次会索取该地址指向对象;

                  在编译运行出错,可以从本质入手;     

                  学会对apple  SDK开发文档使用






1.封装


       封装:把事物的特性封装成抽象的类,可以隐藏内部的实现细节

                访问权限-setter-getter-

       注意: 命名的规范;

      在开发中,可能重写set方法,比如Plist的 对模型的传递

               - (void)setMd:(model *)md

      {

         self.img.image = [UIImage imageNamed:md.icon];

         self.name.text = md.name;

         self.name.font = [UIFont systemFontOfSize:15];

         _md = md;

      }


2.点语法

     点语法:本质就是set和get方法;不是访问成员变量,利用编译器特性

                     直接访问成员变量就一种  ->  箭头

                  @public 公共,权限全部开放

                  @private  私有的,权限是 本类;

                  @protected 当前类和子类,默认的权限

                  @package   框架;


3.self

     self:在类方法之中,就代表自己当前类,在对象方法之中,就代表当前自己对象

           

           super和self

           当子类方法和父类方法一样   子类要想调用父类的方法 [self 方法名]死循环

                                                              super直接用父类方法,不用在当前对象中找

                                                              注意方法的重写时,两者的区别;


          注意:self类方法不能直接调用对象self方法  

          方法: [Person speak]; 等同于  [self speak];  (前提调用是在本类中)

          成员变量: slef.age 等于 _age  等于 p-> _age;  (前提调用是在本类中)


4.继承

      继承:super class child class 实现功能的扩展

                 建立类与类之间的关系 抽取相同的代码和成员变量

                 子类和父类不能有相同的成员变量,父类的声明要放在子类的前面;

                 方法可以有相同的 ,成员变量不可以-(方法的重写) 实现的规则是:先到子类中找 找不到再到父类去找

     坏处:藕合性强

     功能的扩展:继承 分类 组合 ;

     继承与组合的区别:  A组合于B:->  B想用有A            A继承B: -> A就是B   


5.super

           编译器指令符

         super访问父类的方法,不会从当前子类找方法

           使用是在子类方法(类方法-对象方法)中,调用父类的类方法或对象方法,意味必须有继承关系;

           作用:使用父类的方法,功能;子类加扩展功能;(如:创建控件初始化同时加载资源;)


6.多态

    多态:       用父类创建子类对象;必须有继承关系

          如果参数是一个类且有子类可以传送子类的对象,

                       参数是父类,子类的对象也可以使用,(动态监测,传递的对象类型,执行方法,根据实际运行的对象类型调用)

   动态绑定:动态绑定运行的时候确定类型,编译和运行不一样;不建议这么写(调用子类的特有方法,但是编译可以通过)

                       好处 代替多行代码;父类可以传入很多子类型

                       Person * p = [Student alloc] init ];

                      [p study];   study 是student 方法; 

   注意:        对象的类型转换 向上(父类方法)、向下 (子方法) 想转换类型 * 转换后名称=(类型 *)要转换的对象名称

              

                      [Person Class]; - - -  %@  获得当前类名;


                      CXLPerson * p = [[CXLStudent alloc] init];

         [p eat]; //eat - person的方法

         [p  personSpeak];









1.ARC:AutoMatic Reference Counting(自动引用计数器)

   MRC:手动引用计数


2.  内存管理:通知一个对象,我要使用你,此时计数器会加1,不用这个对象的时候让计数器会减1;

                      合理对内存的使用,不会造成内存的泄漏;这样就对内存进行合理的分配; 

     思想:当对象去 拥有或者赋值 另一个对象 此时,我们要做记录 对象被几个人占有 确定能不能被释放回收,在上述中,出现拥有  

                 或者赋值的此时(set方法设置),  我们要记录对象占有人数,使其计数器加1,没人使用对象后要释放收回


3.   每个对象有一个 引用计数器 占用四个字节

      对象刚创建,引用计数器的值为1;

      栈:先进后出 (FILO),基本数据

      队列: 先进先出(FIFO):

      堆: 对象数据类型,需要手动释放


4. 只要有new/alloc/copy/creat(在线程中) /retain

             都需要release;有加就有减

             当retainCount 为0的时候,对象会被销毁;


5. 僵尸对象: 被销毁释放的对象

    野指针: 指向僵尸对象的指针;

    空指针: 指向为nil的指针,运行编译不会报错;


6. dealloc方法;

 - (void) dealloc    //相当于,临死的遗言,对象被销毁的都是自动调用这个方法

      {

                    [super alloc];   //arc 不能写此方法,手动管理内存需要注意,以免遗漏

         }



 7.内存管理的黄金法则:

           :多对象的时候 注意分析好 对象之间的指向关系,知道什么时候会销毁对象的位置;

          换取对象的时候,注意setter方法的改变,对原对象的操作;3步曲

         if(_book!=book)     1.if判断重复复制:(p=b1;p=b1;p=b1);如果为同一对象:此时不做计数

                                           

             {

                [_book release];                    2.  释放回收原来的对象,release旧值

                _book=[book retain];           3.  对现对象进行计数,因为开始使用新对象;retina新值

            }  

 

        if(成员对象!=参数对象)             此成员对象保存的是上次对象,参数对象为新传入对象,判断同一对象

        {

            [ 成员对象 release];               释放回收原来的对象      

             成员对象=[参数对象 retain]  1.记录新关系 计数器=1

                                                                       2.传入新对象,记录;

          }


8.@class头文件循环引用

      如:A #import  B,B #Import A,此时a中引用b,b中引用a;

              如上,为循环引用;编译error   

              解决: 头文件引用用 @class; 此时不会有error;

        #import : 会拷贝,源文件的属性,方法;由于import是一个预编译指令, 他会将""中的文件拷贝到import所在的位置

        @calss: 只会告诉当前类,我有这么一个方法;不会告诉它内部的属性和方法;

                         当 #import 的源文件,被修改,他会重写拷贝到当前使用的类,此后,依次重写拷贝引用该文件的类;

                         @class 不会有上述情况;


9.内存管理循环引用问题;

 

         A的属性中有B,B的属性有A;

         在release中,两者都不会被释放;

解决1: 一个类 retain, 一个类assign

解决2: 一个类 strong, 一个类weak;



10. dealloc 方法提升

- (void)dealloc

{

    self.person = nil;  //用点语法,相当于调用set方法,此时会release一次;

    NSLog(@"car - dealloc");

    [super dealloc];

}


















           




1. oc语法没有,私有方法

    伪私有方法: 不在 @interface 中声明方法

                           直接在 @imelmention 实现

 


 2. id类型

              NSObject * obj 是静态数据;不能调用子类的方法

           id 万能指针

              id是动态类型的数据;运行的时候才检测数据的类型

           id类型一般用于参数;

              由于动态数据类型可以调用任意方法, 所以有可能调用到不属于自己的方法, 而编译时又不会报错, 所以可能导致运行时的错误

             instancetype:


           //判断stu对象 是不是CXLPerson 的实例对象 或者 子类

     BOOL flag = [stu isKindOfClass:[CXLPerson class]];

    

    //判断stu对象 是否为 CXLPerson 的实例对象 (不包括子类)

     BOOL flag = [stu isMemberOfClass:[CXLPerson class]];


3.构造方法的重写

          重写构造方法

                  1.先写父类的构造方法

                  2 写子类

                  3 调用对象为:self    ----- reture self

                  4 返回类型为 id 

                  不断的向上初始化父类->nsobject

                  作用;可以自己初始化值,同时传递或者修改一些属性;


                 自定义构造方法规范:需要声明

                 1- 一定为对象方法

                 2- 返回id

                 3-  方法名字以init开头,后面首字母,必须大写

                 判空

  •                 - (id)initWithAge : (int) age

               {

                         if( self = [super init] )  //初始化-并且赋值给--self

                  {

                   _age=age;                //一般为 _下划线访问方式;编码规范

                  }

                    return self ;

              }‘


4.类工厂方法创建对象

                + (instancetype)alloc;  //类方法

                + (instancetype)person

       {

         return [[self alloc] init];  //self,不一定是本类创建对象;

       }

      Student *stu = [Student person]; //此时self-为Student

             self:谁调用,self就是谁

              一般类方法之中,不能访问成员变量,一般不用访问成员变量的方法,优先考虑类方法

          注意:一个类提供自定义构造方法和自定义类工厂方法用于创建一个对象


5.SEL

              SEL:相当于函数指针,打包方法,可以直接调用执行方法,可以让方法作为参数执行


             1.判断有没有实现该方法

            NSLog(@"%d",[stu respondsToSelector:@selector(test)]);

              多用于,代理模式,是否实现了协议的方法

 

             2.通过SEL调用方法

             [stu performSelector:sel]; //无参数 

     [stu performSelector:sel withObject:@“123”]; //有参数

             多用于监听,或者状态的改变,用SEL自动调用方法执行


6.Load和initialeize

        共同点:都会先调用父类的方法,在执行本类的方法,都会执行一次,只是执行的时间不一样

         Load:   当xcode编译的时候,会执行;

         initialeize: 当这个类被使用的时候会调用;





你可能感兴趣的:(oc)