最近常使用 Sublime Text 來編輯一些文件,有時候,電腦重灌就忘了一些常用套件是怎麼裝旳,以下列一些常用的套件的URL吧!
Sublime Text 2 http://www.sublimetext.com/2 Package Control https://sublime.wbond.net/installation#st2 Markdown preview https://github.com/revolunet/sublimetext-markdown-preview
最近常使用 Sublime Text 來編輯一些文件,有時候,電腦重灌就忘了一些常用套件是怎麼裝旳,以下列一些常用的套件的URL吧!
Sublime Text 2 http://www.sublimetext.com/2 Package Control https://sublime.wbond.net/installation#st2 Markdown preview https://github.com/revolunet/sublimetext-markdown-preview
接著上一篇如何存取iPhone 通訊錄裡的資料,接著就是要新增一筆資料寫入通訊錄了。其實很簡單,只要呼叫 ABPersonCreate(); 便可產生一筆空白資料,多項資料(MultiProperty)比單項資料(Property)多了一道處理程序;直接來看範例~
NSString *firstName, *lastName, ... ;
NSDictionary *emails;
...
//產生 AddressBook 物件
ABAddressBookRef addressBookObj = ABAddressBookCreateWithOptions(NULL, NULL);
//產生一筆空白聯絡人資料
ABRecord record = ABPersonCreate();
//處理單項資料 (property)
ABRecordSetValue(record, kABPersonFirstNameProperty, CFBridgingRetain(firstName) , nil);
ABRecordSetValue(record, kABPersonLastNameProperty, CFBridgingRetain(lastName) , nil);
//處理多項資料 (MultiProperty)
NSArray *allLabels = [emails allKeys];
ABMutableMultiValueRef multiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
for(NSString *label in allLabels) {
NSString *value = [emails objectForKey:label];
ABMultiValueAddValueAndLabel(multiValue, CFBridgingRetain(value), CFBridgingRetain(label), NULL);
}
ABRecordSetValue(record, kABPersonEmailProperty, multiValue, nil);
//寫入&儲存
ABAddressBookAddRecord(addressBookObj,record,nil);
ABAddressBookSave(addressBookObj);
在上面的例子中,是直接產生一筆空白的聯絡人資料;若是換成即有存在的舊資料,也是可以的,但在處理多項資料時,若遇到已經存在的label,不可使用 ABMultiValueAddValueAndLabel,請改用 ABMultiValueReplaceValueAtIndex 去處理;
除了,直接寫入通訊錄外, framework 另外提供了預設的聯絡人的輸入UI,共有二套,一為 "ABNewPersonViewController";另一為 "ABUnknownPersonViewController";差別在於後者可以選擇覆寫即有的資料。
ABNewPersonViewController 的範例~
ABNewPersonViewController *newPersonVC = [[ABNewPersonViewController alloc] init];
ABRecordRef aNewRecord = ABPersonCreate();
newPersonVC.newPersonViewDelegate = self;
newPersonVC.addressBook = addressBookObj;
newPersonVC.displayedPerson = aNewRecord;
[currentNavigationViewController pushViewController:newPersonVC animated:YES];
ABNewPersonViewController 的範例~
ABUnknownPersonViewController *unknowPersonVC = [[ABUnknownPersonViewController alloc]init];
unknowPersonVC.unknownPersonViewDelegate = self;
unknowPersonVC.displayedPerson = aOldRecord;
unknowPersonVC.allowsAddingToAddressBook = YES;
unknowPersonVC.allowsActions = YES;
[currentNavigationViewController pushViewController:unknowPersonVC animated:YES];
iPhone 內部是使用 SQLite3 作為通訊錄的資料庫,但是因為沙盒的限制(沙盒「sandbox」: 指程式在一個獨立且受限的虛擬環境裡執行,可確保不會受其它干擾,也不干擾其它程式運作) 。所以,你是無法直接讀取的必需透過 XCode 所提供的 AddressBook.framework 來讀取和寫入資料。
而 AddressBook.framework 所提的 API,比較接近 C 語言,無法直接使用 NSArray, NSString 來定義變數;其實,在學XCode以來,在 AddressBook.framework 所定義的變數保留字,一直給我一種“為定義而定義”的感覺,很多餘。但不列出來,再過一陣子,我一定會忘了;在此,先列出在 AddressBook.framework 中所使用的變數保留字。
ABAddressBookRef addressBookObj = ABAddressBookCreateWithOptions(NULL, NULL);ABRecordRef newPerson = ABPersonCreate();CFTypeRef firstName; 知道了 AddressBook.framework 常用的變數保留字,就來將 iPhone 通訊錄中的 所有記錄取出來吧~
//產生 AddressBook 物件
ABAddressBookRef addressBookObj = ABAddressBookCreateWithOptions(NULL, NULL);
//取出所有聯絡人記錄
CFArrayRef allPeoples = ABAddressBookCopyArrayOfAllPeople(addressBookObj);
int numPeople = CFArrayGetCount(allPeoples);
//依續取出每個聯絡人資料
for(int i=0 ; i<numPeople; i++ ) {
ABRecordRef onePeople = numPeople[i];
// 取出該聯絡人所有資訊
}
有了聯絡人,接著就著手處理聯絡人所包含資訊。首先,資料有分單一資料(Property)和多項資料(MultiProperty),取出後的處理方法也不一樣; 先釐清一個觀念,CFDictionary(屬性:kABDictionaryPropertyType)是單一資料,雖然,Dictionary 可以包含很多資料;而屬性 kABMultiDictionaryPropertyTyple 才是多項資料;很明顯地,在屬性鍵值有'multi’的字眼,便是多項資料; 取出資料的指令為
CFTypeRef valueRef = ABRecordCopyValue(oenPeople, kABDictionaryPropertyType);
而要取出所有資料的方法如下:
for(ABPropertyID propKey = kABPersonFirstNameProperty; propKey <= kABPersonSocialProfileProperty; propKey++) {
//先取出數值
CFTypeRef valueRef = ABRecordCopyValue(onePeople,propKey);
ABPropertyType propType = ABPersonGetTypeOfProperty(propKey);
//判斷是單一資料或多項資料
if(propType & kABMultiValueMask) {
//多項資料處理
} else {
//單一資料處理
}
}
接著,讓我們看看在一筆聯絡人記錄中,帶有那些資訊吧~
| ABPropertyID | 描述 |
|---|---|
| kABPersonFirstNameProperty; | First name - kABStringPropertyType |
| kABPersonLastNameProperty; | Last name - kABStringPropertyType |
| kABPersonMiddleNameProperty; | Middle name - kABStringPropertyType |
| kABPersonPrefixProperty; | Prefix ("Sir" "Duke" "General") - kABStringPropertyType |
| kABPersonSuffixProperty; | Suffix ("Jr." "Sr." "III") - kABStringPropertyType |
| kABPersonNicknameProperty; | Nickname - kABStringPropertyType |
| kABPersonFirstNamePhoneticProperty; | First name Phonetic - kABStringPropertyType |
| kABPersonLastNamePhoneticProperty; | Last name Phonetic - kABStringPropertyType |
| kABPersonMiddleNamePhoneticProperty; | Middle name Phonetic - kABStringPropertyType |
| kABPersonOrganizationProperty; | Company name - kABStringPropertyType |
| kABPersonJobTitleProperty; | Job Title - kABStringPropertyType |
| kABPersonDepartmentProperty; | Department name - kABStringPropertyType |
| kABPersonEmailProperty; | Email(s) - kABMultiStringPropertyType |
| kABPersonBirthdayProperty; | Birthday associated with this person - kABDateTimePropertyType |
| kABPersonNoteProperty; | Note - kABStringPropertyType |
| kABPersonCreationDateProperty; | Creation Date (when first saved) - kABDateTimePropertyType |
| kABPersonModificationDateProperty; | Last saved date - kABDateTimePropertyType |
| kABPersonAddressProperty; | Street address - kABMultiDictionaryPropertyType |
| kABPersonDateProperty; | Dates associated with this person - kABMultiDatePropertyType |
| kABPersonKindProperty; | Person/Organization - kABIntegerPropertyType |
| kABPersonPhoneProperty; | Generic phone number - kABMultiStringPropertyType |
| kABPersonInstantMessageProperty; | Instant Messaging - kABMultiDictionaryPropertyType |
| kABPersonURLProperty; | URL - kABMultiStringPropertyType |
| kABPersonRelatedNamesProperty; | Names - kABMultiStringPropertyType |
| kABPersonSocialProfileProperty | kABMultiDictionaryPropertyType |
先來看看多項資料,要怎麼處理?
CFTypeRef *multiValueRef = ABRecordCopyValue(onePeople,propKey);
//先取得資料的數量
int numberOfValues = ABMultiValueGetCount(multiValueRef);
//在來依續取出其中的資料
for(int i = 0 ; i<numberOfValues ; i++) {
CFTypeRef *singleValureRef = ABMultiValueCopyLabelAtIndex(multiValueRef,i);
//單一資料處理
}
問題來了,取出來的數值型別皆為 CFTypeRef,若是很熟悉 CFType,那直接使用吧,但我就不熟,所以,還是要轉換成 XCode 常用的型別;
NSString *stringValue = CFBridgingRelease(valueRef); **//kABStringPropertyType**
NSNumber *numberValue = CFBridgingRelease(valueRef); **//kABIntegerPropertyType**
NSDate *dateValue = CFBridgingRelease(valueRef); **//kABDateTimePropertyType**
NSDictionary *dictionaryValue = CFBridgingRelease(valueRef); **//kABDictionaryPropertyType**
^可作為區塊運算的識別字。有關XCode 的區塊運算是一個非常方便的工具,它可以當作 callback function,也可以將一組function直接嵌入你要呼叫的function裡,例如://在沒有ARC下,可在ViewController 移除後,將自已給釋放
[myViewController dismissViewControllerAnimated:YES
completion:^() {
[myViewController release];
myViewController = nil;
}
];
在官網文件中,開宗明義指出You use the ^ operator to declare a block variable and to indicate the beginning of a block literal. The body of the block itself is contained within {}。 '^'符號作為區塊(Block)的開頭文字,在使用方法上,請見下圖不解釋了。//MyViewController.h
typedef void (^TouchedInside)();
@interface MyViewController : UIView
{
__strong TouchedInside _insideBlock;
}
-(void)setTouchedInsideBlock:(TouchedInside)insideBlock;
@end
//MyViewController.m
@implementation FPTouchView
-(void)setTouchedInsideBlock:(TouchedInside)insideBlock
{
_insideBlock = [insideBlock copy];
}
@end
//Declare in UIViewController.h
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion;
//sample
[myViewController dismissViewControllerAnimated:YES
completion:^() {
[myViewController release];
myViewController = nil;
}
];

