- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
当使用 Swift 时,Cocoa 框架被声明为返回原生 Swift 类型,即使这些框架实际上返回的是 Objective-C 对象。同样,这些方法将 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
将在分配给 a
时桥接到 Swift 数组,然后桥接回 NSArray
作为参数传递时。至少从分析和反汇编来看是这样。
当我实际上不需要在 Swift 中使用数组时,有没有办法避免这些潜在的缓慢转换?当我刚从 Cocoa 收到它然后将它传递回 Cocoa 时?
起初,我认为为 a
添加类型信息会有所帮助:
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。 (即使在 Release 版本中也会发生这种情况。)我曾希望通过键入 c
作为 NSArray
就不需要桥接了。
我担心这会导致 inefficiencies具有非常大的数据结构,对常规数据结构进行许多不同的转换,以及惰性/代理的集合,因为它们不一定很大但计算起来可能很昂贵。能够receive就好了这样一个来自 Objective-C 代码的数组并将其传回,而无需实现数组的所有元素,如果它们从未从 Swift 访问的话。
这是一个很different performance模型比 Core Foundation/Foundation 的桥接是免费的。在很多情况下,代码假设它将是 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 代码将 NSMutableString
传递给 Swift 代码时,Swift String
以 副本 结束可变字符串。从某种意义上说,这很好,它不会在 Swift 背后发生意外变异。但是,如果您需要做的只是将一个字符串传递给 Swift 并简单地查看它,那么这个副本可能会增加意想不到的开销。
最佳答案
你试过做扩展吗?
extension NSMutableArray
{
func addObjectsFromNSArray(array:NSArray)
{
for item in array
{
self.addObject(item);
}
}
}
既然我有时间实际玩这个而不是在理论上讨论,我将修改我的答案
创建一个扩展,而是在 objective-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 秒
关于macos - 有没有一种方法可以在不桥接的情况下在 Swift 中使用 Foundation 对象(NSString、NSArray、NSDictionary)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32621880/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!