版本
Objective-C有两个版本1.0和2.0,macos 10.5(2005年)及以后的系统都是2.0,所有iOS系统使用的都是2.0,提供了__OBJC2__可以判断版本。
格式
@符号
OC新增的关键词大部分是以此符号开头
头文件 使用#import ""
文件后缀 h-头文件,m-实现文件,mm-包含OC和C++的文件。
#import
int main(int argc, char *argv[]){
@autoreleasepool{
NSLog(@"Hello World!");
}
return 0;
}
数据类型和API
NS前缀
一般是指来自NextStep的系统API。
NSString
NSString* strA = @"aaa";
NSLog(@"strA=%@", strA); //打印格式
NSInteger/NSUInteger
#if __LP64__ || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
Apple的UIKit代码一般都用的是NSInteger,NSInteger在32系统是int,64位系统是long,兼容性更好。
要注意把NSInteger转换成int时可能会溢出。
NS_ENUM
NS_ENUM是一个OC中的宏,可以指定底层数据类型,是对enum的一种封装,在OC中,几乎不使用enum
typedef NS_ENUM(NSInteger, FlyState) {
FlyStateOne,
FlyStateTwo,
FlyStateThree
};
FlyState state = FlyStateOne;
NS_OPTIONS
在NS_ENUM的基础上,使得按位或计算的结果能够返回正确的数据类型。
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
NSLog
NSLog(@"Hello World");
2021-10-09 16:49:58.733819+0800 RTCSolution[250:4239] [MC] Reading from public effective user settings.
时间 + 程序名 + [进程号:线程号] + 输出信息。
autoreleasepool
用途待补充。
NSObject
基础类。NSObject既是protocol,又是interface,定义见 NSObject.h
@protocol NSObject
//...
@end
@interface NSObject
//...
@end
id
注意id是一种类型,相当于指向NSObject的指针,因而能用于指向所有类类型的变量。
instancetype
instancetype的作用,就是使那些非关联返回类型的方法返回所在类的类型,好处是能够确定对象的类型,能够帮助编译器更好的为我们定位代码书写问题。
布尔类型
C语言标准中没有定义布尔类型,但提供了一个头文件定义布尔类型,方便使用
#include
bool flag = true;
bool flag = false;
C++标准默认包含了boo类型,用法同上。
objective-c中定义了多种布尔类型,一般建议使用BOOL
Name |
Typedef |
Header |
True Value |
False Value |
BOOL |
signed char |
objc.h |
YES |
NO |
bool |
_Bool (int) |
stdbool.h |
true |
false |
Boolean |
unsigned char |
MacTypes.h |
TRUE |
FALSE |
NSNumber |
__NSCFBoolean |
Foundation.h |
@(YES) |
@(NO) |
语法规则
interface
类的定义以关键词interface开始,以end结束
@interface MyClass : NSObject
- (void) sayHello;
- (void) sayHelloWithParaA:(NSString* _Nonnull)paraA
paraB:(NSString* _Nonnull) paraB;
@end
类成员
包含类成员的的定义
interface{}可以定义变量,权限默认为protected, implementation{}也可以定义变量,权限为private。
objective-2.0引入了property,方便getter/setter类变量的使用。
property属性
@property(copy) NSString* name;
@property(readonly) int age;
property的特性在2006年wwdc发布,把原来的实例变量定义成properties属性。
成员变量需要手动声明setter和getter,其他类也可以通过->
访问。
从xcode4.5开始,property不需要再添加@synthesize来合成。
//最短写法
@property BOOL isOpen;
//最复杂的写法
@property (nonatomic, readonly, copy, getter=theNewTitle, setter=setTheNewTitle:, nullable) NSString *newTitle;
类实现implementation
implementation
@implementation MyClass
- (void)sayHello {
NSLog(@"say hello");
}
- (void) sayHelloWithParaA:(NSString* _Nonnull)paraA paraB:(NSString* _Nonnull) paraB {
NSLog(@"paraA=%@, paraB=%@", paraA, paraB);
}
@end
类方法&实例方法
类似Java中的Static Method,不需要实例化就能使用,标志是前面的 +
普通的对象方法前面是-
传递消息/对象方法调用
类/对象的方法调用,用OC的说法是传递消息
普通的函数调用同C,对于类或对象的方法,调用格式如下:
[mycls sayHello];
[mycls sayHelloWithParaA:strA paraB:strB];
protocol协议
类似java中的interface,特点:
协议中可以定义可选的方法,也就是非必须实现的方法,关键词是optional
@protocol Printable
-(void)print:(NSString*)str;
@optional
-(void)sayHello:(NSString*)str;
@required //不加optional默认即为required
-(void)sayName:(NSString*)name;
@end
@interface MyClass : NSObject //实现类可以实现多个protocol
@end
category分类
给一个已经存在的类增加方法,而不用去修改类本身的源码,即使开发者没有该类的源码也可以如此使用。
NSObject+Json+XML.h 定义
@interface NSObject (Json)
-(NSString)toJson;
@end
@interface NSObject (XML)
-(NSString)toXML;
@end
NSObject+Json+XML.m 实现
@implementation NSObject (Json)
-(NSString)toJson {
//...
}
@end
@implementation NSObject (XML)
-(NSString)toXML {
//...
}
@end
main.m 使用
#import "NSObject+Json+XML.h"
@implementation XYZController
-(void)test {
NSObject *obj = [[NSObject alloc]init];
NSString *json = [obj toJson];
NSString *xml = [obj toXML];
}
@end
Extension扩展
扩展不仅可以添加新的方法,还可以添加实例变量,都是private。
使用扩展时,类名后的小括号中不添加任何东西。
扩展中声明的方法必须在相应类的implementation代码中实现。
// 如下代码位于 MyClass.h 文件中
@interface MyClass : NSObject
- (float)value;
@end
// 如下代码位于 MyClass.m 文件中
@interface MyClass () { // 扩展
float value;
}
- (void)setValue:(float)newValue;
@end
// 实现
@implementation MyClass
- (float)value {
return value;
}
- (void)setValue:(float)newValue {
value = newValue;
}
@end
class关键词
在一些代码的开头文件有这样的用法
//ClassA.h
@class ClassB
//ClassB.h
@class ClassA
用于两个头文件相互引用的时候,避免死循环,编译报错。
其中一方,不要使用@#import引入对方的头文件,而使用class关键词。
block闭包
OC语言对闭包的实现。闭包允许一个函数访问声明该函数运行上下文中的变量。
//定义一个函数,入参是blcok
void logBlock(int (^theBlock)(int para)) {
NSLog(@"Closure var X:%i", theBlock(1));
}
//main()
//定义block变量,变量名字为myBlock
int(^myBlock)(int);
int x = 42;
//block变量赋值
myBlock = ^(int i) {
return i + x;
};
logBlock(myBlock); //输出Closure var X:43
参考上面的例子,定义了一个myBlock变量,入参是一个int型,返回值也是int型。
然后将一个声明的block赋值给myBlcok,在这个实现函数中访问了main()函数上下文定义的局部变量x=42
调用logBlock函数时,将myBlock作为入参传入,在logBlock函数内部虽然没有定义x变量,但是仍然可以访问x。这里在闭包函数内部默认做了一次复制操作,保证可以正常访问到x。
NULL/nil
标志 |
值 |
含义 |
NULL |
(void *)0 |
一般赋给C指针变量 |
nil |
(id)0 |
Objective-C 对象的字面空值 |
Nil |
(Class)0 |
Objective-C 类的字面空值 |
NSNull |
[NSNull null] |
用来表示空值的 Objective-C 对象 |
这里Class不了解
箭头运算符和点运算符
箭头运算符(->)从C继承,用法同C,比如对象是一个指针,访问对象的变量就可以用obj->name。
点运算符(.)除了C中的用法,也用于getter和setter方法,等号左边就是setter方法,等号右边就是getter方法。
NSLog(@"name = %@", obj.name); //调用了getter方法
NSLog(@"name = %@", [obj name]);
obj.name = @"Jim"; //调用了setter方法
[obj setName:@"Jim"];
ARC
自动引用计数。(Automatic Reference Counting)在iOS 5引入,时间是2011 WWDC。
作用域修饰符private/public/protected
指令 |
意思 |
@private |
作用范围只能在自身类 |
@protected |
作用范围在自身类和继承自己的子类,什么都不写,默认是此属性。 |
@public |
作用范围最大,在任何地方 |
@interface Boss : NSObject {
@public
NSString* name;
@private
int age;
@protected
NSString *job;
}
@end
pragma mark
纯粹代码阅读方便,不影响编译
#pragma mark - 接口主类
#pragma mark -
OC面向对象特性
- interface用于定义类
- implementation用于类的实现
- property用于定义属性
- 也可以直接定义成员变量。
- 成员函数。可以定义+型类成员函数,也可以定义-型对象成员函数。
- protocol用于定义类似Java的interface,里面可以定义必须实现和可选实现的方法。
- protocol可以继承其他的protocol,类可以实现多个protocol
- category分类可以给一个类添加方法,这个类可以没有源码。category有自己的名字。
- extension扩展不仅可以添加方法,也可以添加实例变量。新增加的方法必须在类中实现,用于声明私有属性,私有方法,私有成员变量。
问题记录
1 category和extension的适用场合。
可参考 https://www.jianshu.com/p/6e8a398b9c0b
2 m文件的implementation中可否定义没有在interface中声明的方法?比如RTCSampleChatViewController的initializeSDK。测试了一下可以,这样的方法可以被内部其他方法调用,但是没有声明在头文件中,不可被外部调用。
3 OC的对象构造和析构规则是什么alloc init创建的对象,怎么释放?
参考资料
NS_ENUM