顯示具有 iphone 標籤的文章。 顯示所有文章
顯示具有 iphone 標籤的文章。 顯示所有文章

2014年6月26日 星期四

iOS 7 的 MotionEffects

iOS 7 剛出來時,大家第一個會注意到的事在 Lock Screen 有一個會動的背景;那就是 Motion Effects。
其實它很簡單,我試著在一個UIView 加上一個 UIButton,接著讓 Button 是浮動的。看程式碼就懂了。

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    aButton.layer.mask.frame = aButton.bounds;
    aButton.layer.masksToBounds = YES;

    UIInterpolatingMotionEffect *xAxis = [[UIInterpolatingMotionEffect alloc]
                                          initWithKeyPath:@"center.x"
                                          type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];

    xAxis.minimumRelativeValue = [NSNumber numberWithFloat:-90.0];
    xAxis.maximumRelativeValue = [NSNumber numberWithFloat:90.0];

    UIInterpolatingMotionEffect *yAxis = [[UIInterpolatingMotionEffect alloc]
                                          initWithKeyPath:@"center.y"
                                          type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];

    yAxis.minimumRelativeValue = [NSNumber numberWithFloat:-90.0];
    yAxis.maximumRelativeValue = [NSNumber numberWithFloat:90.0];

    UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc]init];
    group.motionEffects = @[xAxis, yAxis];
    [aButton addMotionEffect:group];
}

2013年12月4日 星期三

如何存取iPhone 通訊錄裡的資料

iPhone 內部是使用 SQLite3 作為通訊錄的資料庫,但是因為沙盒的限制(沙盒「sandbox」: 指程式在一個獨立且受限的虛擬環境裡執行,可確保不會受其它干擾,也不干擾其它程式運作) 。所以,你是無法直接讀取的必需透過 XCode 所提供的 AddressBook.framework 來讀取和寫入資料。

而 AddressBook.framework 所提的 API,比較接近 C 語言,無法直接使用 NSArray, NSString 來定義變數;其實,在學XCode以來,在 AddressBook.framework 所定義的變數保留字,一直給我一種“為定義而定義”的感覺,很多餘。但不列出來,再過一陣子,我一定會忘了;在此,先列出在 AddressBook.framework 中所使用的變數保留字。

  • ABAddressBookRef : 用來宣告 AddressBook物件變數,AddressBook物件在使用上,和 NSManagedObjectContext 一樣,任何對 iPhone 通訊錄的讀取或儲存,都需要透過 AddressBook物件來完成;而建立一個 AddressBook物件指令為 ABAddressBookRef addressBookObj = ABAddressBookCreateWithOptions(NULL, NULL);
  • ABRecordRef : 用來宣告 ABPerson 物件變數,一筆資料即為一 ABPerson 物件。例如: 產生一筆空白資料,指令為 ABRecordRef newPerson = ABPersonCreate();
  • CFTypeRef : 萬用變數宣告,其實它就是 void* ;用於字串、任一數值, 例如: CFTypeRef firstName;
  • CFArrayRef : 用來宣告陣列變數;

知道了 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**

2013年10月16日 星期三

iOS Development Program (IDP) 瞭解如何設定開發者環境


在註冊成為 Apple 開發者之後,接著便要著手設定環境開始開發 iOS App了;但很多初學者在還沒開始,便已經被如何設定開發環境,搞得昏頭轉向了。 以下便是我作的簡單的整理:

1.取得開發者認證 CA

一位合法的 iOS 開發者,要開發出可散佈的 App,首先要要先從 apple 取得合法的CA (所謂CA,即是Certificate Authority;電子憑證)。而 iOS 開發者認證CA有二種;“iOS Development” ﹠“iOS Distribution” ,就字面意思就是研發用和上架用(其實還有其它四種,這裡先不介紹)。iOS的認證採雙向認證;所以,要開發者自已先產生“憑證要求檔”,再用這個“認證授權檔”上傳至 Apple,來取得你專屬的認證(xxx.cer)。

1.1 建立“憑證要求檔”來向Apple 要求憑證:

