2012年12月31日 星期一

Class Method (二):Signleton

如果你有要在多執行續使用 signletion 的話,請改看這篇文章。
Class Method (三):Signleton 改 - 在多執行續的解法

之前有說到 Class Method 還有另一種用法,就是 Singleton,
它是在第一次宣告這個 Class 取得記憶體位置之後,
之後的宣告都不會改變它的記憶體位置的使用方法,
假設現在有兩個 Class,一個是 aClass、另一個是 bClass,還有一個使用 Singleton 方法的 cClass
aClass 與 bClass 都會宣告 cClass,
這時候不管是哪個 Class 先宣告,另一個 Class 裡的都會使用到相同記憶體位置的 cClass,
像是需要保持資料庫的連結時就會這麼做,
在 Objective-C 中內建的 Class 中,UIDevice、NSBundle 等等都有這種用法,
說明就到此為止,接下來就教怎麼做。

首先與上一篇的建立 Class Method 的方法一樣,
不過比較不同的的是 Singleton 通常不會有傳值的動作。

Method.h
+ (id)method;

建立完了以後就是來實作它了

Method.m
+ (id)method
{
	static Method *singleton = nil;
	if (singleton == nil) {
		singleton = [[Method alloc] init];
	}
	return singleton;
}

Singleton 與一般的 Class Method 的差別是 Singleton 完全不需要 release,
因為它的記憶體位置是需要被保留下來的,
所以之後它只要在第一次宣告之後,
未來的宣告都會使用相同的記憶體位置。

這次的教學就到此為止,下次等我有想到有不同的教學再來吧。

2012年12月30日 星期日

Class Method (一)

有一段時間沒有更新這個網誌了
剛好趁跨年假期來打個一篇
這次是 Class Method,這是大部分的書本沒交到的使用方法,
不過要是學會的話會愛不釋手,因為可以省下打一堆字,
下面就開始這次的教學了。

這次是 Class Method

什麼是 Class Method ?
在 Objective-C 中的 [NSString string] 等方法就是 Class Method。
它同時也是符合 Auto Release 的功能。

那麼要如何寫一個 Class Method 呢?
其實很簡單,只要將一般的 Method 的開頭減號改成加號即可。
不過實際的內容要怎麼寫呢?

假設有兩個檔案為 Method.h 與 Method.m
一個 Class Method 都會是對外公開的 Method
所以 Method 的名稱都會打在 h 檔中

Method.h
+ (id)aMethod; // 這是一個不需要傳入值的 Class Method
+ (id)aMethodWithValue:(NSInteger)integer; // 這是一個需要傳入值的 Class Method

實作 Class Method 有三種方法:
一是直接回傳其他 Class 的 Class Method,這個就不用說了,
二是自己建立自己的 Class Method,這個是這次教學的重點,
三是建立一個 singleton 的 Class Method,這算是 Class Method 的一種變形,在下個教學會教到。

Method.m
+ (id)aMethod
{
	Method *method = [[[Method alloc] init] autoRelease];
	// 其實這跟一般的 Class 宣告方法一樣,
	return method;}

+ (id)aMethodWithValue:(NSInteger)integer
{
	Method *method = [[[Method alloc] initWithValue:integer] autoRelease];
	// 有傳值的 Class Method 就比較特別了,這要看你傳入的值要給哪個初始化的 Method,如果沒有這個 Method 就要自己建立一個了。
	return method;
}

這樣子在其他 Class 裡要用到這個 Class 的功能時就可以這樣子宣告,

Method *method = [Method aMethod];
或
Method *method = [Method aMethodWithValue:0];

這樣子就比一般 Class 宣告的方法短多了,而且又符合 Auto Release 的條件,
就不會忘了這個變數需要 Release 的問題。

未完續待

2012年9月2日 星期日

將相機畫面加到自己的 View 裡面

基本上我們要使用相機來擷取畫面時都是呼叫一個新的 ViewController 出來使用
不過有些時候需要一啟動 App 就載入相機的畫面
這時候有兩個方式:
一個是在 AppDelegate.m 中直接將 UIImagePickerController 加入 rootViewController 中
不過要是需要自定相機的介面的時候就會比較麻煩,因為基本上不會在 AppDelegate.m 中寫太多程式在裡面

另一個是就是跟一般 UI 元件一樣加到現在這個 ViewController 中
用的方法如下:
UIImagePickerController *pickerView = [[UIImagePickerController new] autorelease];
[[self view] addSubview:[pickerView view]];

