问题描述
在回答另一个问题的过程中,我在 Playground 中遇到了一个奇怪的错误.我有以下代码来测试对象是 Array
、Dictionary
还是 Set
:
In the course of answering another question, I came across a weird bug in Playground. I have the following code to test if an object is an Array
, Dictionary
or a Set
:
import Foundation
func isCollectionType(value : AnyObject) -> Bool {
let object = value as! NSObject
return object.isKindOfClass(NSArray)
|| object.isKindOfClass(NSDictionary)
|| object.isKindOfClass(NSSet)
}
var arrayOfInt = [1, 2, 3]
var dictionary = ["name": "john", "age": "30"]
var anInt = 42
var aString = "Hello world"
println(isCollectionType(arrayOfInt)) // true
println(isCollectionType(dictionary)) // true
println(isCollectionType(anInt)) // false
println(isCollectionType(aString)) // false
当我将代码放入 Swift 项目或从命令行运行它时,代码按预期工作.但是 Playground 不会编译并在向下转换到 NSObject
时给我以下错误:
The code worked as expected when I put it into a Swift project or running it from the command line. However Playground wouldn't compile and give me the following error on the downcast to NSObject
:
Playground execution failed: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x7fb1d0f77fe8).
* thread #1: tid = 0x298023, 0x00007fb1d0f77fe8, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fb1d0f77fe8)
* frame #0: 0x00007fb1d0f77fe8
frame #1: 0x000000010ba46e12 libswiftCore.dylib`Swift._EmptyArrayStorage._withVerbatimBridgedUnsafeBuffer (Swift._EmptyArrayStorage)<A>((Swift.UnsafeBufferPointer<Swift.AnyObject>) -> A) -> Swift.Optional<A> + 50
在所有三种情况下,构建平台都是 OS X.有谁知道如何让 Playground 一起玩?
The build platform was OS X in all three cases. Does anyone know how to get Playground to play along?
Xcode 6.3.2.斯威夫特 1.2.OS X 10.10.3 优胜美地
Xcode 6.3.2. Swift 1.2. OS X 10.10.3 Yosemite
推荐答案
并不是那个 bug 的真正原因(看起来确实很奇怪)但是...您将需要使用可选链接,因为值可以是 AnyObject:
Not really the cause of that bug (it does look weird) but...You will need to use optional chaining since value can be AnyObject:
import Foundation
func isCollectionType(value : AnyObject) -> Bool {
if let object = value as? NSObject {
return object.isKindOfClass(NSArray)
|| object.isKindOfClass(NSDictionary)
|| object.isKindOfClass(NSSet)
}
return false
}
var arrayOfInt = [1, 2, 3]
var dictionary = ["name": "john", "age": "30"]
var anInt = 42
var aString = "Hello world"
isCollectionType(arrayOfInt)
isCollectionType(dictionary)
isCollectionType(anInt)
isCollectionType(aString)
另外值得注意的是,NSArray 和 Array 是不同的东西:
Also worth noting, NSArray and Array are different things:
NSArray 是一个不可变的类:
NSArray is an immutable class:
@interface NSArray : NSObject
虽然数组是一个结构体:
whilst Array is a struct:
struct Array: MutableCollectionType, Sliceable, _DestructorSafeContainer
考虑到这一点,isCollectionType(arrayOfInt) 返回 true 可能会令人惊讶 - 但发生了转换.
With this in mind it might be surprising that isCollectionType(arrayOfInt) returns true - but there is a conversion happening.
这篇关于游乐场和项目之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!