先開啟程式“鑰匙圈存取”;在從程式選單選取“鑰匙圈存取“->“憑證輔助程式”->“從憑證授權要求憑證來開啟“憑證輔助程式”視窗。 

1.1.1 使用者電子郵件位址:請填入和開發者帳一致的Email Address.
1.1.2 一般名稱:你的英文名字 或 公司名稱.
1.1.3 已將要求:請選擇“儲存到磁碟”,並勾選取”指定密鑰配對資訊“

按選“繼續”,跳至“密鑰配對資訊”,其預設值為“2048 bit”﹠“RSA”,不用動;再來就一直按“續繼”,直到憑證要求檔建立為止。

當建立憑證要求檔後,在“鑰匙圈存取”的“鑰匙”類別,會產生二個鑰匙。

1.2 取得開發者憑證

1.2.1 上傳“憑證要求檔” 開啟網頁“http://developer.apple.com”,點取“iOS Dev Center”(此時可能會要求你登入,請登入),在右邊的快捷項目中,點取“Certificates, Identifiers & Profiles”;之後,點取"Certificates",來設定開發者憑證。

1.2.2 產生憑證設定檔(Profile) 在“Certificates, Identifiesr & Profiles”頁面下,點取“Certificates”下的“All“。再點取右邉的加號方塊來產生憑證設定檔;當你按了”加號方塊“後,進入Profile 設定頁面。 這時,有個很重要的事,若從來沒有下載和安裝過WWDR憑證(WWDR? 目前,所做的事都是為了取得私鑰,而WWDR就是公鑰啦!開發時需要同時要有公私鑰,請在“Profile設定頁面”的最下方,點連結 “Worldwide Developer Releations Certificate Authority”去下載。下載後,雙擊該檔,就會安裝至鑰匙圈了。

當安裝完Certificate後,在“鑰匙圈存取”的“憑證”類別,可以看到你所安裝的憑證。展開它,可看到它指向產生它的key。


總結上述的步驟;為了要取得開發所需要的電子憑證,要先自行產"憑證要求檔",在產生憑證要求檔後,便會在鑰匙圈內產生專用密鑰;接著登入“Apple 開發者網站”,先取得WWDR公用憑證,依指示上傳“憑證要求檔”,以產生開發者憑證,以上;
但要注意要在發開過程沒有錯誤,這三個東西,一個都不能少;也就是WWDR,開發者憑證和產生憑證用的專用密鑰,全都要都在鑰匙圈內。
有關CA憑證就是這樣啦~ 但可以開發了嗎?答是 ...還早,開發還需Provisioning profiles

2.在“Certificates, Identifiers & Profiles” 頁面中

2.1 Certificates:

用來管理CA憑證的地方,先前就是產生CA的方法。

2.2 Identifiers:

建立和管理另 AppID 的地方, 每一個App都有一組全世界唯一的ID,就在這裡建立管理;除了AppID,另外的是給Passbook和推播用的 ID。

2.3 Device:

建立和管理測試用的iPhone和iPad。一個開發者帳號只能列100個裝備(device)。

2.4 Provisioning profile:

管理Provisioning profile:(它的性質很像是一組設定檔)是Certificate/ID/Devices的集合(注意,我在device 使用複數)。舉例:假設我要開發一個新的App,叫“HappyApp”, 而devices已經建立了我和客戶所有測試用的機器。於是,我先到App ID去建立一組HappyApp專屬的ID,再到Provisioning 建立一組新的開發用profile,在profile設定頁面中,選擇一個開發用CA憑證和”HappyApp”的AppID,再將要測試用的機器勾選起來,最後按建立,便可產生一個給”HappyApp”開發用的provisioning profile
而要給”HappyApp”上架用的profile要另外建立(只需選上架用CA和這個”HappyApp”的ID即可)。最後,將這二個Profiles下載下來,放入XCode的Organizer(在啟起XCode程式,按shift+command+2,即可開啟Organizer)。新建HappyApp這個XCode專案時,要需要AppID一致,並在設定中分別選擇這二個Profiles給開發和上架用,即可

2013年4月22日 星期一

Xcode : 如何開啟 facebook 粉絲頁,在facebook app 或 Safari 上

開啟 facebook 粉絲頁,簡單一個指令搞定。
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:@"https://www.facebook/com/taiwanbreezeman"]];
若只是這樣,就遜了。 當 iPhone上有安裝 facebook app,最好能直接打開在 facebook app上。以下便是範例:
NSURL *url = [NSURL URLWithString:@"fb://profile/277473558949767"];
[[UIApplication sharedApplication] openURL:url];
問題來,在 profile 後面那一長串的數字是什麼?? 那便是 facebook 的 profile id。在我解釋如何取得profile id 前;容我介紹一下,social graph 和 profile id 的關係。
social graph 這個詞是2007由 facebook 所提出,其概念很簡單,每個人/事/物都是一個點;而關係是一個便是一條線。你,和親朋好友的關係;和就讀過的學校的關係;和工作的地點的關係;和去過的地點/餐廳或店家的關係; 想像一張白紙,在白紙的中心劃一個點代表你自已,在你自已點的周邊,點上代表著親朋好友/學校/公司/景點或店家的點。再將代表你的點和這些點以線代表關係,連起來。便可形成如下圖(來自Wiki),屬於你的 social graph。
Social_graph

