我认为新的符号是这样的:
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也适用于类别(需要检查它是否已经定义)
答案 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的解决方案少得多的工作,其代价是边际成本略有增加。