UITextField 若需要客製化功能,需要加入UITextFieldDelegate, 使用上:
而在UITextFieldDelegate 中,常用的函數列出如下:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
//若不允許被編輯,則return NO,
- (void)textFieldDidBeginEditing:(UITextField *)textField;
//目前物件成為focus 物件
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
//return YES, 允許結束編輯並重設focus物件的狀能
//return NO,不允許結束編輯`
- (void)textFieldDidEndEditing:(UITextField *)textField;
//??
//may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
//return NO,不允許改變文字
- (BOOL)textFieldShouldClear:(UITextField *)textField;
//當 User按 clear按鈕, 則此函數會被呼叫;return NO 去忽略 clear 命令
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
//當 User 按 "換行"鈕, 則此函數會被呼叫;return NO 去忽略 換行 命令
以下有我使用上幾個實例,
我希望當使用者, 點 TextField 時,能跳出一個對話框、執行一個動畫、或一個選單;這時候,我可以使用 UITextField Delegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
進一步,我要 TextField 的內容,皆選單或程式完成,不要使用者直接輸入;這時候,我在這個函數的最後回傳“NO”,即可。有點像將 "User Interaction Disabled".
這是滿常見的,在將 TextField 的英文,轉換成大寫 (Upper case string)
- (IBAction)textFieldValueChanged:(id)sender {
firstNameField.text = [firstNameField.text uppercaseString];
}
RN: 2013Oct2:新增 範例一﹠範例二