简单了解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
网友评论