2013年7月9日 星期二

Asset framework 簡單範例

ALAssets 簡介 參考

An instance of ALAssetsLibrary provides access to the videos and photos that are under the control of the Photos application.

The library includes those that are in the Saved Photos album, those coming from iTunes, and those that were directly imported into the device. You use it to retrieve the list of all asset groups and to save images and videos into the Saved Photos album.

簡單說就是其實存在 camera roll 裡的東西不是單純的影片和照片,而是一個一個的 Asset 裡面包很了很多其他的資訊,像是 Location。

昨天有位朋友問我要如何實現 iPhone 內建相機左下角打開 camera roll 的功能,且button要是camera roll裡最後一張的圖片。

這個 Button 分成兩個部份,一個是要如何擷取 camera roll 裡最後一張照片出來,第二個是要開啟相簿(目前似乎無法像 Apple 直接打開某一個 Asset)

要做到這功能必須使用 AssetsLibrary.framework 且要有 block 的觀念。

下載 DemoCode

這個 DemoCode 很多都是由 Apple 官方文件修改而來的,有興趣更進一步了解的可以參考 這裡

還有一點要注意的是,在 Democode 裡的 ViewController.h 必須 adopt UIImagePickerControllerDelegate 和 UINavigationControllerDelegate 協定

其他說明在 democode 裡都有註解表示了,就不在此多加闡述了,有問題可以留言。


2013年7月5日 星期五

Objective-C property屬性


Property 是在Objective-C 2.0之後才有的,主要是方便取存或設定物件裡的實體變數, 系統會幫你寫好 setter 和 getter (在 xcode4.5 之後不需要搭配 @sythesize 這個合成指令, compiler會幫你關聯至在原變數名稱前加上底線 ex  _abc).


另外 Property 有幾個屬性可以設定, 語法如下

@property(attribute1, attribute2…)int iVal;

這些屬性分別為

readonly : 唯讀,(compiler 不會幫你合成 setter method)。

readwrite : 可讀可寫(Default)。

assign : 在設值時替換新舊資料(Default)。

retain : 在設值時retain新的資料,release舊資料。

copy : 在設值時copy一份新資料,release舊資料。

strong /weak : iOS5 之後取代 retain 和 copy, 由compiler幫你決定使用那一種.

nonatomic : non safety thread

atomic :  safety thread(Default)

assign 就只是單純的將新值賦予變數, 如下

- (void)setX:(int)iVal {
       _value = iVal;
}

retain用於物件。會在給值前先 release 舊的值並於新的物件上將其引用計數器+1 後賦予變數, 如下

- (void)setX:(NSString*)sVal {
          if (_string != sVal ) {
                [_string release];
                _string = [sVal retain];
        }
}


copy 與 retain 基本上是一樣的, retain 是將該物件的引用計數器+1, 而 copy 會依照類別型態做不同的動作, 這部份還待理解....但是一切在 iOS 5 提出 ARC 後, retain 和 copy 都被 strong 和 weak 取代了, 交由 compiler 幫你決定是用 retain 或是 copy.

strong 跟 retain 沒兩樣, 每次呼叫時都會將引用計數器+1, weak 則只是單純的參照記憶體位址.

weak 最常用的兩個地方是 delegation 中的 id<myDelegate> delegate 和 subviews.

因為所有的 subviews 都被 mainview 所持有, 所以只需參照記憶體位址即可.

atomic 表示若同時有多個地方呼叫該變數的 setter 或 getter 則必須一個一個慢慢來. 較安全, 但效能較低.

nonatomic 表示多人能同時呼叫 setter 和 getter 安全性較低,但性能較高, 大多數時間都設定為此屬性.

2013年7月4日 星期四

Objective-C Delegate 委派觀念及使用整理

## DemoCode 下載

delegation 是一種 design pattern (設計模式),方便在各個物件之間傳遞參數以及互相支援。

@protocol 是Obj-c 裡的一個關鍵字,直到@end關鍵字做結束,通常宣告在 .h 檔置於 @interface 之上,用法如下:

//aaa.h
@protocol myDelegation <NSObject>
   @required
         -(void)delegationPrint;
   @optional
         -(int)delegationLog:(int) iVal;
@end

@interface aaa <NSObject>

@property (weak, nonatomic) id <myDelegation> delegate;
-(void) someMethod;
-(void)anotherMethod:(NSString *)str
@end
在 aaa.h 宣告了一個叫做 myDelegation 的 protocol(協定) 出來並定義兩個方法 delegationPrint 以及 delegationLog:

其中 delegationPrint 屬於 @require,表示若有其他類別採納了 myDelegation 這個protocol則"一定"要實現 delegationPrint 方法,否則編譯器會出現警告,反之 @option 則可以不實現。

再來宣告並讓編譯器自動合成一個 "採納 myDelegation" 的泛型物件叫做 delegate,且屬性為 weak及nonatomic 其中 weak 為必要,避免物件相互持有無法釋放造成 memory leak。

**採納myDelegation的泛型物件名稱為增加閱讀性,一般都固定名稱為 delegate,不建議採取其他名稱。

**唯有採納 myDelegation 的物件可以呼叫 @protocol 所定義的方法(method)。

程式流程怎麼跑用 log 來看最清楚不過了,所以在每個 Method 都加了 NSLog 方便大家做 tracking.

假設今天有個類別 bbb 採納了 aaa 的 protocol 則程式片段應如下。


//aaa.m
-(void) someMethod {
         //確保 delegate 不為空且可回應 delegatePrint Method
     if(self.delegate != nil && [self.delegate delegatePrint]){
         NSLog(@"aaa.m someMethod exec");
         [self.delegate delegatePrint];
     }
}

-(void)anotherMethod:(NSString *)str {
     if(self.delegate != nil && [self.delegate delegateLog:]){
        NSLog(@"aaa.m anotherMethod exec");
        NSLog(@"str = %@ and return = %d",str, [self.delegate delegateLog:123]);
     } 
}


// bbb.h
#import "aaa.h"
@interface bbb:UIVierController <myDelegation>
@end



//bbb.m
@implementation ViewController
-(void)viewDidLoad {
      aaa *myAAA = [aaa new];
      myAAA.delegate = self;
      [myAAA someMethod];
      [myAAA anotherMethod:@"Hello World!"];
}
-(void)delegationPrint{     NSLog(@" bbb.m delegationPrint exec"); } -(int)delegationLog:(int) iVal{     NSLog(@"bbb.m delegationLog exec");     NSLog(@"bbb.m delegationLog: %d",iVal);     return iVal*10; }
@end
程式執行的結果輸出如下

aaa.m someMethod exec

bbb.m delegationPrint exec

aaa.m anotherMethod exec

bbb.m delegationLog exec

bbb.m delegationLog:123

str = HelloWorld! and return = 1230


以上程式碼片段是人腦 coding + 人腦 compiler,若是有錯誤的地方還請大家指正。