而每一個點都有一個 profile 來描述這個點它代表的人/事/物。而每個點都擁有一個獨一無二的編號,那就是 profile id。
好,言歸正傳,取得 profile id 的方法有二種。 一種是,它就顯示在網址列上:
在網址上

而另一種,無法在網址列上找到。如下圖,是以關鍵字的方式顯示;那就需要 facebook另一個網址來查詢了,查詢網址格式為:"http://graph.facebook.com/{關鍵字}"。頁面顯示便是profile 的內容,在內容中找尋一個名為 "id" 的字串,後面所帶出來的數字,便是 profile id。
透過facebook

2013年4月10日 星期三

Xcode: 讀取 (read) / 寫入 (write) plist file

要開啟 plist file,首先要先知道 plist file 的根 (root) 是何種資料型態。"根"的資料型態有二種:Array / Dictionary。
plist 的根,只能是Array或Dictionary
依資料型態選擇不同,使用不同類別來開啟。

* Array範例:

NSString *plistPath = [[[NSBundle mainBundle] bundle]
stringByAppendingPathComponent:@"MyPlist.plist"];
NSArray *plistArray = [NSArray arrayWithContentsOfFile: plistPath]; //讀取plist file
NSString *propertyString = [plistArray objectAtIndex:2];            //取得字串物件
NSInteger *propertyInt = [[plistArray objectAtIndex:2] intValue]; //取得整數值
Bool propertyBool = [[plistArray objectAtIndex:2] boolValue];    //取得布林值
float propertyFloat = [[plistArray objectAtIndex:2] floatValue];   //取得浮點數值
[plistArray writeToFile:plistPath atomically:NO]; //回寫plist file

* Dictionary範例:

NSString *plistPath = [[[NSBundle mainBundle] bundle]
stringByAppendingPathComponent:@"MyPlist.plist"];
NSDictionary *plistDic = [NSDictionary dictionaryWithContentsOfFile: plistPath]; //讀取plist file
NSString *propertyString = [plistDic objectForKey:@"姓名"];            //取得字串物件
NSInteger *propertyInt = [[plistDic objectForKey:@"年齡"] intValue]; //取得整數值
Bool propertyBool = [[plistDic objectForKey:@"已婚"]  boolValue];    //取得布林值
float propertyFloat = [[plistDic objectForKey:@"身高"]  floatValue];   //取得浮點數

[plistDic writeToFile:plistPath atomically:NO]; //回寫plist file

2013年4月9日 星期二

Xcode : plist file 都支援那些資料格式