這樣子就可以在 ViewController.m 中編寫相機的相關功能,而且自定相機介面的時候也不會那麼麻煩。

2012年8月4日 星期六

2012年7月26日 星期四

查詢計算未來幾天後的日期

有時候需要去計算未來幾天後的日期,
不過 Objective-C 有計算未來幾秒後的功能,用的是
[NSDate dateWithTimeIntervalSinceNow:second];
這是可以計算未來幾天後的日期,
不過如果要算一個月後了?
因為一個月有分大月與小月,另外還有潤年的問題,
用這個算法就不實用,所以我找到了另一個方法,
還記得我之前說的 FMDB 嗎?
在 SQL 語法中剛好有這項功能,
所以可以直接使用,這樣子可以省下判斷大月與小月的時間,
只不過使用 SQL 時會增加記憶體的使用,
這是犧牲記憶體容量來縮減判斷時間的作法,
那麼要如何做了?

在 SQL 語法中查詢未來天數的寫法是,
SELECT DATE('2012-07-26', '+ X day');
其中 "+ X day" 的 X 就是要增加的天數,
如果要增加的月份的時候就改成 "+ X month" 就好了,
同理,要增加年份也是一樣的,
還有如果改成 "- X day" 的時候是計算過去的日期,
另外日期的格式必須要是 "YYYY-MM-DD" 的格式才行,

還有另一個是格式化輸出的日期,語法如下
SELECT STRFTIME('%Y-%m-%d','2012-07-26');
因為上面的輸出格式是固定的,不過有時候會想要改變輸出的格式,
所以就需要這個語法了,
其中 %Y 指的是年,%m 指的是月份,%d 指的是日期,
只要在這三個之間插入不同的東西就會輸出不同的格式,
像是 "%Y年%m月%d日" 就會輸出 "2012年07月26日"。

所以就結合 FMDB 的方式來計算未來幾天後的日期做成了一個 Method,
- (NSString *)seachFutureDate:(NSString *)date withDay:(int)day andFormate:(NSString *)formate{
FMDatabase *db = [FMDatabase databaseWithPath:nil];

if (![db open]) {
NSLog(@"DB Can't Open");
}

NSString *dayStr = [NSString stringWithFormat:@"+%d day", day];

FMResultSet *rs = [db executeQuery:@"SELECT STRFTIME(?,DATE(?, ?));", formate, date, dayStr];

NSString *dateStr = [[NSString new] autorelease];

while ([rs next]) {
dateStr = [rs stringForColumnIndex:0];
}

[db close];

return dateStr;
}

因為這個查詢的動作不需要真的有資料庫的檔案才能做,
所以不會佔用任何資料空間,
而且只要小小的修改就能變成查詢幾月後的日期與幾年後的日期了,
這樣子計算天數會更加方便。

OS X 10.8 Mountain Lion

從二月發表等到現在才正式公開下載的 Mountain Lion
有人下載了嘛?

App Store 連結:http://itunes.apple.com/tw/app/os-x-mountain-lion/id537386512?l=zh&mt=12

另外 Xcode 在 Mountain Lion 中需要更新為 4.4 版才能繼續使用

App Store 連結:http://itunes.apple.com/tw/app/xcode/id497799835?l=zh&mt=12

2012年7月21日 星期六

強制將符合地區語言格式的星期/月份強制改成英文

這是我在做第三隻 APP 時所遇到的問題,
因為 iOS 的多國語言的關係,
所以月份與星期會因為語言而切換成該國的語言,
不過有時候會希望顯示的還是英文,
所以要反過來利用多國語言的設定檔來強制切換成英文,
就是採用下面的方式,

大部分的多國語言都是使用英文轉換成該國語言,
不過我的方式是相反的使用方式,
有相同問題的人可以嘗試看看。

2012年7月19日 星期四

設定圖片給 UITextView 當背景

基本上 UITextView 不能使用圖片當背景,
過有時候還是需要這麼做,
這時候就要用下面這個作法,
[textView insertSubview:imageView atIndex:0];
這樣子就可以在 UITextView 中加入背景。

至於為什麼要這麼做?
這是因為 UITextView 的背景可以跟著 UITextView 裡面的 UIScrollView 一起滾動
像是信紙一樣的每行都有底線的時候,就會希望這麼做。

2012年7月14日 星期六

SQLite 的救星 FMDB

