“扩展可能不包含存储的属性”,除非你是Apple?我错过了什么?
为什么苹果能做到这一点:“扩展可能不包含存储的属性”,除非你是Apple?我错过了什么?
import CoreGraphics
import GameplayKit
import simd
/**
@header
SceneKit framework category additions related to GameplayKit integration.
@copyright 2017 Apple, Inc. All rights reserve.
*/
extension SCNNode {
/**
* The GKEntity associated with the node via a GKSCNNodeComponent.
*
* @see GKEntity
*/
@available(OSX 10.13, *)
weak open var entity: GKEntity?
}
/**
* Adds conformance to GKSceneRootNodeType for usage as rootNode of GKScene
*/
extension SCNScene : GKSceneRootNodeType {
}
...我不能做到这一点:
extension SCNNode {
weak open var ntity: GKEntity?
}
,并得到了两个错误:
- '弱' 可能只适用到类和类绑定的协议类型,而不是'< <错误类型>>'
- 扩展可能不包含存储的原型rtyies
我想实际做的是在10.13之前提供一个OSX版本的实体属性,所以额外的建议也是值得欢迎的。
这在Swift中是不可能的。正如Sulthan所指出的,这是一个Objective-C类别,您可以看到由Xcode生成的Swift版本。现在,Objective-C不轻易支持在类别中添加属性(扩展在Objective-C中称为类别),但是您可以使用关联对象来获得所需内容。
马特·汤普森有关于他的NSHipster博客关联的对象一个伟大的文章:Associated Objects - NSHipster
滑稽我有同样的感受为OP。由苹果自己检查这个博客帖子:https://developer.apple.com/swift/blog/?id=37
你会发现他们显然打破他们唯一的规则,他们解释如何使用JSON与不是编译代码。
extension Restaurant {
private let urlComponents: URLComponents // base URL components of the web service
private let session: URLSession // shared session for interacting with the web service
static func restaurants(matching query: String, completion: ([Restaurant]) -> Void) {
var searchURLComponents = urlComponents
searchURLComponents.path = "/search"
searchURLComponents.queryItems = [URLQueryItem(name: "q", value: query)]
let searchURL = searchURLComponents.url!
session.dataTask(url: searchURL, completion: { (_, _, data, _)
var restaurants: [Restaurant] = []
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
for case let result in json["results"] {
if let restaurant = Restaurant(json: result) {
restaurants.append(restaurant)
}
}
}
completion(restaurants)
}).resume()
}
}
整篇文章是关于如何在Swift中处理JSON,所以“餐厅”没有在任何Objective-C代码中定义。
你可以试试这个代码,我使用的Xcode 8.3.3和3.1雨燕:
import SceneKit
import GameplayKit
extension SCNNode {
@available(OSX 10.13, *)
public var entity: GKEntity? {
return self.entity
}
}
斯威夫特4/iOS的11/9.2的Xcode
这里的答案是正确的技术上,但无论如何这都是一个解决方案。
在你的扩展中,用你想要的字段定义一个私有结构。使一切都静态,像这样:
private struct theAnswer {
static var name: String = ""
}
我知道,我知道,静态意味着它是一个类的变量/属性,而不是一个实例。但是我们实际上不会在这个结构中存储任何东西。
在下面的代码,obj_getAssociatedObject和objc_setAssociatedObject都需要一个UnsafeRawPointer作为密钥。我们使用这些函数来存储与此唯一实例关联的键/值对。
下面是一个字符串的完整的例子:
import Foundation
class ExtensionPropertyExample {
// whatever
}
extension ExtensionPropertyExample {
private struct theAnswer {
static var name: String = ""
}
var name: String {
get {
guard let theName = objc_getAssociatedObject(self, &theAnswer.name) as? String else {
return ""
}
return theName
}
set {
objc_setAssociatedObject(self, &theAnswer.name, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
}
他们真的不能。 'SCNNode'可能是一个Obj-C扩展,这就是Swift接口生成的方式。这真是无效的Swift。 – Sulthan
它可以是一个计算属性,它们看起来与生成的接口中存储的属性相同。 –