在上篇提到,plist file 可以儲存設定 / 資料,但其支援的的資料格式有那些?上圖為從 Apple developer 截圖下來的。一般而言,資料格式有 NSArray / NSDictionary / NSString / NSData / integer / float / Boolean。


  • NSString:儲存字串;
  • NSArray:objective-c 內的陣列型態,和C語言的陣列有些不同,在C語言宣告一個陣列為 "int index[10]",這個 index[] 僅能存放整數,依宣告不同的資料型態,而存放不同類型的資料;而NSArray的第一個不同是,僅能存放 objective-c 的 "id",所謂 "id" 即為物件。第二個不同是不能在放 int 資料,因為 int 資料不是物件,而需要將 int 資料轉為 NSNumber 物件來儲放。第三個不同是NSArray 僅能夠儲放 "id",只是物件都能儲放,可在第零位置上放置字串,第一放置NSData;並不限制要同一種資料型態。
  • NSDictionary:NSArray 這麼好用,在一個陣列中,可以放不同的資料。問題來了,不同位址放不同型態的資料,很難不搞混吧。我也不這麼作,風險太大了。用NSDictionary 吧!NSDictionary 用的不是位址來儲放資料,而是以key值來作索引,例如:以 "name" 來作姓名的索引,便可取出姓名的字串,或用 "age" 來作年齡的的索引,便可取年齡的整數值;
  • NSData:用來儲存 NSData物件,只要是能轉成 NSData的物件皆可;我曾將幾張小圖,分別用 NSData 物件存在 plist file,照樣可以用。
  • integer / float / Boolean:全部都是用 NSNumber 物件來儲存。寫入和讀出的指令要一致;千萬別寫入時用 numberWithBool 寫入boolean 值,而讀取時用 intValue,讀出來的卻是整數值,那就糗了。


ref: Apple developer

如何在 Xcode 中,新增一個 plist file



當在 Xcode 上打開了一個專案, 一定可以在左邊檔案列表㯗內,Support Files下找到一個名為“{專案名稱}-info.plist“的檔案,從內容中可以看到,可以設定設備可支援肖像模式和風景模式,預設 Navigation bar 是黑色的。在這個檔案內,可以任意的添加和修改程式的預設值。



而 plist file 也可以儲存程式中的設定和資料。(當然,用 UserDefault介面和 DB 也可以)。
接下來,在專案內,新增一個 plist file。
在專案中,點取要放置新增 plist 檔的目錄,按滑鼠右鍵,點取 "New file..."。在樣版視窗中,選擇 “iOS -> Resource -> Property List -> Next";接著輸入檔名/存檔即可。


接著,便可在 plist file 中,輸入你想要輸入的資料或設定了。




2013年4月8日 星期一

iOS Apps上架,所需要 Icons 的大小