在 Objective-C 要使用 SQLite 是一件很痛苦的事
因為控制 SQLite 是走 C lib 的作法
不是純 Objective-C 的作法,所以就有人寫出了一個更方便控制 SQLite 的 Class
那個就是 FMDB,它是一個已經將主要的控制 SQLite 功能已經包裝在一起了
方便程式設計師去控制 SQLite

安裝 FMDB
方法很簡單,就跟所有的 Class 一樣的三步驟。
1. 首先你要先把 libsqlite3.dylib 加進 library
(基本上只需要 FMDatabase、FMDatabasePool、FMResultSet)
2. 將上面三種 Class 的.h 跟.m 加進你的 project 中
3. 在需要用到 FMDB 的檔案中加入#import "FMDatabase.h"
接著就可以開心的使用 FMDB

要使用資料庫之前首先要開啟資料庫連接
開啟資料庫連接的程式法如下
FMDatabase *db = [FMDatabase databaseWithPath:dbName];
if (![db open]) {
NSLog(@"DB Can't Open");
}

當然有開啟就有關閉,關閉的方法很簡單,只要一行就能解決了
[db close];

我自己會想要將開啟連結的使用方式變得更簡單,所以就變成是這樣子
- (FMDatabase *)openDB{
NSString *dbPath = [self databasePathWithName:@"資料庫檔案名稱"];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
if (![db open]) {
NSLog(@"DB Can't Open");
}
return db;
}

以後只要一行就能開啟資料庫了,就像是這樣子
FMDatabase *db = [self openDB];

可以開啟與關閉資料庫後,接下來就是控制它了
(使用前記得建立資料庫的連結,使用完也要關閉連結)

控制的方法分兩種,一是更新資料庫
像是建立 / 刪除資料表,寫入欄位值等等
if (![db executeUpdate:@"SQL 語法"]) {
NSLog(@"Could not create table: %@", [db lastErrorMessage]);
}

更新資料庫時也可以傳入值給它
if (![db executeUpdate:INSERT INTO 資料表名稱 (欄位 1, 欄位 2) VALUES (?,?)", @"欄位 1 的值", @"欄位 2 的值"]) {
NSLog(@"Could not insert data: %@", [db lastErrorMessage]);
}

另一個方法就是查詢資料庫的資料,這部份就比較麻煩一些
NSMutableArray* items = [NSMutableArray arrayWithCapacity:0];
FMResultSet *rs = [db executeQuery:@"SELECT 欄位 1, 欄位 2 from 資料表名稱"];

while ([rs next]) {       
int uid = [rs intForColumn:@"欄位 1"];
NSString *name = [rs stringForColumn:@"欄位 2"];     

[items addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:uid], @"欄位 1",
name, @"欄位 2",
nil]];
}

[rs close]; 

其中,查詢時可以選擇要接收的形態
如果是 int 的話,可以使用 [rs intForColumn:@"欄位 1"]
如果是 NSString 的話,可以使用 [rs stringForColumn:@"欄位 2"]
其他的形態可以在 FMResultSet.h 中看到

2012年7月11日 星期三

AddressBook & AddressBookUI Framework

這次替朋友做一個 App
它需要用到 AddressBook 的功能,取得某人的單一個電話
所以就去找了這方面的資訊
不過這部份書本的資料也不多,所以改成去網路上找
找了很久才找到幾個比較實用資料,並且將它整合在一起

使用 AddressBook 的功能時,你會需要 AddressBook.framework 與 AddressBookUI.framework 這兩個 framework
AddressBook.framework 是用來擷取 AddressBook 資料用的
AddressBookUI.framework 是用來建立 AddressBook 的 UI 用的
建立 UI 的時候需要 ABPeoplePickerNavigationControllerDelegate、ABPersonViewControllerDelegate 這兩個 Delegate
這些 Delegate 的 Method 都是必定建立的,所以都要打入 .m 檔中

之後就來教要如何建立第一個 AddressBook 的 UI 了
這邊是使用 ABPeoplePickerNavigationController
我是用一個按鈕呼叫 add 這個方法
所以就在那邊建立這個介面

這個 Method 回傳 Yes 時就可以進入聯絡人的詳細資料
回傳 No 時會維持現在這個畫面
因為我要切換到 ABPersonViewController 這個介面
所以就回傳 No
其中 setDisplayedProperties 是設定我要顯示的聯絡人詳細資訊的內容
因為我只要電話的資訊而已,所以限定顯示電話資訊就好了
這樣子不會讓使用者不知道要點哪個地方
setDisplayedProperties 的詳細設定可以自行去查察看,我就不提供了

