osx – 有没有办法使用基础对象(NSString,NSArray,NSDictionary)
使用Swift时,即使框架实际上返回了Objective-C对象,Cocoa框架也被声明为返回本地Swift类型。同样,这些方法将Swift类型作为参数,这在哪里是有意义的。
假设我想调用一个Cocoa方法(在Objective-C中)会给我一个NSArray,然后将它传递给一个采用NSArray的Cocoa方法。有了这样的代码: let a: [AnyObject] = [] // Imagine calling a method that returns a huge NSArray. let mutable = NSMutableArray() mutable.addObjectsFromArray(a) 它看起来像巨大的NSArray将被分配到一个Swift数组,当被分配给一个然后桥接回NSArray作为一个参数传递。至少这是从分析和查看拆卸看起来如何。 当我不需要在Swift中使用数组时,是否有办法避免这些潜在的慢转换?当我刚从Cocoa接收它然后再传回Cocoa? 起初,我认为这有助于添加类型信息: let a: NSArray = [] // Imagine calling a method that returns a huge NSArray. let mutable = NSMutableArray() mutable.addObjectsFromArray(a as [AnyObject]) 但是后来我必须将参数转换为Swift数组,否则编译器会抱怨。 此外,代码的拆卸如下: let c: NSArray = mutable.subarrayWithRange(NSMakeRange(0,50)) 显示调用__TF10Foundation22_convertNSArrayToArrayurFGSqCSo7NSArray_GSaq__和__TFer10FoundationSa19_bridgeToObjectiveCurfGSaq__FT_CSo7NSArray,似乎将返回值转换为Swift,然后返回到Objective-C。 (即使发布版本也会发生。)我曾经希望通过键入c作为NSArray,不需要桥接。 我担心这可能导致inefficiencies具有非常大的数据结构,许多不同的常规转换,以及懒惰/代理的集合,因为它们不一定很大,但计算成本可能很高。如果从Swift不能访问,那么可以从Objective-C代码中获得receive这样一个数组,并将其传递回来,而无需实现数组的所有元素。 这是一个非常different performance模型,而不是核心基金会/基金会,桥接是免费的。有很多情况下,代码会传递对象,假设它将是O(1),如果这些对象不可见地改变为O(n),则外部算法可能会变成二次或更差。在这种情况下,我不清楚应该做什么。如果没有办法关闭桥接,似乎所有触及这些对象的东西都需要在Objective-C中重写。 以下是基于上述示例的一些示例时序代码: NSArray *getArray() { static NSMutableArray *result; if (!result) { NSMutableArray *array = [NSMutableArray array]; for (NSUInteger i = 0; i < 1000000; i++) { [array addObjectsFromArray:@[@1,@2,@3,@"foo",@"bar",@"baz"]]; } result = array; } return result; } @interface ObjCTests : XCTestCase @end @implementation ObjCTests - (void)testObjC { // 0.27 seconds [self measureBlock:^{ NSArray *a = getArray(); NSMutableArray *m = [NSMutableArray array]; [m addObjectsFromArray:a]; }]; } @end class SwiftTests: XCTestCase { func testSwift() { // 0.33 seconds self.measureBlock() { let a: NSArray = getArray() as NSArray let m = NSMutableArray() m.addObjectsFromArray(a as [AnyObject]) } } func testSwiftPure() { // 0.83 seconds self.measureBlock() { let a = getArray() var m = [AnyObject]() m.appendContentsOf(a) } } } 在这个例子中,testSwift()比testObjC()慢约22%。只是为了好玩,我尝试用本地Swift数组进行数组追加,而这慢得多。 一个相关的问题是,当Objective-C代码通过Swift代码一个NSMutableString时,Swift String结束了一个可变字符串的副本。这在Swift的背后不会意外突变的意义上是好的。但是,如果你需要做的只是将一个字符串传递给Swift并简要地看一下,这个副本可能会增加意外的开销。
你试过扩展吗?
extension NSMutableArray { func addObjectsFromNSArray(array:NSArray) { for item in array { self.addObject(item); } } } 现在我有时间真的玩这个,而不是在理论上说话,我要修改我的答案 创建扩展名,而是在目标c文件中执行 @interface NSMutableArray(Extension) - (void)addObjectsFromNSArray:(NSObject*) array; @end @implementation NSMutableArray(Extension) - (void)addObjectsFromNSArray:(NSObject*) array { [self addObjectsFromArray:(NSArray*)array]; } @end 我发现代码的工作速度要快很多,这样做。 (从我的测试几乎两倍) testSwift 4.06秒 testSwiftPure 7.97秒 testSwiftExtension 2.30秒 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |