id和instanceType的区别
1、id 万能指针,对未知的类型一般都会使用id 来表示
2、instanceType 对象初始化 在构造函数中 建议使用
总结:
id 可以作为方法参数传递 intancetype 不能
id 可以去接受对象 instancetype不能
在自定义初始化或者便利构造方法中尽量使用instancetype作为返回值类型,保证类型安全
构造函数 写法
//一般的写法
-(id)initWithxx:(类型) xx{
if(self=[super init]){
//想初始化的操作
}
}
//有了instanceType之后的写法
-(instancetype)initWithxx:(类型) xx{
if(self=[super init]){
//想初始化的操作
}
}
协议 类别 和扩展
1、协议
//定义一个协议
@protocol AnimalDelegate <NSObject>
@required //必须实现的方法
-(void)eat;
@optional //可选实现的方法
-(void)run;
-(void)say;
-(void)sleep;
@end
--------------------------------------------
#import <Foundation/Foundation.h>
#import "AnimalDelegate.h"
@interface Person : NSObject<AnimalDelegate>
-(void)eat;
@end
-----------------------
#import "Person.h"
@implementation Person
-(void)eat{
NSLog(@"eating...");
}
@end
1、一个协议可以扩展自另一个协议,例如上面AnimalDelegate就扩展自NSObject,如果需要扩展多个协议中间使用逗号分隔;
2、和其他高级语言中接口不同的是协议中定义的方法不一定是必须实现的,我们可以通过关键字进行@required和@optional进行设置,如果不设置则默认是@required(注意ObjC是弱语法,即使不实现必选方法编译运行也不会报错);
3、协议通过<>进行实现,一个类可以同时实现多个协议,中间通过逗号分隔;
4、协议的实现只能在类的声明上,不能放到类的实现上(也就是说必须写成@interface Person:NSObject<AnimalDelegate>而不能写成@implementation Person<AnimalDelegate>);
5、协议中不能定义属性、成员变量等,只能定义方法;
2、类别
//
// NSString+Extend.h
// Protocol&Block&Category
//
// Created by Kenshin Cui on 14-2-2.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (Extend)
-(NSString *)stringByTrim;
@end
-----------------------------------
//
// NSString+Extend.m
// Protocol&Block&Category
//
// Created by Kenshin Cui on 14-2-2.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "NSString+Extend.h"
@implementation NSString (Extend)
-(NSString *)stringByTrim{
NSCharacterSet *character= [NSCharacterSet whitespaceCharacterSet];
return [self stringByTrimmingCharactersInSet:character];
}
@end
3、扩展
//person.h
#import <foundation foundation.h>
@interface Person : NSObject
- (instancetype)initWithName:(NSString*)aName;
- (void)print;
@property(nonatomic,strong) NSString *name;
@end
----------------------------------
#import Person.h
//定义一个Extension;
@interface Person ()
//对于普通变量,不能使用strong,retain,copy,只能使用assign;
@property(nonatomic,assign) int age;
//这是可以理解为private 类型的方法;只可以在该类@implementation内部调用;对外部不可见;
- (void)printName;
- (void)printAge;
@end
//类的实现文件;
@implementation Person
- (instancetype)initWithName:(NSString*)aName
{
//使用父类的方法来初始化对象;
self = [super init];
if (self) {
//设置该对象的属性值;
self.name = aName;
self.age = 23;
}
//这里返回出去的是一个对象;
return self;
}
- (void)print{
NSLog(@Person print);
[self printName];
[self printAge];
}
//实现Extension中定义的方法;
- (void)printName{
NSLog(@name:%@,self.name);
}
- (void)printAge{
NSLog(@name:%d,self.age);
}
@end
4、块
//
// KCButton.h
// Protocol&Block&Category
//
// Created by Kenshin Cui on 14-2-2.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import <Foundation/Foundation.h>
@class KCButton;
typedef void(^KCButtonClick)(KCButton *);//块类型
@interface KCButton : NSObject
#pragma mark - 属性
#pragma mark 点击操作属性
@property (nonatomic,copy) KCButtonClick onClick;
//上面的属性定义等价于下面的代码
//@property (nonatomic,copy) void(^ onClick)(KCButton *);
#pragma mark - 公共方法
#pragma mark 点击方法
-(void)click;
@end
--------------------------------------------------
//
// KCButton.m
// Protocol&Block&Category
//
// Created by Kenshin Cui on 14-2-2.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCButton.h"
@implementation KCButton
-(void)click{
NSLog(@"Invoke KCButton's click method.");
if (_onClick) {
_onClick(self);
}
}
@end
------------------------------------------------
//
// main.m
// Protocol&Block&Category
//
// Created by Kenshin Cui on 14-2-2.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "KCButton.h"
int main(int argc, const char * argv[]) {
KCButton *button=[[KCButton alloc]init];
button.onClick=^(KCButton *btn){
NSLog(@"Invoke onClick method.The button is:%@.",btn);
};
[button click];
/*结果:
Invoke KCButton's click method.
Invoke onClick method.The button is:<KCButton: 0x1006011f0>.
*/
return 0;
}
上面代码中使用Block同样实现了按钮的点击事件,关于Block总结如下:
1、Block类型定义:返回值类型(^ 变量名)(参数列表)(注意Block也是一种类型);
2、Block的typedef定义:返回值类型(^类型名称)(参数列表);
3、Block的实现:^(参数列表){操作主体};
4、Block中可以读取块外面定义的变量但是不能修改,如果要修改那么这个变量必须声明_block修饰;
@class 对象互相调用 防止编译问题 可以使用