Objective-C是C语言的超集,完全兼容标准C语言并在其基础上添加了面向对象,消息机制以及反射等。 IDE 选择Xcode
、vsCode
等,先敲个简单的"hello world":
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]){
@autoreleasepool{
NSLog(@"Hello World!");
}
return 0;
}
代码说明:
#import <Foundation/Foundation.h>
和C语言include
相似,不同的是import
会自动防止重复包含。
Foundation.h
头文件中包含的是macOS系统提供的基础框架的接口声明。
@autoreleasepool
是Objective-C中用于管理内存的机制,在其包含的代码块中申请内存位于本线程的一个自动释放的内存池上,会在内存池销毁的时候自动回收。
字符串字面量在 Objective-C 是这么表示的@"strings"
不像C中是个char数组而是一个 NSString
类。
编译命令:
# objc 编译时指定导入的framework
clang -framework Foundation hello.m -o hello.o
Objective-C的面向对象语法源自 SmallTalk,消息传递(Message Passing)风格。在代码风格方面,这是它与C Family语言(包括C/C++、Java、PHP)差别最大的地方。
在 oc 中,强制要求将类分为声明interface
和实现implementation
两个部分。声明放在 .h
文件,实现放在 .m
文件中。
在 oc 中大部分类都是直接或间接的继承 NSObject
。这个类遵循 NSObject
协议,提供了一些通用的方法(初始化、垃圾回收等),通过继承 NSObject
,可以从其中继承访问运行时的接口,并让对象具备 objc 对象的基本能力。
// @interface 定义类(Hello)
@interface ClassName: NSObject
// @property 定义属性
@property property_type *property_name;
@property property_type property_name;
+ (return_type) class_method; // 类方法
- (return_type) instance_method1; // 一般的实例方法
- (return_type) instance_method2: (int) p1; // 单个参数
- (return_type) instance_method3: (int) p1 andPar: (int) p2; // 多个参数
@end
// @implementation 实现类(ClassName)
@implementation ClassName : NSObject
+ (return_type)class_method {
// TODO
}
- (return_type)instance_method1{
// TODO
}
- (return_type)instance_method2: (int) p1 andPar: (int) p2{
// TODO
}
@end
Interface
, Implementation
定义的实体变量两者区别在于访问权限的不同;
protected
private
在 Implementation
区段定义私有成员更符合面向对象之封装原则,因为如此类别之私有信息就不需曝露于公开 interface
(.h
文件)中。
// @protocol 声明协议(MyProtocol)
@protocol MyProtocol
// 默认为 @required 强制
- (void)bar;
@optional // 可选
- (void)foo;
@end
// 使用协议
@interface MyPro : NSObject <MyProtocol>
- (void)bar;
@end
MyObject *my = [[MyObject alloc]init];
MyObject *my = [MyObject new];
自定义初始化:
- (id) init {
if ( self=[super init] ) { // 必须调用父类的init
// do something here ...
}
return self;
}
block声明:returnType (^blockName)(argumentType1, argumentType2, ...);
block实现:
returnType (^blockName)(argumentType1, argumentType2, ...) = ^(argumentType1 param1, argumentType2 param2, ...){
//do something here
};
// 定义一个 callbackLogger 块类型
typedef void (^callbackLogger)(void);
// 作为一个函数的参数
void genericLogger(callbackLogger blockParam) {
blockParam();
NSLog(@"%@", @"This is my function");
}
int main(int argc, char *argv[]) {
@autoreleasepool {
// exmaple 1:将一个值乘以2
int (^multiply)(int) = ^(int a) {
return a * 2;
};
NSLog(@"Multiply x2: %d", multiply(3));
// exmaple 2:作为函数参数
callbackLogger myLogger = ^{
NSLog(@"%@", @"This is my block");
};
genericLogger(myLogger);
// exmaple 2.1: inline 调用
genericLogger(^{
NSLog(@"%@", @"This is my second block");
});
}
return 0;
}
NSString
,NSMutableString
// NSString
NSString *myStr1 = [[NSString alloc] initWithCString:"Lord of The Rings"
encoding:NSUTF8StringEncoding];
NSString *myStr2 = [NSString stringWithCString:"Dune"
encoding:NSUTF8StringEncoding];
NSString *combine = [NSString
stringWithFormat:@"%@ is a great book and %@ is also a great book",
myStr1, myStr2];
NSLog(combine);
// NSMutableString
NSMutableString *mut = [NSMutableString stringWithString:@"This is"];
[mut appendString:@" a mutable string"];
NSLog(mut);
NSNumber
// character literals.
NSNumber *theLetterZ = @'Z'; // equivalent to [NSNumber numberWithChar:'Z']
// integral literals.
NSNumber *fortyTwo = @42; // equivalent to [NSNumber numberWithInt:42]
NSNumber *fortyTwoUnsigned =
@42U; // equivalent to [NSNumber numberWithUnsignedInt:42U]
NSNumber *fortyTwoLong =
@42L; // equivalent to [NSNumber numberWithLong:42L]
NSNumber *fortyTwoLongLong =
@42LL; // equivalent to [NSNumber numberWithLongLong:42LL]
// floating point literals.
NSNumber *piFloat =
@3.141592654F; // equivalent to [NSNumber numberWithFloat:3.141592654F]
NSNumber *piDouble =
@3.1415926535; // equivalent to [NSNumber numberWithDouble:3.1415926535]
// // BOOL literals.
NSNumber *yesNumber = @YES; // equivalent to [NSNumber numberWithBool:YES]
NSNumber *noNumber = @NO; // equivalent to [NSNumber numberWithBool:NO]
NSLog(@"%@, %@, %@, %@, %@, %@, %@, %@, %@", theLetterZ, fortyTwo,
fortyTwoUnsigned, fortyTwoLong, fortyTwoLongLong, piFloat, piDouble,
yesNumber, noNumber);
NSArray
,NSMutableArray
// NSArray 初始化
NSArray *array1 = [NSArray arrayWithObjects:@"one", @"two", @1, nil];
NSArray *array2 = @[ @"Hello", [NSNumber numberWithInt:42] ];
NSArray *array3 = @[ @"1", @"one", @"3", @4, @"ONE" ];
NSLog(@"array1=%@ \\n array2=%@ \\n array3=%@", array1, array2, array3);
// NSMutableArray 初始化
NSMutableArray *myMutantArray = [NSMutableArray array];
// 添加元素
[myMutantArray addObject:@"Leonardo"];
[myMutantArray addObject:@"Raphael"];
[myMutantArray addObject:@"Donatello"];
[myMutantArray addObject:@"Michalangelo"];
// 修改元素
[myMutantArray replaceObjectAtIndex:0 withObject:@"turtle"];
NSLog(@"myMutantArray=%@", myMutantArray);
NSDictionary
,NSMutableDictionary
// NSDictionary @{} 初始化
NSDictionary *someDictionary1 = @{
@"key1" : @42,
@"key2" : @"Some string",
@"key3" : myMutantArray,
@"key4" : myStr1
};
// NSDictionary 快速枚举
for (id key in someDictionary1) {
id obj = [someDictionary1 objectForKey:key];
NSLog(@"someDictionary1.%@=%@", key, obj);
}
// NSDictionary dictionaryWithObjectsAndKeys 初始化
NSDictionary *someDictionary2 = [NSDictionary
dictionaryWithObjectsAndKeys:@42, @"key1", @"Some string", @"key2",
myMutantArray, @"key3", myStr1, @"key4",
nil];
NSLog(@"someDictionary2=%@", someDictionary2);
// NSDictionary objectForKey 获取元素
NSNumber *theAnswerForEverything = [someDictionary2 objectForKey:@"key1"];
NSLog(@"someDictionary2.key1 = %@", theAnswerForEverything);
// NSMutableDictionary
// NSMutableDictionary 初始化
NSMutableDictionary *myMutantDictionary = [NSMutableDictionary dictionary];
// NSMutableDictionary setObject 添加元素
[myMutantDictionary setObject:@1 forKey:@"newkey"];
[myMutantDictionary setObject:@2 forKey:@"newkey1"];
[myMutantDictionary setObject:@100 forKey:@"newkey2"];
// NSMutableDictionary 修改元素1
myMutantDictionary[@"newkey1"] = @45;
// NSMutableDictionary 修改元素2
[myMutantDictionary setValue:@46 forKey:@"newkey"];
// NSMutableDictionary removeObjectForKey 删除元素
[myMutantDictionary removeObjectForKey:@"newkey2"];
NSLog(@"myMutantDictionary = %@", myMutantDictionary);
// 初始化 NSFileManager
NSFileManager *fileManager = [NSFileManager defaultManager];
// fileExistsAtPath 判断路径是是否存在
if ([fileManager fileExistsAtPath:@"/tmp/zznQ.txt"] == YES) {
NSLog(@"File exists");
} else {
NSLog(@"File not exists");
}
// contentsEqualAtPath 比较两个文件的内容
if ([fileManager contentsEqualAtPath:@"/tmp/file1.txt"
andPath:@"/tmp/file2.txt"] == YES) {
NSLog(@"File contents match");
}
// copyItemAtPath 复制一个文件
if ([fileManager copyItemAtPath:@"/tmp/file1.txt"
toPath:@"/tmp/file2.txt"
error:nil] == YES) {
NSLog(@"Copy successful");
}
// 移动文件
// moveItemAtPath:toPath:error:
// 删除文件
// removeItemAtPath:error:
// 文件管理器接受 NSURL 类型参数的版本来定位资源。
// copyItemAtURL:toURL:error:
// removeItemAtURL:error:
// NSURL
// fileURLWithPath 创建NSURL对象
NSURL *fileSrc = [NSURL fileURLWithPath:@"/tmp/file1.txt"];
NSURL *fileDst = [NSURL fileURLWithPath:@"/tmp/file2.txt"];
[fileManager moveItemAtURL:fileSrc toURL:fileDst error:nil];
// 快捷的写入文件方式
NSString *tmp = @"something temporary";
[tmp writeToFile:@"/tmp/tmp1.txt"
atomically:YES
encoding:NSASCIIStringEncoding
error:nil];
// NSURL版本:writeToURL:atomically:encoding:error:
// 通过 NSFileHandle 写入文件
NSFileHandle *fileHandle =
[NSFileHandle fileHandleForWritingAtPath:@"/tmp/tmp2.txt"];
// 内容追加到文件末尾
[fileHandle seekToEndOfFile];
[fileHandle writeData:[tmp dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
}