xcode 除非您是 Apple,否则“扩展程序可能不包含存储的属性”?我错过了什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44674549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 10:04:01  来源:igfitidea点击:

"Extensions may not contain stored properties" unless your are Apple? What am I missing?

swiftxcodeswift4xcode9

提问by Bertan Gundogdu

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:

并得到两个错误:

  • 'weak' may only be applied to class and class-bound protocol types, not '<<error type>>'
  • Extensions may not contain stored properties
  • 'weak' 可能只适用于类和类绑定的协议类型,而不适用于 '<<error type>>'
  • 扩展可能不包含存储的属性

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 版本上提供实体属性,因此也欢迎对此提出其他建议。

采纳答案by Kai Engelhardt

This is currently not possible in Swift. As noted by Sulthan this is an Objective-C category for which you see the Swift version, which is generated by Xcode.

这在 Swift 中目前是不可能的。正如 Sulthan 所指出的,这是一个 Objective-C 类别,您可以看到它的 Swift 版本,它是由 Xcode 生成的。

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 博客上有一篇关于关联对象的精彩文章:关联对象 - NSHipster

回答by drewster

Swift 4 / iOS 11 / Xcode 9.2

斯威夫特 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_getAssociatedObjectand objc_setAssociatedObjectboth require an UnsafeRawPointeras a key. We use these functions to store a key/value pair which is associated with this unique instance.

在下面的代码中,obj_getAssociatedObjectobjc_setAssociatedObject都需要一个UnsafeRawPointer作为键。我们使用这些函数来存储与此唯一实例关联的键/值对。

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)
        }
    }
}

回答by AndreG

Funny I have the same feeling as the OP. Check this blog post by Apple itself: https://developer.apple.com/swift/blog/?id=37

有趣的是我和OP有同样的感觉。查看 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 代码中定义。

回答by mustafa elsebaie

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
    }
}