IOS objective-c程式設計簡單入門
文章目錄
準備工作
- 購買蘋果電腦.
或者, 使用虛擬機器(vmware)安裝黑蘋果, 作業系統至少10.13.4. 反正是越新越好, 否則, 安裝不了新版的xcode. 這個方式比較艱難, 會出現各種奇怪的錯誤, 要到百度上搜索解決方法. - 申請蘋果賬號(Apple ID)
- 安裝xcode, 版本至少9.4. 也是越新越好.
建立xcode專案
雖然有swift新語言, 但很多開源庫仍然是objective-c, 而且objective-c更容易和c/c++混合程式設計.
先建立一個xcode工程, 這個太簡單了. (以下圖片是通過快捷鍵command+shift+3截圖的)
xcode -> Fle -> New -> Project
選擇macOS -> Command Line Tool型別
基本語法
objective-c是C語言的超集, 支援C語言, 同時也是面象物件的語言. 學過C語言, 然後又學過C++或Java的程式設計師上手應該很快.
知識點: 類的宣告和實現
#import <Foundation/Foundation.h> //宣告 @interface MyObject : NSObject { //預設為protected, 其它的物件無法訪問 int member; } // +表示靜態函式, -表示成員函式。 // c++/java程式設計師對這兩種型別的函式應該很熟悉了 //p1為第1個引數, p2為第二個引數; param2相當於p2的暱稱, //呼叫這個函式時,也必須這樣寫。 比如 [MyObject staticFun: 1 param2:2]; //引數之間是用空白符分開的, c/c++/java都是用逗號分開的 +(int) staticFun: (int) p1 param2: (int) p2; //init是預設建構函式. instancetype可以理解為當前物件的型別 // 返回instancetype型別的函式,都可以理解為建構函式, 也可以新增帶引數的建構函式. //如果不需要初始化,也可以省略掉預設構造方法 //objective-c建立建立物件時,會預設將記憶體清0 -(instancetype) init; //銷燬物件時,會呼叫這個方法。 //如果沒有需要手動釋放的資源,可以省略掉這個函式 -(void) dealloc; -(int) member; -(void) setMember: (int) value; @end //實現 @implementation MyObject +(int) staticFun: (int) p1 param2: (int) p2 { return p1 + p2; } //init是預設建構函式,返回instancetype型別的函式,都可以理解為建構函式 //如果不需要初始化,也可以省略掉預設構造方法 -(instancetype) init { NSLog(@"default constructor"); return self; } //普通成員函式 -(int) member { return self->member; } - (void) setMember: (int) value { self->member = value; } -(void) dealloc { [super dealloc]; NSLog(@"default deconstructor"); } @end
類的使用方法如下:
//呼叫靜態方法
int ret =[MyObject staticFun:1 param2:2];
NSLog(@"staticFun: %d", ret);
//構造物件
MyObject* obj = [[MyObject alloc] init];
//呼叫方法
[obj setMember:123];
ret = [obj member];
NSLog(@"get member: %d", ret);
//釋放物件, 如果開啟了“自動引用數”,系統會釋放掉這個物件,不需要手動呼叫
//[obj release];
分類和擴充套件
objective-c可以通過繼承來建立一個新的類, 也可以通過分類和擴充套件這兩種方式來為原有的類新增新功能
分類Categories
可以為已有的類新增新的方法, 但是不能新增成員變數
@interface NSString (Test)
-(NSString*) myFunc;
@end
@implementation NSString (Test)
-(NSString*) myFunc
{
return @"test categorys";
}
@end
//測試
NSString* str = @"my";
NSLog(@"%@", [str myFunc]);
擴充套件Extensions
objective-c還支援別外一種方式來擴充套件介面, 如下:
在.h中宣告一些可以暴露的程式碼
@interface MyExtension : NSObject
{
int m;
}
@end
在.m中宣告內部的一些成員
@interface MyExtension()
-(void) myPrivteFunc;
@end
@implementation MyExtension
-(void) myPrivteFunc
{
NSLog(@"my private func");
}
@end;
在xcode的程式碼自動補全列表, 不會顯示myPrivteFunc方法, 從而達到隱藏程式碼的效果. (其實, 也可以強行呼叫.)
@property
上例中, 有一個成員變數member, 為了能夠設定和讀取它的值, 又添加了兩個相關的成員方法. objective-c提供了@property關鍵字, 來讓編譯器自動處理這個問題. 相當於一個高階的語法糖.
@interface MyProperty : NSObject
//編譯會自動生成一個成員變數_myProperty,
// 再生成myProperty方法, 用於讀取_myProperty的值
// 還生成setMyProperty方法, 用於設定_myProperty的值.
@property int myProperty;
@end
@implementation MyProperty
@end
等價於以下這種形式
@interface MyProperty2 : NSObject
{
int _myProperty;
}
-(int) myProperty;
-(void) setMyProperty:(int)myProperty;
@end
@implementation MyProperty2
-(int) myProperty
{
return self->_myProperty;
}
-(void) setMyProperty:(int)myProperty
{
self->_myProperty = myProperty;
}
使用方式
int ret;
MyProperty* obj = [MyProperty new];
[obj setMyProperty:123];
ret = [obj myProperty];
NSLog(@"get member: %d", ret);
為了使用@property的功能更強大, ojbective-c又給它添加了很多屬性.
比如
只允許讀取, 不允許修改
@property (readonly) int myProperty;
@property的屬性主要有
可寫屬性:
readwrite 預設屬性
readonly 只讀
賦值屬性:
assign
預設屬性, 使用簡單的賦值方式, 即x=y這種
retain
新值會呼叫retain函式, 舊值會呼叫release函式. 對C++程式設計比較熟悉的程式設計師, 應該容易理解這種場景.
copy
新值會呼叫copy函式來生成一個新的物件, 舊值會呼叫release.
原子屬性
nonatomic
預設情況下, getter和setter是原子訪問的(也就是執行緒安全), 這會影響效能, 因此開發者可以指定為非原子操作nonatomic
垃圾回收處理
objective-c也支援垃圾自動回收, (雖說沒有java這麼傻瓜化, 但是效能上肯定比java好, 可以理解為半自動回收吧)
如果工程開啟了自動引用計數(ARC), 那麼就不需要手動呼叫release函式. 但是各種賦值操作就得注意了, 一不小心釋放掉了一個正在使用中的物件, 程式就崩潰了. 所以才有了上面的retain, copy這兩處屬性, 然後又出現了 __weak , __strong 修飾符.
__strong
預設屬性, 表示強引用, 即引用計數必須正確的進行加減, 例如
@property (retain) __strong NSString str;
它會呼叫新值的retain函式(即計數+1), 避免新值被釋放. 同時會呼叫舊值的release函式(即計數-1), 避免舊值記憶體洩露.
__weak
弱引用, 不改變計數值. 比如, 如果新值的生命週期一定比當前物件要長, 那麼操作引用計數沒有任何意義.
Protocol
類似於java中的interface.
//宣告協議
@protocol MyProtocol
-(void) myProtocol;
@end
//實現協議
@interface MyProtocolImpl: NSObject<MyProtocol>
@end
@implementation MyProtocolImpl
-(void) myProtocol
{
NSLog(@"invoke protocol");
}
@end
//使用協議
@interface TestProtocol : NSObject
-(void) testProtocol:(id<MyProtocol>) callback;
@end
@implementation TestProtocol
-(void) testProtocol:(id<MyProtocol>) callback
{
[callback myProtocol];
}
@end