這個 Method 回傳 Yes 時就可以執行聯絡人資料中的動作
點到電話時就是播出電話,點到 Mail 時就是寫 Mail 給他
回傳 No 時會維持現在這個畫面
因為我不會進入這個畫面,所以回傳什麼都沒關係

這個 Method 是做進入 ABPeoplePickerNavigationController 按下右上方的 Cancel 按鈕時的動作
當然通常按下 Cancel 的時候就是取消這個介面,回到上一個介面了

建立 ABPersonViewController 這個介面時我會用它的 Delegate
下面的 Method 就是屬於這個 Delegate 的
其實進入 ABPersonViewController 時會跟 ABPeoplePickerNavigationController 的第二層介面是一樣都是聯絡人的詳細資料
不過這邊能取得你點擊到的資訊,而不是這個聯絡人的全部資訊

我在模擬器裡面點移這個聯絡人的這隻電話
這時候 Log 就會顯示我點到的聯絡人姓名與電話資料了

2012年7月5日 星期四

介面

這次的介面決定為這樣子
左上角是指南針(明明是指北針......),右上角是電量顯示
下方是經緯度與海平面高度
中間就是最主要的時鐘,不過目前還沒決定指針要長成怎樣子
所以還沒做出來

2012年7月3日 星期二

第三隻 App

我第三的 App 預定是要做指針式時鐘,
程式方面已經完成了,只差美工的部分而已,
所以打算使用一段長時間來解決

2012年6月29日 星期五

設定 UINavigationController 到第二個 View 中

大部分的教學都是教你如何使用 UINavigationBar 或是將 UINavigationController 設定到第一頁中
並沒有教你如何將 UINavigationController 加到第二頁或是第三頁中
不過還是讓我找到如何使用了
這個教學是使用 Utility Application 的範本
在 MainViewController.m 的 - (IBAction)showInfo:(id)sender
加入下面的程式碼
就可以在 FlipsideViewController.m 使用 UINavigationController 的功能了

第二個 App

這次的 App 原本是想做成"一鍵地震文"的功能,
不過這樣子會因為功能太簡單的關係被 Apple 退件,
所以將它改成求救用的功能,就是當你遇難時能將你的求救訊息傳到 Facebook 或 Twtter 與微博中,
但是光是設計 icon 就花費我半天的時間了,程式方面只花了將近一週的時間,
這個是程式的主畫面,
假設一位遇難者在海上遇難,到了一個孤島,
他找到了一張紙和一張便條紙,他在這張紙寫下他的求救訊息,
所以我將它做成一張紙的風格,並且使用手寫文字的方式畫出介面,
還有便條紙其實是一個按鈕,按下去時可以呼叫傳送訊息的介面,
當然傳送訊息時必須使用網路功能,所以必須做網路檢查的功能,
這樣子才能審核通過,
這個是設定畫面,在這邊你可以設定你的預設求救訊息與是否顯示你的座標,
和選擇傳送的服務,在現在送審的版本只有 Twitter 的功能,
等到支援 iOS 6 的程式可以送審的時候才會將這個版本送審,
這是選擇傳送的服務的選擇畫面,同上,這只有下一版才有這個畫面。

2012年6月27日 星期三

音樂、電影

iTunes Store 總算開放台灣地區的音樂與電影商店了
音樂一首台幣20元算便宜了,不過我都是買日文歌曲,
所以對我用處不大,

電影一片要台幣350~590元,也是很便宜,
而且租借一片台幣60元起跳,比外面的影片出租店便宜許多。

2012年6月22日 星期五

台幣

在一夜之間,所有台灣的 App Store 的幣值從原本的美金改成台幣
Mac App Store 也一樣
這樣子是很方便,至少不用拿著計算機換算了

2012年6月21日 星期四

即將完成

這次這個 App 總算進入完成階段了
只要將設定的資料寫入檔案儲存起來就可以送給 Apple 審核了
目前預定價格是 USD 1.99$ (NTD 60$)
上架時特價免費一週,近請期待。

2012年6月20日 星期三

第二畫面樣式

原本的畫面是長得這個樣子
不過我多做了新的畫面供使用者選擇
之後在程式的設定畫面中就可以選擇你想要哪一種的畫面了

2012年6月18日 星期一

字型設定

這次是上一篇說的字型設定教學,
這部份我是在一個 App 裡面發現到的,
因為 App 裡面有字型的檔案,
所以才找了字型相關的設定,
接下來就正式開始教學了。
要設定字型當然要先準備字型檔案,
任何一個都可以,
準備好後就直接放入專案中,

