1 面向过程部分
object-C是C的一个超集,所以下面列出两者之间的不同点
(1)NSLog输出函数的格式字符:%@表示输出ojbect-C对象,其余的和c语言一样
(2)BOOL类型: YES表示true, NO表示false ==>内部实现用的是signed char, 所以占一个字节
(3) #import,是对#include所作的优化,可以避免重复导入的问题
(4) 块(Block)
这个objc对ANSIC所做的扩展, 可以看成是匿名函数
^ [块返回值类型] (形参类型1 形参1, 形参类型2 形参2,…)
{
// 块执行体
}
例子:
void (^print)(NSString*);
print = ^(NSString* info){
NSLog(@"info 参数为: %@", info);
}
//调用
print("helloworld!");
块与局部变量:
- 系统在定义块的时候就会把局部变量的值保存在块中,而不是等到执行时才去访问
- 要想在块中改变局部变量的值,可以加上__block修饰变量
int var1= 10;
__block int var2 = 20;
void(^print)(void) = ^(void){
var1 = 11; // error
var2 = 21; // ok
}
(5)其余部分与ANSI C完全一样
2 面向对象部分
(1) 类的定义与实现
Person.h
@interface Person : NSObject
{
// (1)成员变量,Xcode4.0开始,建议成员变量以_开头命名
// (2)object-C里面不存在类变量
int _age;
NSString* _name;
}
// 实例方法(开头是-)
- (void) say : (NSString*)content;
// 下面定义了一个setName:andAge:方法
// objc建议第2个形参开始都带一个形参标签,用来表明这个形参的作用
- (void) setName:(NSString*)name andAge:(int)age;
// 类方法(开头是+)
+ (void) foo;
@end
Person.m
@implementation Person
{
// 这里体现了object-c接口与实现分离的特性,
// 这个变量只能在实现部分使用
int _testAttr;
}
- (void)setName:(NSString *)name andAge:(int)age{
_name = name;
_age = age;
}
- (void)say:(NSString *)content{
NSLog(@"%@", content);
}
// 这里体现了object-c接口与实现分离的特性,
// 这个方法只能在实现部分使用
- (void) test{
NSLog(@"只能在实现部分使用的方法");
}
+ (void) foo{
NSLog(@"通过类名调用的类方法");
}
@end
(2) 类的使用
// (1) 方法与函数不是一个概念
// (2) 函数可以独立存在
// (3) 方法要么属于类,要么属于对象,只能通过[对象 方法],[类 方法]来进行调用
Person* person = [[Person alloc] init];
[person say:@"helloworld"];
[person setName:@"小明" andAge:12];
[Personfoo];
(3) 访问控制符
objc里面有4个访问控制符
@public, @protected, @private以及@package, 前3个与c++是一致的
关于@package是作用域是“同一映像”,即:编译生成的同一个框架或同一个执行文件
(4) 合成存取方法
从object-C2.0开始,可以通过如下方法来自动合成成员变量的setter和getter方法
- 在类接口部分使用@property指定定义属性
- 在类实现部分使用@synthesize指令声明该属性即可
@interface User : NSObject
// property 额外指示符号
// atomic (noatomic): 合成是存取方法是否为原子操作
// copy: set的时候,是否拷一份再赋值
// assign: 只是简单的赋值,不改变引用计数
// readonly、readwrite
// retain: 引用计数改变(原来引用的对象计数减1,被赋值的加1), 启用ARC之后用不着这玩意
// strong、weak, 强引用(hold引用计数)与弱引用(不hold引用计数)
@property (nonatomic , copy) NSString* name;
@property int age;
@end
@implementation User
@synthesize name;
@synthesize age;
@end
使用方法:
User* user=[[User alloc] init];
[user setName:@"小明"];
NSLog(@"username: %@", [user name]);
// 通过点语法来访问
user.name=@"小强";
NSLog(@"通过点语法访问, user name:%@",user.name);
(5) 对象初始化
初始化一个对象分为两个过程:alloc -> init
所有object-C类都是NSObject的子类
NSObject有一个方法:alloc, 有如下作用:
- 为该对象的所有实例变量分配 内存空间
- 将每个实例变量的内存空间都重置为0。
-- 整型置为0
-- 浮点置为0.0
-- BOOL置为NO
-- 指针置为nil
可以在重写NSObject的init方法,用来完成自定义初始化
- (id) init{
if(self == [super init]){
// 自定义初始化
}
returnself;
}
(6) 继承与多态
- Object-C 只能单继承
- 在子类中可以通过super来找寻父类的方法与变量
- 多态与c++类似
- 指针变量的类型强转: (type*)variable
- 判断指针变量的实际类型,例子:
[helloisKindOfClass: [NSObject class]]
[helloisSubClassOfClass: [NSObject class]]
(7) 类别(category)与扩展(extension)
- 比如给上面的User类新增一个学生类别, 添加addSchool方法
// 扩展方法
@interface User(student)
-(void) addSchool:(NSString*) school;
@end
@implementation User(student)
- (void) addSchool:(NSString *)school{
NSLog(@"%@", school);
}
@end
- 扩展与类别相似,相当于匿名类别
// 扩展方法
@interface User()
-(void) addSchool:(NSString*) school;
@end
@implementation User()
- (void) addSchool:(NSString *)school{
NSLog(@"%@", school);
}
@end
(8) 协议与委托
- 协议的定义
@protocol 协议名 <父协议1, 父协议2, ...>
@required
// 方法声明
@optional
// 方法声明
@end
- 协议的实现
@interface 类名 : 父类 <协议1, 协议2,...>
@end
- 例子
// 输出
@protocol Output
- (void) output;
- (void) addData: (NSString*) msg;
@end
// 生产信息
@protocol Productable
- (NSDate*) getProduceTime;
@end
// 可打印
@protocol Printable <Output, Productable>
- (NSString*) printColor;
@end
// 打印机
@interface Printer : NSObject <Printable>
@end
@implementation Printer
- (void) output{
NSLog(@"output");
}
- (void) addData: (NSString*) msg{
NSLog(@"addData");
}
- (NSDate*) getProduceTime{
return [[NSDate alloc] init];
}
- (NSString*) printColor{
return @"红色";
}
@end
如果程序需要使用协议来定义变量,有如下两种方法:
NSObject<协议1, 协议2,...>* 变量;
id<协议1, 协议2, ...> 变量;
- 委托是一种设计模式,类似代理模式