KOYAMA Yoshiaki のブログ

プログラミングについての試行錯誤をつらつら書き溜めていきます。

WWDC、E3、Objective-C のブロックと変数

WWDC 2012 基調講演が、11日午前10時 (日本時間、翌12日午前2時) に開催されました。Mac Book Air / Pro、iOS 6、OS X Mountain Lion の発表がありましたが、一番の関心は、Retina ディスプレイ MacBook Pro の発表です。iPadiPhone アプリ開発のために、iMac 27 インチを使用してきましたが、Retina ディスプレイ MacBook Pro でも問題なさそうです。所有してる iMac (Mid 2010) 27 インチは、Thunderbolt、USB 3.0 に対応していないので、購入時期も迫ってきています。Retina ディスプレイ iMac が発表されていら、間違いなく購入していました。もう一年、我慢しようか、悩みどころです。


基調講演は、Apple のサイト

Apple - Apple Events - Apple Special Event March 2012
http://events.apple.com.edgesuite.net/123pibhargjknawdconwecown/event/index.html

で見れます。Podcast でも配信されています。

iTunes - Podcast - Apple Inc.「Apple Keynotes」
http://itunes.apple.com/jp/podcast/apple-keynotes/id275834665

iTunes - Podcast - Apple Inc.「Apple Keynotes (1080p)」
http://itunes.apple.com/jp/podcast/apple-keynotes-1080p/id509310064

iTunes - Podcast - Apple Inc.「Apple Keynotes (HD)」
http://itunes.apple.com/jp/podcast/apple-keynotes-hd/id470664050

1080p、HD 版も配信されています。


E3 も開催されていました。

E3 2012 - GameSpot.com
http://e3.gamespot.com/

上のサイト、左上の赤の背景に白色の文字で E3 2012 と表示されている部分をクリックし、Press Conferences を選ぶとそれぞれの基調講演を見ることができます。また、任天堂の基調講演は

任天堂 E3 2012情報 | E3レポート
http://www.nintendo.co.jp/n10/e3_2012/report/index.html

でも見れます。


以前、[id:KYoshiaki:20120429] iCloud プログラミングで書いた

Creating iOS 5 Apps: Develop and Design

Creating iOS 5 Apps: Develop and Design

[Kindle 版] と復習のために買った

Objective-C Programming: The Big Nerd Ranch Guide (Big Nerd Ranch Guides)

Objective-C Programming: The Big Nerd Ranch Guide (Big Nerd Ranch Guides)

[Kindle 版] を読み終えました。


Blocks とスコープ外の変数について、理解が深まりました。

typedef void (^ArrayEnumerationBlock)(id, NSUInteger, BOOL *);

ArrayEnumerationBlock devowelizer;

NSMutableArray *newStrings = [NSMutableArray array];

devowelizer = ^(id string, NSUInteger i, BOOL *stop) {

        NSMutableString *newString = [NSMutableString stringWithString:string];

        for (NSString *s in vowels) {
            NSRange fullRange = NSMakeRange(0, [newString length]);
            [newString replaceOccurrencesOfString:s withString:@"" options:NSCaseInsensitiveSearch range:fullRange];
         }
         [newStrings addObject:newString];
};

[oldStrings enumerateObjectsUsingBlock:devowelizer];


上のように、block 内で

[newStrings addObject:newString];

とスコープ外の変数 newStrings の内容を変更することができます。これは、メソッドを呼んでいるからです。プロパティで代入する場合も、同じです。

typedef void (^SampleBlock)();
__block NSString *two = [NSString stringWithString:@"two"];

SampleBlock sampleBlock;
FooClass *fooClass;
 
fooClass = [[FooClass alloc] init];

sampleBlock = ^() {
    NSString *three = [NSString stringWithString:@"three"];
            
    fooClass.foo = [NSString stringWithString:@"Orange"]; 
    two = three;
     changeValue(8);
};

sampleBlock();

ブロック内で

fooClass.foo = [NSString stringWithString:@"Orange"]; 

と代入することができます。ここでは、説明しやすいように

self.foo = bar;

とします。


実際には、ドット演算子を使ったプロパティは

The Objective-C Programming Language: Declared Properties
https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1

▼ Declared Properties
	▼ Property Declaration and Implementation
		Property Declaration
Key-Value Coding Programming Guide: Key-Value Coding Fundamentals
https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/BasicPrinciples.html#//apple_ref/doc/uid/20002170-BA

▼Key-Value Coding Fundamentals
	Dot Syntax and Key-Value Coding

を利用しているので

[self setFoo:bar];

または

[self setValue:bar forKey:@"foo"];

と同一です。故にメソッドを使っているので、block 内で代入できます。

foo = bar;

は、block 内で使えないので注意してください。foo が Objective-C のオブジェクト、または int、double などのスカラー型いずれの場合でも、__block を宣言しない限り、ブロック内では代入できません。

sample(bar);

上のような C の関数は、ブロック内で使えます。


結局、Cの関数、Objective-C の method は、ブロック内で使うことができます。また、プロパティを使ったドット表記も、実際には method を使っているので、ブロック内で使えます。ブロック内でスコープ外の変数に = (イコール) を使った代入は、__block を宣言しないと使えません。


サンプルとして zip ファイルを公開します。

VowelMovement.zip
http://kyoshiaki.sakura.ne.jp/osx/Sample/VowelMovement.zip


Creating iOS 5 Apps: Develop and Design

Creating iOS 5 Apps: Develop and Design

[Kindle 版] で見つけた面白い Blocks の使い方のサンプルも下記 URL で公開します。

Weights.zip
http://kyoshiaki.sakura.ne.jp/osx/Sample/Weights.zip


サンプルは、[ Creating iOS 5 Apps: Develop and Design ] [Kindle 版] のソースから、面白い使い方の箇所を抜き出して修正したものです。

//
//	Weights.m
//
- (void)processWeightEntryUsingBlock:(void (^)(NSNumber*)) block
{
    
    NSLog(@"Weights.entries: %@", self.entries);
    
    for (NSNumber* entry in self.entries) {
        block(entry);
    }
}
//
//	States.m
//
-(void)doStates
{
 
    NSMutableArray *array;

    array = [NSMutableArray array];
    
    [self.weights processWeightEntryUsingBlock:^(NSNumber *number) {
        int value;
        NSNumber *num;
        
        value = [number intValue];
        num = [NSNumber numberWithInt:value*2];
        
        [array addObject:num];
    }];


    NSLog(@"processWeightEntryUsingBlock: %@", array);

}