load和initalize
load是类的加载,在应用程序的生命周期内只会调用一次,而且是先执行父类的load方法再执行子类的load方法,load方法是根据方法的内存地址调用的
init是在类第一次接收到消息的时候调用的,每个类初始化一次他的父类的initalize方法就会调用一次,也是先调用父类再调用子类,initalize是通过objc_msgSend调用的,子类没有实现会调用父类的,分类实现了会覆盖父类的
深拷贝和浅拷贝
深拷贝:创建一个新的指针,并开辟新的内存空间,内容拷贝自原指针指向的内存,并指向它
浅拷贝:只创建一个新的指针,指向原指针指向的内存
mutableCopy -->不管原来的对象是什么类型,拷贝后返回的都是 可变对象
copy -->不管原来的对象是什么类型 拷贝后返回的都是 不可变对象
是否产生新的对象:
只有不可变对象的 copy方法,才不产生新的对象,其他的都会产生新对象
拷贝的类型区分:
不产生新对象的拷贝就是浅复制,其他都是深复制
对集合类进行mutableCopy时,虽然新建了个集合类对象,但是集合内存储的元素内存地址没有变化。也就是说深拷贝值只能拷贝对象本身,对象内部元素仍然是浅拷贝
可以通过以下方法实现深拷贝
NSMutableArray *arr2 = [[NSMutableArray alloc]initWithArray:arr copyItems:YES];
属性和成员变量
@interface Person : NSObject
{
NSString *_sex;//成员变量
}
@property (nonatomic, copy) NSString *name;//属性
@end
1. 成员变量的默认修饰是@protected。
2. 成员变量不会自动生成set和get方法,需要自己手动实现。
3. 成员变量不能用点语法调用,因为没有set和get方法,只能使用->调用。
1. 属性的默认修饰是@protected。
2. 属性会自动生成set和get方法。
3. 属性用点语法调用,点语法实际上调用的是set和get方法
分类和类的扩展
分类
1、分类里面可以定义@property属性,但是不会自动生成set和get方法,以及对应的成员变量
2、分类不能添加成员变量,但是可以通过关联对象的方式添加成员变量
3、分类中有和原有类同名的方法, 会优先调用分类中的方法
4、多个分类中同名方法,优先调用后面参与编译的分类里面的方法
扩展
1、为一个类声明一些额外的方法和属性
2、常用在.m文件中添加一些私有属性。创建viewcontroller文件时会自动在.m文件内最上面实现扩展代码
关联对象举例
.h中写法
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^ButtonClickBlock)(void);
typedef void(^CanShuBlock)(int status);
@interface UIButton (Additions)
@property(nonatomic,copy)ButtonClickBlock clickBlock;
@property(nonatomic,copy)CanShuBlock canShuBlock;
@property(nonatomic,strong)NSString * buttonStr;
- (void)addClickBlock:(void (^)(void))block forControlEvents:(UIControlEvents)controlEvents;
-(void)addCanShuClick:(void(^)(int status))block forControlEvents:(UIControlEvents)controlEvents;
@end
NS_ASSUME_NONNULL_END
.m种写法
#import "UIButton+Additions.h"
static void * clickBlockKey = &clickBlockKey; //关联对象要用到的key
static NSString * buttonStrKey = @"buttonStr";
static int * canShuKey = &canShuKey;
@implementation UIButton (Additions)
-(void)setClickBlock:(ButtonClickBlock)clickBlock
{
//使用关联对象进行绑定
objc_setAssociatedObject(self, &clickBlockKey, clickBlock, OBJC_ASSOCIATION_COPY);
}
-(ButtonClickBlock)clickBlock
{
//用来读取对象
return objc_getAssociatedObject(self, &clickBlockKey);
}
-(void)setCanShuBlock:(CanShuBlock)canShuBlock
{
//使用关联对象进行绑定
objc_setAssociatedObject(self, &canShuKey, canShuBlock, OBJC_ASSOCIATION_COPY);
}
-(CanShuBlock)canShuBlock
{
//用来读取对象
return objc_getAssociatedObject(self, &canShuKey);
}
-(void)setButtonStr:(NSString *)buttonStr
{
objc_setAssociatedObject(self,&buttonStrKey, buttonStr, OBJC_ASSOCIATION_COPY);
}
-(NSString *)buttonStr
{
return objc_getAssociatedObject(self, &buttonStrKey);
}
/**
给按钮绑定事件回调block
@param block 回调的block
@param controlEvents 回调block的事件
*/
- (void)addClickBlock:(void (^)(void))block forControlEvents:(UIControlEvents)controlEvents {
self.clickBlock = block;
[self addTarget:self action:@selector(cq_blcokButtonClicked) forControlEvents:controlEvents];
}
// 按钮点击
- (void)cq_blcokButtonClicked {
if (self.clickBlock) {
self.clickBlock();
}
}
-(void)addCanShuClick:(void(^)(int status))block forControlEvents:(UIControlEvents)controlEvents
{
self.canShuBlock = block;
[self addTarget:self action:@selector(canShuBlockClick) forControlEvents:controlEvents];
}
-(void)canShuBlockClick
{
__weak typeof(self)welkSelf = self;
if (self.canShuBlock) {
welkSelf.canShuBlock(20);
}
}
@end
调用举例
UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
button.backgroundColor = [UIColor redColor];
button.buttonStr = @"123";
[button addClickBlock:^{
NSLog(@"click 事件执行");
} forControlEvents:UIControlEventTouchUpInside];
[button addCanShuClick:^(int status) {
} forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
成员变量,属性变量,全局变量,局部变量
@interface MakerViewController ()
{
/*
name和score都是成员变量,成员变量用于类内部,无需与外界接触的变量。因为成员变量不会生成set、get方法,所以外界无法与成员变量接触,
成员变量 只能 通过类对象来访问
注意 : 成员变量 不能离开类, 离开类 之后就不是 成员变量
成员变量 不能声明的同时进行初始化
存储 : 堆 (当前对象对应的堆的存储空间中)
// 存储在堆中的数据, 不会被自动释放,只能程序员 手动释放
*/
NSString * name;//成员变量(实例变量) 实例变量本质上就是成员变量,只是实例是针对类而言,如果变量的数据类型是一个类则称这个变量为实例变量
int score;//成员变量
}
@property(nonatomic,strong)NSArray * sourceArray;//属性变量(用@property声明会自动生成成员变量和get,set方法),属性变量的好处就是允许让其他对象访问到该变量(因为属性创建过程中自动产生了set 和get方法)。当然,你可以设置只读或者可写等,设置方法也可自定义。所以,属性变量是用于与其他对象交互的变量。
@end
@implementation MakerViewController
/*
// 写在函数 和 大括号外部的变量 , 我们称呼为全局变量
// 作用域 : 从定义的哪一行开始, 一直到文件末尾
// 局部变量 可以先定义再初始化, 也可以定义的同时 初始化
// 存储 : 静态区
// 程序已启动 就会分配存储空间, 直到程序结束才会释放
*/
int age = 20;//全局变量
- (void)viewDidLoad {
[super viewDidLoad];
/*
(栈) 局部变量 : 存储在 栈中的 数据有一个特点, 系统会自动给我们释放
(静态区) 全局变量 : 程序已启动 就会分配存储空间, 知道程序结束才会释放
(堆) 成员变量 : 存储在堆中的数据, 不会被自动释放,只能程序员 手动释放
*/
int sex = 1;//局部变量
NSLog(@"%d",sex);
}
@synthesize和@property
@property(nonatomic,strong)NSArray * sourceArray;//属性变量
@property 声明一个属性变量,编译器会自动生成set和get方法,并且会生成一个实例变量(成员变量的一种)_sourceArray,我们在调用属性变量sourceArray的时候可以通过self.sourceArray和_sourceArray调用(self.sourceArray其实等同于_sourceArray)
@synthesize sourceArray;
这个声明之后我们可以通过sourceArray调用sourceArray属性变量(这里的sourceArray其实等同于self.sourceArray,但是不能通过_sourceArray调用了)
想要可以通过sourceArray、_sourceArray都可以调用sourceArray属性变量,可以通过如下下写法实现
@synthesize sourceArray = _sourceArray;
ios framework
“静态库” 链接时候完整的拷贝至可执行文件中,被多次使用就会有多次拷贝。
“动态库” 链接时候不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存!
静态库形式: .a和.framework
动态库形式: .dylib和.framework
.a和framework的区别
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a + .h + sourceFile = .framework。