为什么以及如何someArray [5]在objective-c中工作?

时间:2012-11-15 03:44:33

标签: objective-c

我认为新的符号是这样的:

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

在BASH NSArray和NSOrderedSet中,有一个文本NS_AVAILABLE(10_8,6_0);

然而,它在NSArray上并没有中断,而是在NSOrderedSet上打破。为什么呢?

奖励:我如何使NSOrderedSet也适用于类别(需要检查它是否已经定义)

3 个答案:

答案 0 :(得分: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).

答案 1 :(得分: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()

答案 2 :(得分:0)

Jeffry的回答非常棒,并提供了如何声明选择器工作的见解。

另外,我只是这样做:

self.businessDetailed.Phones.array[0];

然后我会告诉我未来的孙子将其改为

self.businessDetailed.Phones[0];

当iPhone 15上架时。

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