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

深入研究一下,看起来 NSOrderSet 在 iOS 6 中只有 -objectAtIndexedSubscript: ,但 NSArray 在 iOS 5 和 iOS 6 中都有 -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不支持-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 的回答很棒,并提供了有关声明选择器如何工作的见解。

作为替代方案,我只是这样做:

self.businessDetailed.Phones.array[0];

然后我会告诉我未来的孙子们把它改成

self.businessDetailed.Phones[0];

当 iPhone 15 上架时。

与 Jeffry 的解决方案相比,工作量要少得多,但代价是边际成本略有增加。

于 2012-11-20T10:20:19.703 回答