(2013/12/10 更新 ; ref: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html#//apple_ref/doc/uid/TP40006556-CH27-SW1)

Apple對於 iPad 和 iPhone 的 Apps 上架,需要開發者提供數個不同像素的 Icons 來滿足應用上的需要;這些 Icons 會在那些地方出現呢?目前這些 Icons 會出現的地方有 iPad和iPhone的主畫面 (Home screen) 、App Store、和Spotlight search的結果:


  1. 給iPhone的Apps. 必需要提供的要4種;非必要的4種:
            1. 1024x1024 pixels:用來使用於 App Store 內顯示用。
            2. 120x120 pixels:App Icon 顯示於 iPhone 主畫面上;
            3. 76x76 pixels:給非Retina的iPad使用;因為iPhone的程式亦可以使用於iPad上。故需支援。
            4. 152x152 pixels:最後是給支援Retina 的iPad使用。
           
            而非必要的分別是 29x29 / 58x58 / 40x40 / 80x80 pixels. 分別用於設定頁面中使用;為了有美美的 Icons,建議還是加進去。
       

       2. 給iPad的Apps. 無法在iPhone上執行。所以必需要提供的,只要3種,不需提供120x120pixels;非必要的照舊是同上4種:

    iOS: 在ARC環境下,指定特定檔案關閉ARC。


    在目前的開發環境下,一定都會開啟ARC (Automatic Reference Counting),來避免記憶體滲漏 (Memory leak)。






    在開發的過程中,不免會使用到先前開發過專案的原始碼。但無法確保先前專案會開啟ARC選項;
    沒有ARC選項的開發的原始碼在有ARC環境下編譯,最常會遇到編譯錯誤碼:

                 not available in automatic reference counting mode




    其解決方法為 只針對該原始碼檔去關閉ARC選項;
    方法步驟如下:


     1. 在 "Project Navigator"下,點選專案頭 (Project root).
     2. 在 "Targets"的選單下,點選目標項目。
     3. 點選 "Build Phases",並展開 "Compile Sources".
     4. 點選你要關閉 ARC功能的檔案,雙擊該檔案,並在跳出對話窗,填入 "-fno-objc-arc" 指令;

    照上述步驟,便可關閉該檔ARC功能。


    本機上簡單易上手的 Source Code Control - git

    若只是要在自已的電腦上,擁有一個簡單易使用的原始碼管理系統(Version Control System:VCS),我認為 git 是一個不錯的選擇。在此提供一個很簡單的示範和說明;看完這篇你可以得到: 1. 看完示範和說明,你就可以馬上在你的電腦上使用 git 。 2. 瞭解git中的 working directory - staging area - repository 之間的關係。 3. 如何修改 git容器的名稱。
    第一個範例如下:
    $ mkdir demo
    $ cd demo
    $ git init
    Initialized empty Git repository in /root/demo/.git/
    $ touch foo
    $ git add foo
    $ git commit 0m 'a demo'
    
    在這個範例中,有三個 git 的指令,分別是 init / add / commit;
    init : * 這指令會在目前的目錄下 (即為工作目錄working directory的根目錄),產生一個 ".git" 的子目錄,這個名為 ".git" 的子目錄,即為git 的容器(repository)。
    • 而技術上 ".git"的名稱是可以改的,只要在執行 init 前,宣告一個 GITDIR="你希望的名稱" 的環境變數即可。例如 "export GITDIR=.test" 。再執行 init ,便會產生一個名為 ".test"的子目錄為 git容器!
    • 另外,git 和 svn 不同的是 git容器只會存在工作目錄的根目錄;而 svn系統下,名為 ".svn"的子目錄,會存在於根目錄和其所有的子目錄。
    add: * 在工作目錄下,任何新增或修改過的檔案。要送交(commit)至容器前,一定要先註記為已完成階段性(staging)工作。故透過 add 指令,將註記新增或修改過的檔案,並加入已完成階段性檔案區域 (staging area)。(staging area僅是個邏輯的區域,並不會真的有個目錄作為staging area)
    • 已放入 staging area的檔案,若有新的修改,即會被強迫脫離staging area,取消註記。需再透過 add 指令重新註記檔案。
    commit : * 最後,透過 commit 指令,將目前的版本送交至容器。
    整個狀態,可以用下圖來描述:
    狀態圖
    而在第一次送交時,可能會有下列錯誤訊息。
    錯誤訊息」
    那是因為 git 要求要有記錄是誰送出這次送交的。可就訊息中的指令範例去設定使用者名稱和使用者 Email。這只要設定一次即可。設定後,會在使用者家目錄下,產生一個 ".gitconfig" 檔案,記錄著你的設定。

    git - 看懂 file status


    當在管理 git 時,經常會使用 git status 來檢視目前工作目錄(working directory)下,有那些檔案被修改了,而又有那些修改過的檔案已經放入已完成階段性工作區域 (staging area)。所以,git status 算是非常常用的指令。

    話不多說,直接先在工作目錄下執行 git status 看看吧~

    在上圖範例中,告訴著有那些訊息呢?
    1. On branch master : 目前正位於master 分支上。
    2. Changes to be committed: 描述著有那些檔案已經放入 staging area。目前看到有一個被修改過的檔案 "foo" 正等著被送交(commit)。
    3. Changes not staged for commit: 列出了那些在容器中存在的檔案,而被修改過尚未加入 staging area。
    4. Untracked files: 列出那些檔案,是 git 從未追蹤過的新檔案。