有時候 Xcode 很神奇的不會將新增的檔案加入 "Copy Bundle Resource" 中,
所以這時候就要手動加入了,
只要將左邊的專案檔案清單中的檔案直接拉入就可以了,
我之前一直失敗,無法自定字型,結果就是這個原因,
之後到 Targets 的 Info 設定字型檔案,
如果有多個字型檔案就一直加下去就可以了,
之後就是正式設定字型了,
在 .m 檔中你想要建立字型的地方打入,
UIFont *newFont = [UIFont fontWithName:@"字型名稱" size: 字型大小 (CGFloat)];
之後在要顯示的 Label 或 TextField 使用 setFont: 就可以增加了

設定字型後的結果就像是這樣子

基本介面完成

經過兩天的努力,總算將基本介面完成了,
這次有增加第一次啟動時的簡介畫面
也有另外做中文版本的
關閉簡介後的畫面
畫面的底圖是參考台灣早期的轉盤式公共電話的配色,
加了一點經過風吹日曬後的塑膠劣化的痕跡
另外在左上角增加了有點不符時代的 LCD 螢幕,
來顯示撥號的數字,當然顯示的字型是 LCD 風格的,
有空我再做修改字型的教學。

2012年6月14日 星期四

Social Framework

iOS 6 開始將所有的社群功能都整合在一個 Framework 上面
就是 Social Framework
使用上也非常簡單
而且要使用 Twitter 時不需要再用舊的 Twitter Framework 了
說不定 Twitter Framework 會是最短命的 Framework

先加入 Social.framework 到專案裡面
之後只要 #import <Social/Social.h> 加入你的 h 檔裡面
接下來就宣告一個名稱給它
SLComposeViewController *social;
這樣子就可以在 m 檔中直接使用了

使用方式如下:
// 設定 Social 的類型
social = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
其中
SLServiceTypeFacebook 就是 Facebook
SLServiceTypeTwitter 就是 Twitter
SLServiceTypeWeibo 就是微博

發送訊息
[social setInitialText:NSSiring];

也可以附加圖片傳送
[social addImage:UIImage];

或是網址
[social addURL:NSURL];

2012年6月12日 星期二

iOS 6 Beta 1 簡單測試

今天半夜一點正是 WWDC 的第一天

這天發表了 iOS 6 與 OS X 10.8 Mountain Lion 兩個作業系統
而 iOS 6 要到秋天才會正式開放給一般使用者使用
因為我是付費開發者,所以可以搶先試用

我個人習慣是一個新系統是從設定看起
所以就先看設定了

設定畫面有做了一點變動,由上而下是
最先是 Statusbar 從原本的灰色改成淺藍色
再來是"藍牙"功能移動到第一頁了
最後是 iOS 6 的新功能"勿打擾"
(因為我是使用英文介面,所以翻譯會有所差異,請見諒)

勿打擾開啟的時候就你的裝置就不會發出任何的聲音與螢幕也不會有點亮的動作
讓你夜晚睡眠的時候不會被打擾
另外這個功能可以設定行程,可以為設定 24 點到 7 點之間自動啟動
另外分享功能從原本的 Twitter 增加了 Facebook 與 Sina 微博兩個功能
Facebook 的設定頁面

接下來是相片的功能
原本的相片串流的選項改到下面了
不會與原本的相片混在一起了

再來是大家較在意的功能"地圖"
iOS 6 中的地圖不再由 Google 進行支援了
改用 TomTom 的圖資
至少不用擔心台灣的資訊會不完全
但是街景功能就消失了

希望 Google 另外推出地圖 App

再來是通訊錄
通訊錄的群組選項改到左上方去了
介面外觀也有些許的修改

電話功能的撥號介面大改
顏色從原本的暗色系改成亮色系

提醒事項的 Bug 修正
原本在設定中使用了"取用限制"功能來禁止"定位服務"功能變動時
"在指定位置傳送提醒"的功能會無法使用
現在就沒這個問題了

另外 App Store 介面更動
主要畫面修改
排行榜介面修改
增加了 App 下載時的下載進度顯示
搜尋介面

Safari 介面小改
分享功能增加了之前說到的那些

相機介面也更動了,從原本灰色改成黑的

另外對台灣的使用者好消息是注音鍵盤更動為一般電腦的樣式了

另外還有 Siri 沒有測試,因為我的是 iPhone4 所以無法使用 Siri
所以就不測試了