[英]"Extensions may not contain stored properties" unless your are Apple? What am I missing?
How come Apple can do this:为什么苹果可以做到这一点:
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 {
}
... and I cannot do this: ...我不能这样做:
extension SCNNode {
weak open var ntity: GKEntity?
}
and get two errors:并得到两个错误:
What I would like to actually do is to provide an entity property on OSX versions before 10.13, so additional suggestions for that are also welcome.我实际上想做的是在 10.13 之前的 OSX 版本上提供一个实体属性,因此也欢迎对此提出其他建议。
Swift 4 / iOS 11 / Xcode 9.2 Swift 4 / iOS 11 / Xcode 9.2
The answers here are technically right, but here's a solution anyway. 这里的答案在技术上是正确的,但无论如何这里都是一个解决方案。
In your extension, define a private struct with the fields you're going to want. 在您的扩展中,使用您想要的字段定义私有结构。 Make everything static, like this:
让一切都是静态的,像这样:
private struct theAnswer {
static var name: String = ""
}
I know, I know, static means it's a class-wide variable/property, not an instance one. 我知道,我知道,静态意味着它是一个类范围的变量/属性,而不是实例。 But we are not actually going to store anything in this struct.
但我们实际上并没有在这个结构中存储任何东西。
In the code below, obj_getAssociatedObject and objc_setAssociatedObject both require an UnsafeRawPointer as a key. 在下面的代码中, obj_getAssociatedObject和objc_setAssociatedObject都需要UnsafeRawPointer作为键。 We use these functions to store a key/value pair which is associated with this unique instance.
我们使用这些函数来存储与此唯一实例关联的键/值对。
Here's the complete example with a String: 这是带字符串的完整示例:
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)
}
}
}
This is currently not possible in Swift. 这在Swift中目前是不可能的。 As noted by Sulthan this is an Objective-C category for which you see the Swift version, which is generated by Xcode.
正如Sulthan所指出的,这是一个Objective-C类别,您可以看到由Xcode生成的Swift版本。
Now, Objective-C does not easily support adding properties in categories (extensions are called categories in Objective-C), but you can use associated objects to get what you want. 现在,Objective-C不容易支持在类别中添加属性(扩展在Objective-C中称为类别),但您可以使用关联的对象来获得所需的内容。
Mattt Thompson has a great article about associated objects on his NSHipster blog: Associated Objects - NSHipster Mattt Thompson在他的NSHipster博客上发表了一篇关于相关对象的精彩文章: Associated Objects - NSHipster
Funny I have the same feeling as the OP. 有趣我和OP有同样的感觉。 Check this blog post by Apple itself: https://developer.apple.com/swift/blog/?id=37
查看Apple本身的博文: https : //developer.apple.com/swift/blog/?id = 37
You will notice they clearly break their only rules, and they explain how to use JSON with a code that isn't compilable. 您会注意到它们明确地违反了它们的唯一规则,并且它们解释了如何将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()
}
}
That entire article is about how to handle JSON in Swift, so "Restaurants" is not defined in any Objective-C code. 整篇文章是关于如何在Swift中处理JSON的,因此在任何Objective-C代码中都没有定义“Restaurants”。
You may try this code, I'm using Xcode 8.3.3 and Swift 3.1: 您可以尝试使用此代码,我正在使用Xcode 8.3.3和Swift 3.1:
import SceneKit
import GameplayKit
extension SCNNode {
@available(OSX 10.13, *)
public var entity: GKEntity? {
return self.entity
}
}
in Swift 5, Xcode 13 I was able to add the property directly to the extension using static (no need to create an inner struct etc..)在 Swift 5, Xcode 13 我可以使用 static 将属性直接添加到扩展中(无需创建内部结构等。)
For example:例如:
extension String {
static var onboarded = "onboarded"
static var locationAllowed = "locationAllowed"
}
Usage:用法:
@AppStorage(.locationAllowed) var locationAllowed = false
@AppStorage(.onboarded) var a = false
@AppStorage
need a "String" as a parameter, so I just used .onboarded
from the Extension @AppStorage
需要一个“字符串”作为参数,所以我只是使用扩展中的.onboarded
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.