类
- Android 中.java 为一个类文件
- oc 中 .h和.m 和为一个类文件
.h 文件
声明文件只做属性声明,函数声明,不做具体逻辑实现,以@interface 声明
- 方法声明
+(int)personWithA1:(float)a1 andA2:(NSString*)a2;
- 代表可以通过 类名调用,类似于java 的static,属于类方法 调用:[Person personWithA1:2 andA2:@"类方法"];//调用对象是类名
-(int)personWithA1:(float)a1 andA2:(NSString*)a2;
代码对象方法和java 的正常方法一样
Person * obj1=[[Person alloc]init];
[obj1 personWithA1:1 andA2:@"对象方法"];//调用对象是类对象
- 属性声明
@property int age;
@property 为oc 属性申明。和Java 属性变量和声明变量一样
oc隐士为这个属性做了get 和set 方法,新版的Java 也是隐士调用了
-
成员变量声明:
int i;
不能有初始值只能在方法函数中传递; -
属性获取:
people.name=@"ZhangSan"; 等价:[people setName:@"ZhangSan"];
NSString * theName=people.name; 等价:NSString * theName=[people getName];
这些语法和Java 是一样的
java 中属性声明是包括函数和成员变量,oc 是分开的
.m文件
为具体的函数实现和逻辑的处理,为类扩展文件 例如:
//对类声明中的类方法做实现\
+(int)personWithA1:(float)a1 andA2:(NSString*)a2{\
NSLog(@"%f,%@",a1,a2);\
return 0;\
}\
\
//对类声明中的对象方法做实现\
-(int)personWithA1:(float)a1 andA2:(NSString*)a2{\
NSLog(@"%f,%@",a1,a2);\
return 0;\
}\
\
//对类扩展中的对象方法做实现\
-(void)display{\
NSLog(@"类扩展中声明的方法");\
}
类的导入
引入编程语言提供的头文件的写法是:
#import <文件名>
引入自己写的文件的写法是:
#import "文件名"
引入的文件必须是.h文件,引入.m文件会报错,类在.h文件和.m文件中都可以引入头文件,区别是:在.h文件中引入头文件,.h和.m文件都可以使用这个文件中的资源;如果在.m文件引入头文件,.h文件不能使用该文件中的资源。 所以,在引入头文件的时候,需要考虑在.h文件中当声明类的时候,是否使用该头文件中包含的资源。如果使用,就在.h文件中引入;反之,在.m文件中引入即可。类似java import ,
self 和super
-
self 在使用OC语言创建一个类时,底层就为我们创建好了一个self,它的使用范围仅限于在本类中(在类的实现部分)。
self代表当前方法的调用者。在OC的类中,实现部分全部都是方法(声明部分无法使用self),有类方法和对象方法。如果外界对象调用对象方法时,self就代表这个对象;同样,调用类方法时,self就代表这个类。
所以,这句话简单的理解,就是:如果self所在的这个方法是类方法,那么self就代表当前类;如果是对象方法,self就代表当前类的对象。
在self表示本类对象的时候,就具备类对象的所有功能,可以使用self来调用类中的属性,例如:
self.name=@"ZhangSan";
当self表示本类的时候,可以用来调用其他类方法,相当于java 的this -
super
super和self的使用规则一样,不同之处在于:super指父类方法的调用者。而self指当前方法的调用者。相当于java 的super
@property的几种常用修饰词
- nonatomic:原名:非原子性,它涉及到多线程的相关知识。在这里我们只需要知道有nonatomic声明的属性,任何人任何地点任何时间都可以调用它(就是很多人可以同时使用它),所以它的缺点就是不安全,而优点就是效率高,访问速度快。
- atomic(默认):原子性。和nonatomic正好相反,他对属性的访问进行了限制,保护了声明属性的安全,缺点就是:访问效率低,速度慢。:可以类比java volatile
- copy:一般使用于字符串,它的特点如同它的中文翻译,将内容另外拷贝一份,保存在一个单独的存储空间中
- strong:强引用 类比java 强引用
- weak:弱引用 类比java 弱引用
- assign:我认为是其中最简单的,它应用于OC的基础数据类型(NSInteger、BOOL)和C语言中的基本数据类型(int,float,double,char)
- readwrite: 它代表这个属性即可以读,也可以写(可以调用它的get和set方法)
- readonly:和readwrite不同,它代表这个属性只能读,不能进行写操作(只能调用get方法,不能调用set方法)
OC的动态特性
格意思函数调用的叫法是不正确的,它走得消息机制,类似发送和接收,和>java 的对象函数key -v机制不一样,这也是为什么oc 不容易崩溃的原因,减少空对象
- 动态类型:指的就是:id类型。它可以表示任何类的对象。当我们无法知道数据的具体类型时,我们就可以将数据直接存储到id类型的对象中。
但是需要说明的是id是动态类型绝不仅仅因为它能够存储任何类的对象。主要的原因是:由于id类型在程序编译时无法确定其中具体存储的对象类型,只有在程序通过编译到达运行阶段时,才能确定id类型对象所存储的具体对象的类型。类比java 的泛型 - 动态绑定:
动态绑定,是基于动态类型的,简单的理解就是:只有在程序运行时才能确定对象的具体属性和方法,进而进行绑定。
当程序中包含id动态类型时,编译过程无法确定id类型代表哪个类的对象,也就无法确定id类型调用的是哪个方法。在程序编译阶段,编译器会在你的工程文件中查找id对象调用方法的方法名是不是存在,如果存在,编译通过;反之,程序报错,提示你没有找到对象的方法。\ - 动态加载: 动态加载,简单的理解就是在需要时才会加载
OC 的类别
类别的用途: 简单的说,就是如果我们想在一个类中增加一些可供外界调用的方法,但是又不想影响它的子类,我们就要用类别。类别能够在原有类的基础上添加新的方法,而且还不会让子类继承。这也是类别的优点所在
类别的创建:
原始类:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString * name;
@property (nonatomic,assign)int age;
-(void)run;
@end
#import "Person.h"
@implementation Person
-(void)run{
NSLog(@"the person is running!");
}
@end
类别类
#import "Person.h"
@interface Person (NewFuntion)
//添加方法
@end
#import "Person+NewFuntion.h"
@implementation Person (NewFuntion)
//实现方法
@end
使用的时候和正常的类使用是一致的
还是java好,主动权还是应该给到开发者,虽然这种方式做到了代码隔离
OC中的协议
和java 的接口是一样的,只是相关书写规则有差异;
#import <Foundation/Foundation.h>
@protocol ChildrenDelegate <NSObject>//协议声明
-(void)eat;
@end
@interface Children : NSObject
@property(nonatomic,weak)id<ChildrenDelegate>delegete;
@end
@protocol是定义协议的关键字,告诉编译器,要开始声明协议了。
ChildrenDelegate是协议的名字,规范命名为:类名+Delegate,多个协议在
<>用, 分开
在协议中,有几个方法的修饰词供我们使用:
@required(表示以下方法必须实现)
@optional(表示以下方法可以不实现)
如果不使用任何关键字修饰,默认情况下是@required。
使用和java 很像不再叙述
OC中的单例
和 java 的一样
h
#import <Foundation/Foundation.h>
@interface Car : NSObject
@property (nonatomic,assign)int driveHours;
+(instancetype)car;
@end
m
#import "Car.h"
static Car * car=nil; // 和java 的null类似
@implementation Car
+(instancetype)car{ //instancetype 和id 一样只是作用在方法上面
if (car==nil) {
car=[[Car alloc] init];
}
return car;
}
@end
oc 的常用数据类型
- OC对应-> JAVA 对应
- NSString -> String
- NSArray -> []
- NSDictionary -> Map
- int -> int
- float -> float
- char -> char
- bool -> bool
- NSNumber->integer
- NSValue -> 结构体转成对象
OC中的通知
类似Android 的广播接受器
#import "Worker.h"
@implementation Worker
-(instancetype)init{// 类似java的 构造函数
if (self=[super init]) {
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(makeCar) name:@"canMake" object:nil];
}
return self;
}
-(void)makeCar{
NSLog(@"Let's begin to make car,gogogo");
}
@end
#import <Foundation/Foundation.h>
#import "Worker.h"
int main(int argc, const char * argv[]) {
Worker * worker=[[Worker alloc] init];
[[NSNotificationCenter defaultCenter]postNotificationName:@"canMake" object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:worker name:@"canMake" object:nil];
return 0;
}
KVC和KVO
- kvc Key-Value-Coding,它是一种间接调取对象属性的方法。它的实现方式是通过字符串来自动找到要更改的对象属性。
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString * name;
@property (nonatomic,assign)int age;
@property (nonatomic,assign)int sex;
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person * person=[[Person alloc] init];
[person setValue:@"ZhangSan" forKey:@"name"];
[person setValue:[NSNumber numberWithInt:10] forKey:@"age"];
[person setValue:[NSNumber numberWithBool:YES] forKey:@"sex"];
NSLog(@"The person's name is :%@,and age is :%d, sex is :%d",person.name,person.age,person.sex);
return 0;
}
- kvo
Key-Value-Observer,键值观察(或键值监听)) 和Android databing 类似
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString * name;
@property (nonatomic,assign)int age;
@end
#import "Person.h"
@implementation Person
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"%@",change);
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person * person=[[Person alloc] init];
person.name=@"ZhangSan";
person.age=10;
[person addObserver:person forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[person addObserver:person forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
person.name=@"LiSi";
person.age=20;
[person removeObserver:person forKeyPath:@"name" context:nil];
[person removeObserver:person forKeyPath:@"age" context:nil];
return 0;
}
Block代码
类似java中 匿名内部类和js 的闭包:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
void (^helloWorld)(void);
// void 返回类型, (^helloWorld) 代码块称^ BLOCK标识,void 参数
helloWorld=^(void){ //helloWorld 名字^ 标识(void) 参数
NSLog(@"Hello World!");
};
helloWorld();//调用
return 0;
}
使用示例:
#import <Foundation/Foundation.h>
typedef void(^myBlock)(NSString * name,int age);
@interface Person : NSObject
-(void)exercise:(myBlock)block;
@end
#import "Person.h"
@implementation Person
-(void)exercise:(myBlock)block{
NSString * theName=@"ZhangSan";
int age=10;
block(theName,age);
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person * person=[[Person alloc] init];
[person exercise:^(NSString *name, int age) {
NSLog(@"%@,%d",name,age);// ZHANGSAN 10
}];
return 0;
}
内存管理
- ARC->GC
- 自动引用计数-> JAVA 自动引用计数