加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

osx – 有没有办法使用基础对象(NSString,NSArray,NSDictionary)

发布时间:2020-12-14 05:52:56 所属栏目:百科 来源:网络整理
导读:使用Swift时,即使框架实际上返回了Objective-C对象,Cocoa框架也被声明为返回本地Swift类型。同样,这些方法将Swift类型作为参数,这在哪里是有意义的。 假设我想调用一个Cocoa方法(在Objective-C中)会给我一个NSArray,然后将它传递给一个采用NSArray的Coc
使用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秒

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读