2014年1月28日 星期二
iOS 的資料儲存方式
1. NSUserDefaults
2. plist
3. archiving (封存)
4. SQLite
5. Core Data
APP的 sandbox(沙箱):
除了 NSUserDefaults 外,其他資料保存方式都有同一共同點,也就是應用程式的 /Documents 資料夾。
每一個 APP 都有自己的 /Documents,而 APP 也只能從自己的 /Documents 進行讀寫。
此資料夾存在 /Library 中,在 Mac OS X 10.6 的版本後,Apple 將此資料夾預設為隱藏,
要進入此隱藏資料夾的方法為:
開啟 Finder -> 選擇 “前往” -> "前往資料夾”(快捷鍵:⇧⌘G)-> 輸入 ~/Library
-> Application Support / iPhone Simulator / 版本 / Applications / <UUID> / Documents
在程式中取得 Documents 路徑:
我們可以用以下程式碼來取得 Documents 的參考位址:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSDocumentDirectory:我們正在尋找至目錄 Documents 的路徑
NSUserDomainMask:將搜尋限制在我們的 APP sandbox 中
符合的路徑會以 Array 來回傳,且 Documents 目錄會在 Array 中 index 為 0 的位置,
因為每一個 APP 只會有一個 Documents 資料夾。
我們可在剛擷取的路徑後面加上一個字串來建立檔名,
可使用 stringByAppendingString 這個專為此用途設計的 NSString 方法,
NSString *filename = [documentsDirectory stringByAppendingPathComponent :@“theFile.txt”];
呼叫這個方法後,filename 將會包含一個我們 APP 的 Documents 目錄中,theFile.txt 檔案的完整路徑,
此時我們就可以利用 filename 來建立該檔案並進行讀取及寫入
取得 tmp 目錄:
tmp 為 APP 的暫存目錄,要取得其參考位址相對的比 Documents 的要簡單許多,
使用 NSTemporaryDirectory() 這個 Foundation 函式,就可以回傳我們 APP 的 tmp 目錄完整路徑的字串。
想要在暫存目錄建立檔案,我們可以用以下語法:
NSString *tmpfile = [NSTemporaryDirectory() stringByAppendingPathComponent :@"temp.txt”];
取得 JSON 格式的資料
iOS 5 後內建了對 JSON 的支援。
我們可以透過 NSJSONSerialization 這個類別將 JSON 格式的字串轉換成 NSArray 或 NSDictionary,
也可以將這兩個類別的物件轉換成 JSON。
NSJSONSerialization 對於資料的格式有一些限制:
1. 只能轉換為 NSArray or NSDictionary
2. 每個 Array or Dictionary 內的元素只能為 NSString、NSNumber、NSArray、NSDictionary、NSNull
3. NSDictionary 的 Key 只能為 NSString
4. NSNumber 不能為 Null
NSJSONSerialization 裡的方法都是靜態方法,大致上可分為兩類:
1. 將資料轉換為 JSON 物件
2. 將 JSON 物件轉換為資料
將資料轉換為 JSON 物件:
1. 將 NSData 物件轉換為 JSON 物件 (NSDictionary or NSArray)
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
ex. 你可以讀取一個 JSON 的字串後,並將之轉換為 NSDictionary
NSString *str = [[NSString alloc] initWithFormat:@"You must got to find your love."];
NSData *data = [kJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSJSONReadingOptions 為轉換時的選項,可以讓你指定轉換後所產生的物件特性。
NSJSONReadingMutableContainers:產生的 Array or Dictionary 為 Mutable 物件
NSJSONReadingMutableLeaves:產生的 String 為 Mutable 物件
NSJSONReadingAllowFragments:允許讀取進來的物件最上層不是 NSArray or NSDictionary
2. 讀取串流物件,並轉換為 JSON:
+ (id)JSONObjectWithStream:(NSInputStream *)stream options:(NSJSONReadingOptions)opt error:(NSError **)error;
此 method 可以讀取串流物件,並且轉換成 JSON,但必須自己負責開啓與關閉這個串流
ex.
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://dl.dropbox.com/u/4223444/twLoto.json"]];
NSInputStream *inStream = [[NSInputStream alloc] initWithData:data];
[inStream open];
NSArray *array = [NSJSONSerialization JSONObjectWithStream:inStream options:NSJSONReadingAllowFragments error:nil];
[inStream close];
Question:
1. 同步、非同步使用時機?
同步:當所有資料下載完時,使用者才能繼續動作,期間畫面無論如何都無法動作
非同步:使用者可以一邊下載資料一邊使用 APP,類似 Youtube
2. + (id)JSONObjectWithStream:(NSInputStream *)stream options:(NSJSONReadingOptions)opt error:(NSError **)error ;
何謂串流物件?
與非同步的觀念類似,適合用在需要下載大量資料時,如:音樂、影片等。
我們觀看 Youtube 時,它會讓我們先觀賞已下載好的資料(灰色那條),另一方面一邊下載未完成的資料,
避免使用者等待時間過久,造成負面觀感。
使用串流物件時,一定要使用非同步的方式。
我們可以透過 NSJSONSerialization 這個類別將 JSON 格式的字串轉換成 NSArray 或 NSDictionary,
也可以將這兩個類別的物件轉換成 JSON。
NSJSONSerialization 對於資料的格式有一些限制:
1. 只能轉換為 NSArray or NSDictionary
2. 每個 Array or Dictionary 內的元素只能為 NSString、NSNumber、NSArray、NSDictionary、NSNull
3. NSDictionary 的 Key 只能為 NSString
4. NSNumber 不能為 Null
NSJSONSerialization 裡的方法都是靜態方法,大致上可分為兩類:
1. 將資料轉換為 JSON 物件
2. 將 JSON 物件轉換為資料
將資料轉換為 JSON 物件:
1. 將 NSData 物件轉換為 JSON 物件 (NSDictionary or NSArray)
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
ex. 你可以讀取一個 JSON 的字串後,並將之轉換為 NSDictionary
NSString *str = [[NSString alloc] initWithFormat:@"You must got to find your love."];
NSData *data = [kJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSJSONReadingOptions 為轉換時的選項,可以讓你指定轉換後所產生的物件特性。
NSJSONReadingMutableContainers:產生的 Array or Dictionary 為 Mutable 物件
NSJSONReadingMutableLeaves:產生的 String 為 Mutable 物件
NSJSONReadingAllowFragments:允許讀取進來的物件最上層不是 NSArray or NSDictionary
2. 讀取串流物件,並轉換為 JSON:
+ (id)JSONObjectWithStream:(NSInputStream *)stream options:(NSJSONReadingOptions)opt error:(NSError **)error;
此 method 可以讀取串流物件,並且轉換成 JSON,但必須自己負責開啓與關閉這個串流
ex.
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://dl.dropbox.com/u/4223444/twLoto.json"]];
NSInputStream *inStream = [[NSInputStream alloc] initWithData:data];
[inStream open];
NSArray *array = [NSJSONSerialization JSONObjectWithStream:inStream options:NSJSONReadingAllowFragments error:nil];
[inStream close];
Question:
1. 同步、非同步使用時機?
同步:當所有資料下載完時,使用者才能繼續動作,期間畫面無論如何都無法動作
非同步:使用者可以一邊下載資料一邊使用 APP,類似 Youtube
2. + (id)JSONObjectWithStream:(NSInputStream *)stream options:(NSJSONReadingOptions)opt error:(NSError **)error ;
何謂串流物件?
與非同步的觀念類似,適合用在需要下載大量資料時,如:音樂、影片等。
我們觀看 Youtube 時,它會讓我們先觀賞已下載好的資料(灰色那條),另一方面一邊下載未完成的資料,
避免使用者等待時間過久,造成負面觀感。
使用串流物件時,一定要使用非同步的方式。
2014年1月27日 星期一
Storyboard View 與 View 之間的傳值
假設有兩個 View,分別為 FirstViewcontroller、SecondViewController,
若我們想將 FirestViewController 的值傳給 SecondViewController 的話那該怎麼做呢?
首先,要先將兩個 ViewController 建立關係,
在 FirstViewController 建立一個 button 連結到 SecondViewController,選擇 Modal
新增一個字串(因為這個字串要提供給 self class 以外的類別使用,所以要在 .h 檔宣告):
@property (strong, nonatomic) NSString *strInFirstVC;
_strInFirstVC = [NSString stringWithFormat:@"這是在 FirstVC 的一個字串"];
SecondViewController 也新增一個:
@property (strong, nonatomic) NSString *strInSecondVC;
然後在 FirstViewController 新增以下 method 進行傳值:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
id targetViewController = segue.destinationViewController;
[targetViewController setValue:_strInFirstVC forKey:@"strInSecondVC"];
}
為了證明傳值成功,
我們在 SecondViewController 將字串列印出來
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"這是第二個 VC");
NSLog(@"%@", _strInSecondVC);
}
執行模擬器,按下 button,若成功切換到 SecondViewController 並且顯示:
則表示我們成功了!!
若我們想將 FirestViewController 的值傳給 SecondViewController 的話那該怎麼做呢?
首先,要先將兩個 ViewController 建立關係,
在 FirstViewController 建立一個 button 連結到 SecondViewController,選擇 Modal
新增一個字串(因為這個字串要提供給 self class 以外的類別使用,所以要在 .h 檔宣告):
@property (strong, nonatomic) NSString *strInFirstVC;
_strInFirstVC = [NSString stringWithFormat:@"這是在 FirstVC 的一個字串"];
SecondViewController 也新增一個:
@property (strong, nonatomic) NSString *strInSecondVC;
然後在 FirstViewController 新增以下 method 進行傳值:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
id targetViewController = segue.destinationViewController;
[targetViewController setValue:_strInFirstVC forKey:@"strInSecondVC"];
}
為了證明傳值成功,
我們在 SecondViewController 將字串列印出來
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"這是第二個 VC");
NSLog(@"%@", _strInSecondVC);
}
執行模擬器,按下 button,若成功切換到 SecondViewController 並且顯示:
則表示我們成功了!!
2014年1月25日 星期六
在 iOS 上免費(且合法地)使用額外的字體
iOS 字體列表:http://support.apple.com/kb/HT5878?viewlocale=en_US&locale=en_US
APPLE 範例程式:https://developer.apple.com/Library/ios/samplecode/DownloadFont/Listings/DownloadFont_ViewController_m.html
iOS tips: Custom Fonts:http://refactr.com/blog/2012/09/ios-tips-custom-fonts/
文章來源:http://apple4us.com/2014/01/how-to-use-additional-fonts-on-ios.html
#define 敘述
#define 最常見的用法是指定一個符號名稱(symbolic name)給程式中的常數,
ex.
#define PI 3.1415926
定義符號名稱 PI,並讓它等同於 3.14。
在程式中只要出現 PI 的地方,前端處理程式會自動將 PI 取代為定義 3.14。
#define 敘述有個特殊的語法:將 3.14 指定給 PI 時,不會用到等號,在句尾也沒有分號。(稍後說明)
#define 敘述通常宣告在程式的一開始處,且位於 #import or #include 敘述之後,
放置的位置沒有硬性規定,但一定要置於程式被引用前。
大部份的程式設計師會將 #define 敘述置於標頭檔,如此名稱便能被多個原始檔(source file)使用。
使用 #define 敘述的好處是:
1. 我們不必在每次需要用到常數時,記得該常數值。
2. 若要修改該常數,只要在 #define 敘述裡修改即可。
若不用這個方法,則需要搜尋整個程式,並且在每個使用該常數的地方加以修改。
命名習慣:
一般程式設計師習慣將符號名稱以大寫表示,
ex.
#define PI 3.14#define TRUE 1
#define FALSE 0
這是為了要與變數的定義作區隔,如此便能輕易的分辨,一個名稱代表的是物件、class name、或是 symbolic name。
也有個通俗的習慣,使用 k 作為定義的前置詞,在此情況,命名就不需要全大寫,
ex.
#define kMaximumValue 100
#define kMiniimumValue 1
進階的形態定義:
符號名稱的定義不只限於一個常數,還可以包含一個運算式,
ex.
#define TWO_PI 2.0 * 3.1415926
前端處理程式將置換所有出現的符號名稱,這也就是為什麼不以分號做結束的原因。
若用了分號會變成:
#define PI 3.1415926;
return 2.0 * PI * r;
編譯器看到的是:
return 2.0 * 3.1415926; * r;
而造成語法上的錯誤,
所以請記得不要在 #define 敘述字尾加上分號,除非確定分號就是敘述的一部份。
對前端處理程式定義來說,只要代替的運算式是有效即可。
ex.
#define AND &&
#define OR ||
便可撰寫以下程式:
if (x == 0 OR x == value) { //...
}
甚至也可將 #define 用在相等的比較
#define EQUALS ||
接著撰寫以下敘述:
if (x == 0 EQUALS x == value) { //...
}
這可免除在相等的測試裡誤用單一等號的可能性。
雖然以上範例描述了 #define 敘述的優點,但要注意,若重新定義語言中已知的語法,並不是個撰寫程式的好習慣,
這會使人更難看懂你的程式。
ex.
#define PI 3.1415926
定義符號名稱 PI,並讓它等同於 3.14。
在程式中只要出現 PI 的地方,前端處理程式會自動將 PI 取代為定義 3.14。
#define 敘述有個特殊的語法:將 3.14 指定給 PI 時,不會用到等號,在句尾也沒有分號。(稍後說明)
#define 敘述通常宣告在程式的一開始處,且位於 #import or #include 敘述之後,
放置的位置沒有硬性規定,但一定要置於程式被引用前。
大部份的程式設計師會將 #define 敘述置於標頭檔,如此名稱便能被多個原始檔(source file)使用。
使用 #define 敘述的好處是:
1. 我們不必在每次需要用到常數時,記得該常數值。
2. 若要修改該常數,只要在 #define 敘述裡修改即可。
若不用這個方法,則需要搜尋整個程式,並且在每個使用該常數的地方加以修改。
命名習慣:
一般程式設計師習慣將符號名稱以大寫表示,
ex.
#define PI 3.14#define TRUE 1
#define FALSE 0
這是為了要與變數的定義作區隔,如此便能輕易的分辨,一個名稱代表的是物件、class name、或是 symbolic name。
也有個通俗的習慣,使用 k 作為定義的前置詞,在此情況,命名就不需要全大寫,
ex.
#define kMaximumValue 100
#define kMiniimumValue 1
進階的形態定義:
符號名稱的定義不只限於一個常數,還可以包含一個運算式,
ex.
#define TWO_PI 2.0 * 3.1415926
前端處理程式將置換所有出現的符號名稱,這也就是為什麼不以分號做結束的原因。
若用了分號會變成:
#define PI 3.1415926;
return 2.0 * PI * r;
編譯器看到的是:
return 2.0 * 3.1415926; * r;
而造成語法上的錯誤,
所以請記得不要在 #define 敘述字尾加上分號,除非確定分號就是敘述的一部份。
對前端處理程式定義來說,只要代替的運算式是有效即可。
ex.
#define AND &&
#define OR ||
便可撰寫以下程式:
if (x == 0 OR x == value) { //...
}
甚至也可將 #define 用在相等的比較
#define EQUALS ||
接著撰寫以下敘述:
if (x == 0 EQUALS x == value) { //...
}
這可免除在相等的測試裡誤用單一等號的可能性。
雖然以上範例描述了 #define 敘述的優點,但要注意,若重新定義語言中已知的語法,並不是個撰寫程式的好習慣,
這會使人更難看懂你的程式。
前端處理程式
前端處理程式(Preprocessor)可以讓我們更容易的開發、閱讀、修改程式,以及在不同的系統間移植。
前端處理程式是 Objective-C 編譯的一部份,它能識別在程式中出現的特殊敘述。
它會在分析程式之前,處理這些敘述。
前端處理程式敘述是由井字號(#)加以識別,井字號必須是該行第一個非空白字元。
前端處理程式是 Objective-C 編譯的一部份,它能識別在程式中出現的特殊敘述。
它會在分析程式之前,處理這些敘述。
前端處理程式敘述是由井字號(#)加以識別,井字號必須是該行第一個非空白字元。
修改專案名稱
1. 在專案名稱上直接按 enter 進行修改
2. 點選 scheme name 選擇 Manage Schemes
3. 點一下 Sceme name 按下 enter 進行修改
4. 最後,到資料夾所在位置修改檔名 (可直接在專案名稱上按右鍵 選擇 Show In Finder)
隱藏 Status Bar 的方法
1. 直接於 plist 裡修改:
iOS 7
先將 Status bar is initially hidden 設為 YES,
再新增 View controller-based status bar appearance 欄位,並設定值為 NO
iOS 6
只需將 Status bar is initially hidden 設為 YES 即可
2. 於程式碼裡修改,加入下列程式碼
iOS 7
- (BOOL)prefersStatusBarHidden {
return YES;
}
iOS 6
UIApplication *app = [UIApplication sharedApplication];
[app setStatusBarHidden:YES withAnimation:YES]
差別在於,於程式碼裡修改時,Status Bar 會先出現一會,再以動畫方式消失,
於 plist 裡修改,Status Bar 連出現都不會出現
iOS 7
先將 Status bar is initially hidden 設為 YES,
再新增 View controller-based status bar appearance 欄位,並設定值為 NO
iOS 6
只需將 Status bar is initially hidden 設為 YES 即可
2. 於程式碼裡修改,加入下列程式碼
iOS 7
- (BOOL)prefersStatusBarHidden {
return YES;
}
iOS 6
UIApplication *app = [UIApplication sharedApplication];
[app setStatusBarHidden:YES withAnimation:YES]
差別在於,於程式碼裡修改時,Status Bar 會先出現一會,再以動畫方式消失,
於 plist 裡修改,Status Bar 連出現都不會出現
2014年1月24日 星期五
撥號功能
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:
@"tel:07-1234567"]]];
@"tel:07-1234567"]]];
在地圖裡加上大頭針 MKAnnotation 的觀念
先來看看,在地圖裡加入大頭針的語法:
<MKAnnotation> 這個 protocol 的 id 形態的物件,
<MKAnnotation> 它本身就只是一個 protocol ,
裡面定義著用來記錄 coordinate、title、subtitle 這些資料的參數,
其功能就只是定義一組界面而已,並無法實體化成大頭針顯示在 MapView 上,
所以我們需要自訂一個遵從 <MKAnnotation> 的 class,
讓這個 class 來實體化一個或多個物件 (大頭針),並將 <MKAnnotation> 裡記錄的參數傳入,
好讓大頭針知道自己要顯示在 MapView 的哪個地方,以及他的註解要顯示哪些字。
Apple 本身並沒有將大頭針這功能寫成跟我們一般常用的 UI 一樣,
class 都幫我們寫好只要將它實體化就可以用,
so,只能自己手動新增一個 class 。
在 custom segue 裡利用 QuartzCore Framework 自訂動畫
點選 Segue 將 Style 改成 Custom
新增一個繼承自 UIStoryboardSegue 的 class
指定 custom 的 segue class 為 CustomSegue
於 CustomSegue 裡 override - (void)perform
- (void)perform {
CATransition *transition = [CATransition animation];
transition.duration = 0.4;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
__block UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
__block UIViewController *destinationController = (UIViewController*)[self destinationViewController];
[sourceViewController.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[sourceViewController.navigationController pushViewController:destinationController animated:NO];
}
設定 NavigationItem 的 title 字體、大小、位置
設定字體大小:
Label.font = [UIFont systemFontOfSize:50];
設定字體與大小:
Label.font = [UIFont fontWithName:@"Helvetica" size:50];
設定 NavigationItem 的 title 字體、大小、位置
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320/2, 44)];titleLabel.textAlignment = NSTextAlignmentCenter;titleLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);titleLabel.font = [UIFont fontWithName:@"Helvetica" size:23];titleLabel.text = @“Title”;
UINavigationItem *naviItem = [[UINavigationItem alloc] init];naviItem.titleView = titleLabel;
Label.font = [UIFont systemFontOfSize:50];
設定字體與大小:
Label.font = [UIFont fontWithName:@"Helvetica" size:50];
設定 NavigationItem 的 title 字體、大小、位置
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320/2, 44)];titleLabel.textAlignment = NSTextAlignmentCenter;titleLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);titleLabel.font = [UIFont fontWithName:@"Helvetica" size:23];titleLabel.text = @“Title”;
UINavigationItem *naviItem = [[UINavigationItem alloc] init];naviItem.titleView = titleLabel;
Tab Bar Controller 系統載入流程概述
這是一個以 Tab Bar Controller 為主畫面的專案,以下是專案一開啓的起始畫面
那為什麼畫面一載入時沒有看到該 badge,而是等到我們點一下 1st Tab 後才出現呢?
這是因為 Apple 在軟體運作的設計流程上,並不會一開始就載入所有的 ViewController,
而是直到使用者按下 Tab Bar 的那瞬間,才該呼叫該對應的 ViewController,
如此一來便能大大地節省記憶體的使用。
接下來我們點一下中間那個 1st Tab,畫面會變成
紅色那句:早安 稱之為 Badge,
那為什麼畫面一載入時沒有看到該 badge,而是等到我們點一下 1st Tab 後才出現呢?
這是因為 Apple 在軟體運作的設計流程上,並不會一開始就載入所有的 ViewController,
而是直到使用者按下 Tab Bar 的那瞬間,才該呼叫該對應的 ViewController,
如此一來便能大大地節省記憶體的使用。
另外,Apple 人機界面規定:TabBar 包 Navigation 是 OK 的,
Navigation 包 TabBar 則違反規定。
初遇 Storyboard
Storyboard 是 iOS 5 之後才加入的,所以如果 APP 想要相容於 iOS 5 以前的版本,那就不可使用 Stroyboard 去實作。
PS.
1. Storyboard 拉出來的 ViewController,常常仍需要新增一個 ViewController class 來搭配
2. ViewController 之間使用 Segue 來進行串接,兩個 ViewController 間可以有多個 Segue 做串接,使用 Identifier 來進行識別
實作:
開啓一個 Storyboard 專案,加入 3 個 ViewController,
為了辨識方便我們將 background 設為不同顏色,
使用 Segue 來串接各個 ViewController,
在 Main View 加入兩個按鈕:Go Directly、Go Random,
按下 Go Directly 可直接通往其中一個指定的 ViewController,
而 Go Random 則會隨機通往其中一個 ViewController。
首先,先實作 "按下 Go Directly" 按鈕後,會直接進入指定 ViewController 這個功能:
在 Go Directly 這個按鈕上按下右鍵,將 Triggered Segues 裡 action 連接到欲進入的 ViewController,
選擇 modal (稍後會提到 modal、push 的差別)
另外,點選 segue,在 attributes inspector 中有四個預設效果可選。
首先:
1. 在 main ViewController 中建立一個”返回”用的 method
注意:
以往我們使用 -(IBAction) 型態的 method 時,後面的參數都是帶 (id)sender,
而在此所使用的參數其型態為 (UIStoryboardSegue *),
如此才能讓按鈕在連結 Exit 時接收到。
接下來我們來實作:
按下 Go Random 按鈕會隨機通往其中一個 ViewController
首先,先建立 main ViewController 跟 Black ViewController、Green Viewcontrller 的關聯
點選 main ViewController 然後按右鍵,將 Triggered Segue 裡的 manual 拖拉至另一個 ViewController 選擇 modal
接下來,爲各個 Segue 設置其 Identifier
(如果無法建立代表我們忘了在 .h 檔裡宣告 - (IBAction)goRandomBtn:(id)sender;)
完成!
PS.
1. Storyboard 拉出來的 ViewController,常常仍需要新增一個 ViewController class 來搭配
2. ViewController 之間使用 Segue 來進行串接,兩個 ViewController 間可以有多個 Segue 做串接,使用 Identifier 來進行識別
實作:
開啓一個 Storyboard 專案,加入 3 個 ViewController,
為了辨識方便我們將 background 設為不同顏色,
使用 Segue 來串接各個 ViewController,
在 Main View 加入兩個按鈕:Go Directly、Go Random,
按下 Go Directly 可直接通往其中一個指定的 ViewController,
而 Go Random 則會隨機通往其中一個 ViewController。
首先,先實作 "按下 Go Directly" 按鈕後,會直接進入指定 ViewController 這個功能:
在 Go Directly 這個按鈕上按下右鍵,將 Triggered Segues 裡 action 連接到欲進入的 ViewController,
選擇 modal (稍後會提到 modal、push 的差別)
正確連結後面話應該會如下:
執行後,按下 Go Directly 應該就可以進入藍色的 ViewController 了。
另外,點選 segue,在 attributes inspector 中有四個預設效果可選。
接下來,讓我們在 blue ViewController 上建立一個 button 用於返回上一個 main ViewController
首先:
1. 在 main ViewController 中建立一個”返回”用的 method
-(IBAction)backToFirst:(UIStoryboardSegue *) segue {
NSLog(@"back to FirstPage");
}
2. 回到 blue ViewController 在按鈕上點擊右鍵,連接到下方綠色的 Exit 選擇剛建立的方法
3. 完成後按下按鈕,就可以返回 main ViewController 了
注意:
以往我們使用 -(IBAction) 型態的 method 時,後面的參數都是帶 (id)sender,
而在此所使用的參數其型態為 (UIStoryboardSegue *),
如此才能讓按鈕在連結 Exit 時接收到。
接下來我們來實作:
按下 Go Random 按鈕會隨機通往其中一個 ViewController
首先,先建立 main ViewController 跟 Black ViewController、Green Viewcontrller 的關聯
點選 main ViewController 然後按右鍵,將 Triggered Segue 裡的 manual 拖拉至另一個 ViewController 選擇 modal
如此一來關聯就建立了,
接下來,爲各個 Segue 設置其 Identifier
分別設置好 goBlue、goGreen、goBlack 後,就可以開始撰寫 Go Random 這個 button 的 IBAction 了
- (IBAction)goRandomBtn:(id)sender {
NSInteger targetIndex = arc4random() % 3;
switch (targetIndex) {
case 0:
[self performSegueWithIdentifier:@"goBlue" sender:nil];
break;
case 1:
[self performSegueWithIdentifier:@"goGreen" sender:nil];
break;
case 2:
[self performSegueWithIdentifier:@"goBlack" sender:nil];
break;
default:
break;
}
}
寫好後,再將 Go Random 與剛剛寫好的 IBAction 建立起關聯,(如果無法建立代表我們忘了在 .h 檔裡宣告 - (IBAction)goRandomBtn:(id)sender;)
完成!
2014年1月23日 星期四
在 Blogger 貼上 Objective-C 語法(使用 SyntaxHighlighter)
摸了好久,終於成功了
分享一下給有需要的人,以節省各位再花時間去摸索
首先到 SyntaxHighlighter 網站,下載套件
解壓縮後有兩個檔案是我們等等要上傳至網頁空間的,
分別是:scripts / shCore.js、styles / shCore.css
接著到 http://ppt.cc/6tac 下載 shThemeDefault.css 和 shBrushObjC.js
接著,我們在到 google site 建立一個 "協作平台"
新增頁面
使用 “檔案櫃" 當做範本
上傳剛剛的四個檔案
此時我們可以得到 4 個去掉 ? 參數後面的檔案連結: (同時將 https 改成 http)
http://sites.google.com/site/ertt0001/objc/shBrushObjC.js
https://sites.google.com/site/ertt0001/objc/shCore.css
https://sites.google.com/site/ertt0001/objc/shCore.js
https://sites.google.com/site/ertt0001/objc/shThemeDefault_1.css
修改 Blogger 範本
在 標籤下, 新增以下的內容:
<!-- start for Syntax Highlighting -->
<link href='http://sites.google.com/site/ertt001/objc/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://sites.google.com/site/ertt001/objc/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://sites.google.com/site/ertt001/objc/shCore.js' type='text/javascript'/>
<script src='http://sites.google.com/site/ertt001/objc/shBrushObjC.js' type='text/javascript'/>
<script type='text/javascript']]>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.all();
</script>
<!-- end for Syntax Highlighting —>
然後就可以開始使用啦!
使用方式:在要貼程式碼的地方加上以下標籤
<pre class="brush: objc; toolbar: false;">
//post code here
</pre>
成果大概是這樣:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"Hello World");
}
參考網址:
http://itouchs.blogspot.tw/2011/11/blogspot-objective-c-syntax.html
http://jaminya.com/index.php/en/component/content/article/40-css/50-objc-syntax-highlight
訂閱:
文章 (Atom)


































