美文网首页
OC基础语法

OC基础语法

作者: 微小的沙土 | 来源:发表于2021-05-04 21:38 被阅读0次

    简单了解OC

    1.Objective-C简称Obj-C或者OC,Objective的意思就是面向对象的。
    2.OC其实就是在C语言的基础之上,封装了一层面向对象的语法,他并不是一门全新的编程语言。
    3.OC是Mac OS X系统和iOS系统的主要开发编程语言
    4.C程序的源文件的后缀名为.c,OC程序的源文件是后缀名为.m,m就是message的意思
    5.因为OC是完全兼容C语言的,所以在.m文件之中是可以写任意的C代码。并且OC中main函数仍然是OC程序的入口,作用和C语言中的是一样的,这里就不赘述了
    6.苹果或者第三方事先将一些牛逼(常用)的功能写好,把这些功能模块封装在一个一个类之中,把这些功能提供给大家用。这些类的集合就叫做框架,说白了就是一个功能集合
    7.Objective-C是一个用C编写的很小的运行库,应用程序的规模增加很小。这一点和其他大部分00 (面向对象)语言不一样,它们通常使用很大的VM (虚拟机)执行程序。Objective-C写成的程序通常不会比其源码大很多
    8.Objective-C的最初版本并不支持垃圾回收。在Apple发布的xCode 4中开始支持自动释放。Xcode 4中的自动释放,也就是ARC (Automatic Reference Counting)机制,不需要用户手动Release (释放) 一个对象,而是在编译期间,编译器会自动添加那些已往经常写的“NSObject release"
    9.Objective- C不包括命名空间机制,所以程序设计人员必须在其类别名称前加上前缀,这样经常会导致冲突。2004年, 在Cocoa编程环境中,所有Mac OS X类别和函数均有“NS”作为前缀,例如NSObject或NSButton表示它们属于Mac OS X核心;使用“NS' 是由于这些类别的名称是:在NeXTSTEP开发时确定的
    10.虽然Objective- C是C语言的母集,但是它也不视C语言的基本类型为第一级的对象。 和C++不同,Objective C不支持运算符多载(它不支持ad-hoc多型大。但是和Java相同,Objective C只允许对象继承-一个类别(不允许多重继承)。 Categories和protocols不但具有多重继承的许多优点,而且缺点很少,例如额外执行时间过长和二进制不兼容
    11.由于Objective-C使用动态运行时类型,而且所有的方法都是函数调用,有时甚至连系统调用syscalls也是如此,所以很多常见的编译时性能优化方法都不能应用于biective-C,例如内联函数、常数传播、交互式优化与聚集等。这使得Objective _C性能劣于类似的对象抽象语言,例如C++。所以既然Objective-C运行时消耗大,就不应该运用于C++或Java常见的底层抽象

    OC语法用法

    Foundation框架

    提供了一些OC最基础的功能。Foundation.h这个文件中包含了所有Foundation框架中的头文件,#import 就相当于包含了所有Foundation框架的头文件。

    #import指令

    他是一个增强版的#incluce指令,并且用法和#include指令的用法相同。
    并且#import在包含文件的时候会先判断这个文件是否已经被包含,如果没有被包含就包含,如果已经被包含,就算了

    NSLog函数

    是printf函数的增强版,作用也是向控制台输出信息。

    1.NSLog输出完毕信息之后会默认加一个\n,如果我们手动加了一个\n,NSLog的自动换行就会失效。
    2.在输出信息的同时还会输出一些与程序有关的其他信息(系统时间、程序名、进程ID、线程ID)。
    3.NSLog函数支持printf函数的全部格式控制符,其用法也相同。
    4.NSLog函数的字符串参数前面必须要加一个@符号,这是OC里的字符串格式。
    5.NSLog可以使用%@格式控制符输出对象,而printf不能输出对象。
    6.NSLog函数的第一个参数是NSString类型的指针,所以必须给一个OC字符串。```

    关键字

    @autoreleasepool
    他是一个自动释放池,管理内存的,到时候再扯。```

    @property @synthesize @dynamic
    @property声明的属性默认会生成一个_类型的成员变量,同时也会生成setter/getter方法。
    但这只是在iOS5之后,苹果推出的一个新机制。看老代码时,经常看到一个大括号里面定义了成员变量,同时用了@property声明,而且还在@implementation中使用@synthesize方法

    @interface ViewController ()
    {
       // 1.声明成员变量
        NSString *myString;  
     }
     //2.在用@property
    @property(nonatomic, copy) NSString *myString;  
    @end
    
    @implementation ViewController
    //3.最后在@implementation中用synthesize生成set方法
    @synthesize myString;   
    @end
    

    其实,发生这种状况根本原因是苹果将默认编译器从GCC转换为LLVM(low level virtual machine),才不再需要为属性声明实例变量了。
    在没有更改之前,属性的正常写法需要成员变量+ @property + @synthesize 成员变量三个步骤。
    如果我们只写成员变量+ @property:

    @interface GBViewController :UIViewController
    {
        NSString *myString;
    }
    @property (nonatomic, strong) NSString *myString;
    @end
    

    1、@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = _var;
    2、@synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。
    3、@dynamic告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成。(当然对于readonly的属性只需提供getter即可)。假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var =someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
    使用场景:
    父类有个属性,已经默认自动生成了,而子类也声明了同样的属性,你如果也默认,不做其他操作,这种情形下,子类的属性就会出现警告,由于属性是继承来的,默认是在父类实现getter和setter,子类警告不会在子类出现getter和setter,会去其父类查找,那么你子类声明dynamic,也就是告诉他我会手动生成或者我父类有,你别警告我了,你运行起来就能找到了,自然,警告消除,运行起来调用就会去调用父类的getter和setter,能找到,就不会崩溃

    @interface father() 
    @property (nonatomic, strong, readwrite) NSObject *sampleObject; 
    ...
    @synthesize sampleObject = _sampleObject; 
    @end 
    
    @interface child : father
    @property (nonatomic, strong, readwrite) NSObject *sampleObject;
    ...
    @dynamic sampleObject;
    @end
    
    //.h
    @interface MKJBaseViewController : UIViewController
    @property (nonatomic, strong, readonly) MKJBaseViewModel  *viewModel;
    @end
    
    //.m
    @interface MKJBaseViewController ()
    @property (nonatomic, strong) MKJBaseViewModel  *viewModel;
    @end
    
    @implementation MKJBaseViewController
    - (instancetype)initWithViewModel:(MKJBaseViewModel *)viewModel{
        self = [super initWithNibName:nil bundle:nil];
        if (self) {
            _viewModel = viewModel;
        }
        return self;
    }
    
    //.h
    @interface MKJMainViewController : MKJBaseViewController 
    @property (nonatomic,strong,readonly) MKJMainViewModel *viewModel; 
    @end
    
    //.m
    @interface MKJMainViewController ()
    
    @end
    
    @implementation MKJMainViewController
    @dynamic viewModel;
    

    上面部分代码可以看出,子类已经有一个ViewModel用来初始化,每次初始化的viewModel实例都是根据具体控制器的业务逻辑进行初始化,你如果直接访问self.viewModel,而且直接访问MKJMainViewModel 中的方法,肯定是不行的,除非你这么做(MKJMainViewModel *)self.viewModel,这样做就麻烦点了,其实可以用到上面的关键字dynamic 在子类里面生成一个属性,属性名字和父类一样,这样就会出现上面的警告,告诉我们不会自动生成,由于是继承来的,他会在父类生成实现,那么为了消除警告,你可以在m文件中的实现下面加上@dynamic viewModel;,也就是这个关键字的作用,告诉编译器,不要警告了,getter和setter并不在此处,你运行的时候就知道从父类找了,那么当你子类调用self.viewModel 的时候,你拿到的就是从基类的getter方法中拿出的实例对象

    @dynamic 使用后而且没有自己实现
    -[Car name]: unrecognized selector sent to instance 0x6000000109e0

    @class @interface @implementation
    nonatomic atomic copy assign strong retain weak readonly readwrite****unsafe_unretained

    类型

    int count = 5;
    NSString *hello = @"您好";
    NSArray *array = [@"你",@"我",@"他"];
    

    属性

    @property(nomatic,ass) NSString *title;
    @property(nomatic,strong) NSString *title;
    

    方法

    
    

    
    

    分类

    
    

    扩展

    
    

    参考文章
    https://blog.csdn.net/u012946824/article/details/51788565
    https://www.jianshu.com/p/3f9f83b9d3cb
    https://blog.csdn.net/Deft_MKJing/article/details/78215876
    https://www.jianshu.com/p/725350d1014c

    相关文章

      网友评论

          本文标题:OC基础语法

          本文链接:https://www.haomeiwen.com/subject/vvncdltx.html