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 預定是要做指針式時鐘,
程式方面已經完成了,只差美工的部分而已,
所以打算使用一段長時間來解決