• Objective-C学习笔记


    一、语法基础

    1.OC的语法

      关键字基本上都是以@开头,特例:self super id 等等;

      字符串以@开始;

      BOOL: YES、NO;空:nil;

      NSLog(@"Hello");

    2.包含框架的主头文件就可以包含所有的.H,及.*的作用。

    3.方法与对象:

      对象的方法都是以减号-开始;

      对象方法的声明必须在@interface和@end之间;

      对象方法的实现必须在@implementation和@end之间;

      函数可以写在任意位置;

    4.方法的参数

      OC方法中,一个参数对应一个冒号;

      冒号前需要加个说明;

      冒号也是方法名的一部分;

      - (int)pingFang:(int)num;

      -(int)sumWithNum1:(int)num1 andNum2:(int)num2;

      int n =[object pingFang:10];

      int m = [object sumWithNum1:10 andNum2:5];

    5.self

      self 代表当前调用的对象或者类;this只能用在对象方法中;

    6.多态

      父类指针指向子类对象;

      父类类型的变量,不能用来调用子类的方法;

    7.字符串NSString

      

    NSString *str = @"itcast";
    NSLog(@"我在%@上课",str);
    
    int age =15;
    int no= 5;
    NSString *name = @"Andy";
    
    NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d",age,no];
    
    int size = [name length];
    

     8.注释:

      #pragma mark 注释标签

    9.点语法

      点语法的本质是方法调用;

      stu.age=10;

      编译器:[stu setAge:10];

      int nAge=stu.age;

      编译器:int nAge = [stu age];

     10.set get的编译化

      XCode 4.4以后 @property 独揽了@synthesize的功能

    #import<Foundation/Foundtation.h>
    
    @interface Person:NSObject
    {
        int _age;
        NSString *_name;        
    }
    
    @property int age;
    @property NSString* name;
    
    @end;
    
    @implementation Person
    @synthesize age=_age;
    @synthesize name = _name;
    @end

    11. id类型

      id 相当于 NSObject*

      id 是万能指针;能指向和操作任何OC对象;

      id d = [Person new];

    12.构造方法

      完成的创建一个可用的对象需要两部:

      1.分配存储空间 +alloc;

      2.初始化 -init  

    Person *p=[Person new];
    //1.分配存储空间
    Person *p1 = [Person alloc];
    //2.使用-init进行初始化
    Person *p2 = [p1 init];
    
    Person *p3 =[[Person alloc] init];
    
    //重写Person的init方法
    -(id) init
    {
        //一定要调用super的init方法:初始化父类的其他的成员变量和属性
        //self = [super init];
        if(self = [super init])
            {
               //初始化成功
              _age = 10;
            }
    return self;
    }

    3.自定义构造方法规范

      a.一定是对象方法;

      b.返回类型一般是id类型;

      c.方法名一般以init开头

    13.Category 分类

      不改变原来类的基础上,添加类的方法;

        //声明

        @interface 类名(分类名称)

        @end

        //实现

        @implementation 类名(分类名称)

         分类只能增加方法,不能增加成员变量;

         分类方法实现中可以访问原来类的中成员变量;

        分类方法的实现优先级最高,然后是原来类,然后是父类,这样会导致原来的方法失效;

     14.类的加载和初始化

      a.当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load

    方法;

      b.当第一次使用某个类时,就会调用当前类的+initialize方法;

          c.先加载父类,再加载子类;

          d.先初始化子类,再初始化子类;

    15.description方法

      默认情况下,NSLog和%@输出对象时,结果是:<类名:内存地址>

      1.会调用对象的p的-description方法;

      2.拿到-description方法的返回值(NSString *)显示到屏幕上

     16. SEL

      -(void) test;

      -(void) test2:(NSString *)str;

      [p test];  

      1.把方法包装成SEL类型的数据;

      2.根据SEL数据找到test方法;

      3.根据方法地址调用对应的方法; 

      [p performSelector:@selector(test)];

      [p performSelector:@selector(test2:) withObject:@"123"];

     二、内存管理

      1.引用计数器

        给对象发送retain消息,可以使引用计数器+1;

        给对象发送release消息,可以使引用计数器-1;

        可以给对象发送retainCount消息获得当前的引用计数器值;

      2.对象的销毁

        一个对象的引用计数器为0时;那么它将被销毁;

        当一个对象被销毁时,系统会自动向对象发送一条dealloc方法;    

    Person类的实现
    
    -(void) dealloc
    {
          NSLog("对象被销毁");
          [super dealloc];    
    }
    
    //alloc 和release要成对出现;
    //retain和release需成对出现;

      3.OC不存在空指针错误,给空指针发送消息不报错;

      4.retain方法会返回对象本身;

      5.set方法的内存管理

        基本数据类型,直接复制;

    - (void) setCar:(Car*) car
    {
        if(car != _car)
            {
             [_car release];
             _car = [car retain];  
            }
    }
    
    - (void)dealloc
    {
        [_car release];
    }

      6.@property参数

        1.set方法内存管理相关参数

           a.@property (retain) Book *book; retain:release旧值,retain新值;

           b.assign:直接赋值,适用于非OC对象类型;

           c.copy:release旧值,copy新值;

         2.是否生成set方法

          readwrite:同时生成setter,getter的声明、实现;(默认)

          readonly:只会生成getter的声明、实现;

        3.多线程管理

           nonatomic:不加锁;性能高,一定要加。

           atomic:加锁,默认

        4.setter和getter方法的名称

          @property (getter=methodName,setter=setName:)int height;

          setter方法一定要有冒号:,不常用;

          一般常用于BOOL 类型的getter方法名的修改

          @property (getter=isRich) BOOL rich;

       7.循环retain和@class

          循环retain的解决方案:

            一端用retain,一端用assign;

          @property(nonatomic,retain) Card *card;

          @property(nonatomic,assign) Person* person;

      8.autorelease      

    //autorelease方法会返回对象本身
    //autorelease会将对象放到一个自动释放池;
    //当自动释放池被销毁时,会对池子的所有对象做一次release操作;
    //创建对象时,不要直接用类名;一般用self代替。
    int main()
    {
        @autoreleasepool
        {//开始代表创建了释放池  
            Person *p = [[[Person alloc] init] autorelease];
            return 0;  
        }//结束代表销毁释放池
    }
    
    + (id)person
    {
          //使用Person会出现子类调用时,返回的指针类型还是父类的问题
          //return [[[Person alloc] init] autorelease] ;
         return [[[self alloc] init] autorelease] ;
    }
    
    +(id)personWithAge:(int) age
    {
        //Person*p = [[[Person alloc] init] autorelease] ;
        Person*p =[self person];
        p.age =age;
        return p;
    }

      9.ARC机制  

    //ARC
    ARC的判断准则:
    只要没有强指针指向对象,就会释放对象;
            指针分2种:
                1.强指针:默认情况下,所有指针都是强指针 __strong
                2.弱指针:__weak
    
    //strong 等价于之前的 retain
    //
    @property (nonatomic,strong) Dog *dog;
    @property (nonatomic,weak) Dog *dog;
    
    ARC的特点:
    1.不允许调用release、retain、retainCount;
    2.允许重写dealloc,但是不允许调用[super dealloc]
    3.@property的参数
        *strong:成员变量是强指针(适用于OC对象类型);
        *weak:成员变量是弱指针;
        * assign:适用于非OC对象类型;
    4.以前的retain,修改为strong,其他一切不变。
    5.如果两端互相引用,一端用strong,一端用weak;

     三、其他数据类型

      1.Block

        Block的作用是来封装代码,可以在任何时候执行;

        

    #import <Foundation/Foundation.h>
    
    typedef int(*Sump) (int,int);
    
    typedef int(^MyBlock)(int,int);
    
    int main()
    {
        
        int(^sumBlock)(int,int);
        
        sumBlock = ^(int a,int b){
            return a+b;
        };
        
        MyBlock sum2Block = ^(int a,int b){
            return a+b;
        };
        
        return 0;
    }
    
    void test2()
    {
        int (^sumBlock)(int,int)=
        ^(int a,int b)
        {
            return a+b;
        };
        int c = sumBlock(10,11);
        NSLog(@"%d",c);
        
        
        //用一个block输入n条横线
        
        void (^lineBlock)(int)=
        ^(int n)
        {
            for (int i=0; i<n; i++) {
                NSLog(@"------------");
            }
        };
        
        lineBlock(5);
    }
    
    void test()
    {
        //block用来保存一段代码
        //block的标识:^
        /*
         block跟函数很像:
         1.可以保存代码
         2.有返回值
         3.有形参
         
         block访问外边的变量:
         1.默认情况下,block可以访问外面的变量;
         2。默认情况下,block不能修改外面的变量
         3.给局部变量加上__block关键字,这个局部变量可以在内部修改;
         
         利用typedef定义block类型
         typedef int(^MyBlock)(int,int);
         以后利用MyBlock来定义block变量
         MyBlock sum2Block = ^(int a,int b){
         return a+b;
         };
    
         */
        
        //定义block变量
        //如果block没有形参,后面的括号可以省略
        
        
        void (^myblock)()=
        ^{
            NSLog(@"test-----------");
        };
        
        //利用block变量调用block内部的代码
        myblock();
    }

     2.@protocol 协议

      

    #import <Foundation/Foundation.h>
    
    //定义了一个名叫MyProtocol的协议
    @protocol MyProtocol <NSObject>
    //@required 要求实现,不实现就会发出警告;默认
    //@optional 不要求实现。
    //一个协议遵守了某一份协议,就可以拥有另一个协议中的所有声明方法
    //NSObject 是所有类的基类,也是基协议
    //要求某个对象遵守这个协议
    // NSObject<MyProtocol> *obj = 遵守该协议的类的对象;
    
    /*
     1.协议的定义:
        @protocol 协议名称 <NSObject>
        //方法声明列表...
        @end
     2.如何遵守协议:
        1>类遵守协议:
        @interface 类名:父类名  <协议名称1,协议名称2>
     
        @end
        2>协议遵守协议:
        @protocol 协议名称 <其他协议名称1,其他协议名称2>
     
        @end
     3.协议中方法声明的关键字:
        1>@required 要求实现,不实现就会发出警告;默认
        2>@optional 不要求实现。
     4.定义一个变量的时候,限制这个变量的对象遵守某个协议
        类名<协议名称> *变量名;或者
        id<协议名称> 变量名;
     5.@property中声明的属性也可用做一个遵守协议的限制
        @property(nonatomic,strong) 类名<协议名称> *属性名;
        @property(nonatomic,strong) id<协议名称> 属性名;
     6.协议可定义在其他单独文件中, 也可以定义在某个类中
        1>如果这个协议只用在某个类中,则定义在该类中;
        2>如果用在多个多个类中,则定义在单独文件种。
     
     */
    
    @required
    - (void)test;
    
    @optional
    - (void)test2;
    
    @end

    四、Foundation框架

      1、结构体

    int main()
    {
        /*
         NSRange(location,length)
         NSPointCGPoint
         NSSizeCGSize
         NSRectCGRect
         */
        
        CGPoint point = NSMakePoint(10, 10);
        CGPoint point2 = CGPointMake(10, 10);//常用
        
        
        CGSize size = NSMakeSize(10, 10);
        CGSize size2 = CGSizeMake(10, 10);
        
        CGRect rect1 = CGRectMake(10, 10, 50, 50);
        CGRect rect2 = {{0,0},{50,50}};
        CGRect rect3 = {point,size};
        CGRect rect4 = {CGPointZero,CGSizeMake(100, 90)};
        
        NSString *str = NSStringFromPoint(point);
        
        //比较两个点是否相同
        BOOL bIsSame =CGPointEqualToPoint(point, point2);
        
        BOOL bIsContain = CGRectContainsPoint(rect1, point);
        
    
        return 0;
    }
    
    void testRange()
    {
        //@“i love oc”;
        //    NSRange r1={2,4};//不用
        //    NSRange r2={.location=2,.length=4};//不常用
        //    NSRange r3 = NSMakeRange(2, 4);//常用
        
        NSString *str=@"i love oc";
        
        //查找字符串在str中的范围
        //如果找不到,length=0;location=NSNotFound==-1
        NSRange range=[str rangeOfString:@"love"];
        
        NSLog(@"loc=%ld,length=%ld",range.location,range.length);
    }

    2、字符串  

    /*
         1.字符串创建
         */
        NSString *str1=@"hello";
        NSString *str2=[[NSString alloc] initWithFormat:@"age is %d",10];
        
        NSString *str3 = [[NSString alloc] initWithUTF8String:"abc"];
        const char *cs = [str3 UTF8String];
        
        //从文件中读取
        NSString *str4 = [[NSString alloc] initWithContentsOfFile:@"/Users/chenwei/Desktop/objective-c-01.m" encoding:NSUTF8StringEncoding error:nil];
    //    NSLog(@"%@",str4);
        
        //URL:资源路径
        //协议头://路径
        //本地文件,协议头 file://
        NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/chenwei/Desktop/objective-c-01.m"];
        NSString *str5 = [[NSString alloc] initWithContentsOfURL: url encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"%@",str5);
        
        
        //常用方法.一般都用一个类方法与对象方法对应。
        NSString *str6 = [NSString stringWithFormat:@"age is %d",10];
        NSURL *str7 = [NSURL URLWithString:@""];
        

    3、数组

    /*
     NSArray: 不可变数组
     NSMutableArray:可变数组
     
     @[] 只创建不可变数组NSArray
     */
    int main(int argc, const char * argv[])
    {
        
        NSMutableArray *array=[NSMutableArray array];
        [array addObject:@"Jack"];
        [array addObject:@"Rose"];
        //nil不能添加
        //[array addObject:nil];
        
        //删除元素
        //[array removeAllObjects];
        
        return 0;
    }
    
    void useArray()
    {
        /*
         1.NSArray 创建
         */
        //OC数组只能存放OC对象、不能放非OC对象,比如int、struct等
        //NSArray *array = [NSArray array];
        NSArray *array2 = [NSArray arrayWithObject:@"jack"];
        //nil是数组元素结束的标记
        NSArray *array3=[NSArray arrayWithObjects:@"jack", @"Rose",nil];
        //快速创建数组的方式
        NSArray *array4=@[@"jack",@"rose",@"others"];
        /*
         2.NSArray 个数
         */
        int nCount = array2.count;
        
        /*
         3.NSArray 遍历
         */
        
        for (int i=0; i<array4.count; i++) {
            NSLog(@"%@",array4[i]);
        }
        
        for(id obj in array4)
        {
            NSUInteger nIndex = [array4 indexOfObject:obj];
            NSLog(@"%ld---%@",nIndex,obj);
        }
        
        //NSLog(@"%ld",array3.count);
        
        [array4 enumerateObjectsUsingBlock:
         //没遍历到一个元素,就会调用一次block
         //并且当前元素和索引位置当做参数传递给block
         ^(id obj, NSUInteger idx, BOOL *stop) {
             
             NSLog(@"%ld---%@",idx,obj);
             if (idx == 0) {
                 //停止遍历
                 *stop = YES;
             }
         }];
        
        void (^myBlock)(id,NSUInteger,BOOL *) = ^(id obj, NSUInteger idx, BOOL *stop) {
            
            NSLog(@"%ld---%@",idx,obj);
            if (idx == 0) {
                //停止遍历
                *stop = YES;
            }
        };
        
        for (int i=0; i<array4.count; i++) {
            BOOL bIsStop = NO;
            id obj = array4[i];
            myBlock(obj, i, &bIsStop);
            if (bIsStop) {
                break;
            }
        }
    
    }

     4、字典

    int main(int argc, const char * argv[])
    {
        /*
         字典:
            key------>value
            索引------>文字内容
         里面存储的都是键值对
         
         */
        NSDictionary *dict4=@{@"name": @"jack",@"address":@"北京"};
        
        NSArray *keys = [dict4 allKeys];
        for (int i=0; i<dict4.count; i++) {
            NSString *key = keys[i];
            NSString *object = dict4[key];
            NSLog(@"%@------%@",key,object);
        }
        
        [dict4 enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
            NSLog(@"%@------%@",key,obj);
        }];
        
        return 0;
    }
    
    void useMutableDictionary()
    {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        
        [dict setObject:@"Jack" forKey:@"name"];
        [dict setObject:@"北京" forKey:@"address"];
        [dict setObject:@"Rose" forKey:@"name"];
        
        //[dict removeAllObjects];
        NSLog(@"%@",dict);
    }
    
    void userDictionary()
    {
        NSDictionary *dict = [NSDictionary dictionaryWithObject:@"jack" forKey:@"name"];
        id obj = [dict objectForKey:@"name"];
        
        NSArray *keys=@[@"name",@"address"];
        NSArray *objects=@[@"jack",@"北京"];
        NSDictionary *dict2 = [NSDictionary dictionaryWithObjects:keys forKeys:objects];
        
        NSDictionary *dict3 = [NSDictionary dictionaryWithObjectsAndKeys:
                               @"jack",@"name",
                               @"beijng",@"address",
                               nil];
        
        //常用方式
        NSDictionary *dict4=@{@"name": @"jack",@"address":@"北京"};
        
        id obj2 = [dict4 objectForKey:@"name"];
        
        id obj3 = dict4[@"name"];
        
        NSLog(@"%@",obj2);
        NSLog(@"%@",obj3);
        
        //返回键值对的个数
        NSLog(@"%ld",dict4.count);
    }

    5、NSNumber和NSValue

    int main(int argc, const char * argv[])
    {
        //NSNumber之所以能包装基本数据类型为对象,是因为集成了NSValue
        
        NSNumber *num = [NSNumber numberWithInt:10];
        NSDictionary *dict=
        @{
          @"name":@"jack",
          @"age":num,
        
        };
        
        NSNumber *num2 = dict[@"age"];
        int nNum = [num2 intValue];
        
        NSLog(@"%d",nNum);
        
        //@20将20包装成一个NSNumber对象
        NSDictionary *dict2=
        @{
          @"name":@"jack",
          @"age":@20,
          };
        
        int age = 10;
        NSNumber *ageNum= @(age);
        
        //将结构体包装成OC对象,使用NSValue。
        
        CGPoint p = CGPointMake(10, 10);
        NSValue *pValue = [NSValue valueWithPoint:p];
        
        NSArray *array =@[pValue];
        //将value转换成对应的结构体
        NSPoint newPoint = [pValue pointValue];
        
        return 0;
    }

     6、日期

    int main(int argc, const char * argv[])
    {
        //创建一个时间对象
        NSDate *date = [NSDate date];
        
        NSLog(@"%@",date);
        
        //oc的时间都为秒
        NSDate *date2 = [NSDate dateWithTimeInterval:5 sinceDate:date];
        
        //从1970年开始走过的秒数
        NSTimeInterval secondsFrom1970 = [date2 timeIntervalSince1970];
        
        
        //日期格式化类
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        // y 年 M 月 d 日
        // m 分 s 秒 H(24小时) h(12小时)
        formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
        NSString *str = [formatter stringFromDate:date];
        
        NSLog(@"%@",str);
        
        
        //字符串,转换成NSDate
        NSString *str2 = @"2011/09/10 18:56";
        NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
        formatter2.dateFormat = @"yyyy/MM/dd HH:mm";
        NSDate *date3 = [formatter2 dateFromString:str2];
        
        return 0;
    }

     7、Copy

    @interface Person : NSObject <NSCopying>
    
    //copy代表set方法会release旧对象、copy新对象
    //修改外面的变量,并不会影响到内部的成员变量
    //建议:NSString一般用copy策略,其他对象一般用retain
    
    @property (nonatomic,copy) NSString *name;
    
    + (id) personWithName:(NSString *)name;
    
    @end
    
    
    
    #import "Person.h"
    
    @implementation Person
    
    + (id) personWithName:(NSString *)name
    {
        Person *person = [[[self class] alloc] init];
        person.name = name;
        return person;
    }
    - (id)copyWithZone:(NSZone *)zone
    {
        //这里创建的copy对象不要求释放
        Person *copy = [[[self class] allocWithZone:zone] init];
        copy.name = self.name;
        return copy;
    }
    @end

     8.反射

    NSString *str = @"Person";
    Class class = NSClassFromString(str);
    Person *person = [[Class alloc] init];
    NSLog(@"%@",person);
    
    NSString *name = NSStringFromClass([Person class]);
    
    //方法反射
    NSString *method = @"test";
    SEL selector = NSSelectorFromString(method);
    [person performSelector:selector];

        

  • 相关阅读:
    springboot 2.4.5 redis 配置类+缓存
    华为ensp模拟器 提示40 错误问题
    Nodejs
    Python PermissionError:[Errno 13]权限被拒绝 [winerr 5]
    Window10的linux docker 安装(wsl版本)
    window10的 Linux 子系统ssh配置
    vue3.0中provide和inject实现响应式传值
    正确开启vue3.0调试工具vue-devtools
    vue动态设置组件样式
    element-ui菜单导航的三种递归写法(三)
  • 原文地址:https://www.cnblogs.com/alwaysyouare/p/4143522.html
Copyright © 2020-2023  润新知