3

CS193P コース (Objective-C) のコードを試していました。コンパイラの動作の仕方で何かに気づきました。とNSMutableArray呼ばれるphotosが に追加されましNSMutableDictionaryphotosByPhotographer。その後、 に変更をphotos加えることなく に変更が加えられましたphotosByPhotographer。ログに記録するphotosByPhotographerと、変更が自動的に適用され、追加のコード行は必要ありませんでした。

コンパイラがこれをどのように機能させるのだろうか?読む資料はありますか?

コードは次のとおりです。

- (void)updatePhotosByPhotographer
{
    NSMutableDictionary *photosByPhotographer = [NSMutableDictionary dictionary];
    for (NSDictionary *photo in self.photos) {
        NSString *photographer = [photo objectForKey:FLICKR_PHOTO_OWNER];
        NSMutableArray *photos = [photosByPhotographer objectForKey:photographer];
        if (!photos) {
            photos = [NSMutableArray array];
            [photosByPhotographer setObject:photos forKey:photographer];
            NSLog(@"photosByPhotographer in if: %@", photosByPhotographer);
        }
        [photos addObject:photo];
        NSLog(@"photosByPhotographer after if: %@", photosByPhotographer);
    }
    self.photosByPhotographer = photosByPhotographer;
}

結果は次のNSLog()とおりです。

2012-07-20 20:05:57.618 Shutterbug[453:f803] photosByPhotographer in if: {
Dowbiggin =     (
);
}

2012-07-20 20:05:57.620 Shutterbug[453:f803] photosByPhotographer after if: {
Dowbiggin =     (
            {
        accuracy = 16;
        context = 0;
        dateupload = 1342836026;
        description =             {
            "_content" = "";
        };
        farm = 9;
        "geo_is_contact" = 0;
        "geo_is_family" = 0;
        "geo_is_friend" = 0;
        "geo_is_public" = 1;
        id = 7612787270;
        isfamily = 0;
        isfriend = 0;
        ispublic = 1;
        latitude = "37.307085";
        longitude = "-121.900395";
        originalformat = jpg;
        originalsecret = 052e70d412;
        owner = "22751315@N05";
        ownername = Dowbiggin;
        "place_id" = cils8sJUV7MeXHwt9A;
        secret = 4437007c99;
        server = 8161;
        tags = "square squareformat iphoneography instagramapp uploaded:by=instagram foursquare:venue=49f13597f964a5209c691fe3";
        title = "My little goofball";
        woeid = 55971033;
    }
);
}
4

4 に答える 4

5

これは、Cocoaでは、オブジェクトを使用して参照を渡すためです。

このコードを想像してみてください。

NSMutableArray *a, *b;

a  = [NSMutableArray new];
[a addObject:@"A"]; // a contains @"A"
b = a; // b is assigned to the same object
[b addObject:@"B"]; // a and b contain @"A", @"B"

NSLog(@"a = %p and b = %p", a, b); // same values

変数aとは同じオブジェクトをb 指します。ポインタ値を比較することによってもそれを見ることができます。

ただし、次のようにすると、次のようになります。

NSMutableArray *a, *b;

a  = [NSMutableArray new];
[a addObject:@"A"]; // a contains @"A"
b = [[a mutableCopy] autorelease]; // b is assigned to a COPY of the object
[b addObject:@"B"]; // b contains @"A", @"B", while a still contains @"A"

NSLog(@"a = %p and b = %p", a, b); // NOT the same values

ba(オリジナルではなく)のコピーに割り当てられているためb、他のオブジェクトを指します。オブジェクトのアドレスを比較して確認できます。

于 2012-07-21T19:45:19.687 に答える
3

ポインターと参照がどのように機能するかを理解する必要があります。基本的に、コード内の変数は実際の完全な構造体およびオブジェクトではなく、一般にそれらの構造体への参照またはポインターです。この概念はさまざまな方法で視覚化できますが、おそらく次のような変数を考えると便利です。

NSDictionary *myDict;

myDict オブジェクトのメモリアドレスである実際の数値です。これがどのように機能するかを視覚化したものです:

ここに画像の説明を入力

あなたのNSDictionary参照は、それ自体が他のオブジェクトへの複数の参照を保持するメモリ内のオブジェクトを指しています。これは、辞書自体に影響を与えることなく変更できます。この例ではNSArray、新しいオブジェクトが追加された を示しました。ディクショナリからの配列への参照は同じままです。配列とその中のオブジェクトのインスタンスは常に 1 つだけです。

于 2012-07-21T20:29:17.480 に答える
3

photos配列は、コピーとしてではなく、参照によって NSDictionary に格納されます。したがって、基になる配列を変更すると、ディクショナリにアクセスしたときにそれが表示されます。

これが、一部の変更可能な型のコピーを格納する代わりに、参照によって提供することが危険な場合がある理由です。

于 2012-07-21T19:41:35.580 に答える
0

オブジェクトを呼び出すNSLogと、NSDictionaryそのメソッドdescriptionが呼び出されます。

メソッドの実装では、すべてのキーの各値 (オブジェクト) のメソッドをdescription呼び出しNSDictionaryています。descriptionしたがって、値 (オブジェクト) が変更されると、そのdescriptionメソッドの出力も変更されます。NSLogそのため、NSDictionaryオブジェクトを再度呼び出したときに反映されます。

于 2012-07-21T19:53:30.590 に答える