3

新しい表記法は次のように機能すると思いました。

someArray[5] は次のようになります

someArray[5] は実際には [someArray objectAtIndexedSubscript:5] に変わります

ただし、 NSArray.h と NSOrderedSet.h でこれを見ました:

- (id)objectAtIndexedSubscript:(NSUInteger)idx NS_AVAILABLE(10_8, 6_0);

したがって、objectAtIndexedSubscript は IOS6 でのみ使用できます。

この簡単なコードを作成してみました:

NSArray * someArray =@[@"hello",@"World",@"World"];
NSOrderedSet * someOS = [NSOrderedSet orderedSetWithArray:someArray];
PO(someArray);
PO(someOS);
PO(someArray[0]);
PO(someOS[0]); //Exception thrown here

someOS[0] でのコード ブレーク

-[__NSOrderedSetI objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x8b1fac0

NSArray と NSOrderedSet の両方に、テキスト NS_AVAILABLE(10_8, 6_0); があります。

それでも、NSArray では壊れませんが、NSOrderedSet では壊れます。なんで?

ボーナス: カテゴリを使用して NSOrderedSet でも機能させるにはどうすればよいですか (まだ定義されていないことを確認する必要があります)

4

3 に答える 3

3

これをもう少し詳しく調べると、iOS 6 では NSOrderSet には -objectAtIndexedSubscript: しかありませんが、iOS 5 と iOS 6 の両方で NSArray には -objectAtIndexedSubscript: しかないようです。

私のテストでは、次のことが示されました。

- (void)testNSOrderedSetObjectAtIndexedSubscript
{
    NSString *systemVersion = [UIDevice currentDevice].systemVersion;
    NSString *message = @"NSOrderedSet for %@ does not respond to -objectAtIndexedSubscript:";

    NSOrderedSet *orderedSet = [NSOrderedSet orderedSet];
    STAssertTrue([orderedSet respondsToSelector:@selector(objectAtIndexedSubscript:)], message, systemVersion);
}

- (void)testNSArrayObjectAtIndexedSubscript
{
    NSString *systemVersion = [UIDevice currentDevice].systemVersion;
    NSString *message = @"NSArray for %@ does not respond to -objectAtIndexedSubscript:";

    NSArray *array = [NSArray array];
    STAssertTrue([array respondsToSelector:@selector(objectAtIndexedSubscript:)], message, systemVersion);
}

iOS 5.0 シミュレーター

Test Case '-[SIObjectTests testNSArrayObjectAtIndexedSubscript]' started.
Test Case '-[SIObjectTests testNSArrayObjectAtIndexedSubscript]' passed (0.000 seconds).
Test Case '-[SIObjectTests testNSOrderedSetObjectAtIndexedSubscript]' started.
/Users/jthomas/workspaces/si-catalog-order-ios/SICatalogOrderTests/SIObjectTests.m:20: error: -[SIObjectTests testNSOrderedSetObjectAtIndexedSubscript] : "[orderedSet respondsToSelector:@selector(objectAtIndexedSubscript:)]" should be true. NSOrderedSet for 5.0 does not respond to -objectAtIndexedSubscript:
Test Case '-[SIObjectTests testNSOrderedSetObjectAtIndexedSubscript]' failed (0.000 seconds).

iOS 6.0 シミュレーター

Test Case '-[SIObjectTests testNSArrayObjectAtIndexedSubscript]' started.
Test Case '-[SIObjectTests testNSArrayObjectAtIndexedSubscript]' passed (0.000 seconds).
Test Case '-[SIObjectTests testNSOrderedSetObjectAtIndexedSubscript]' started.
Test Case '-[SIObjectTests testNSOrderedSetObjectAtIndexedSubscript]' passed (0.000 seconds).
于 2012-11-16T20:26:02.820 に答える
3

もっと良い答えがあります!

NSOrderedSetこのコードは、サポートしていない iOS のバージョンに対して動的にパッチを適用します-objectAtIndexedSubscript:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

id PatchedObjectAtIndexedSubscript(id self_, SEL cmd_, NSUInteger index)
{
    return [self_ objectAtIndex:index];
}

void PatchedSetObjectAtIndexedSubscript(id self_, SEL cmd_, id object, NSUInteger index)
{
    return [self_ replaceObjectAtIndex:index withObject:object];
}

void SIPatchNSOrderedSet()
{
    char types[6];

    if (!class_getInstanceMethod([NSOrderedSet class], @selector(objectAtIndexedSubscript:))) {
        sprintf(types, "@@:%s", @encode(NSUInteger));
        class_addMethod([NSOrderedSet class],
                        @selector(objectAtIndexedSubscript:),
                        (IMP)PatchedObjectAtIndexedSubscript,
                        types);
    }

    if (!class_getInstanceMethod([NSMutableOrderedSet class], @selector(setObject:atIndexedSubscript:))) {
        sprintf(types, "v@:@%s", @encode(NSUInteger));
        class_addMethod([NSMutableOrderedSet class],
                        @selector(setObject:atIndexedSubscript:),
                        (IMP)PatchedSetObjectAtIndexedSubscript,
                        types);
    }
}

アプリケーションの開始時に (-application:didFinishLaunchingWithOptions:おそらく) を呼び出しますSIPatchNSOrderedSet()

于 2012-11-16T22:19:45.953 に答える
0

Jeffry answer は素晴らしく、セレクターの動作を宣言する方法についての洞察を提供します。

別の方法として、私は単にこれを行います:

self.businessDetailed.Phones.array[0];

そして、未来の孫たちに、それを変えるように言います。

self.businessDetailed.Phones[0];

iPhone 15が発売されたとき。

途中で限界費用がわずかに増加するという犠牲を払って、Jeffryのソリューションよりもはるかに少ない作業です。

于 2012-11-20T10:20:19.703 に答える