【问题标题】:Cannot access property wrapper across modules in Swift无法在 Swift 中跨模块访问属性包装器
【发布时间】:2019-12-02 07:03:59
【问题描述】:

在我的Common 模块(框架项目)中有用户默认值的属性包装器

@propertyWrapper
public class MyUserDefaultWrapper<T> {
    let key: String
    let defaultValue: T

    public init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    public var wrappedValue: T {
       get {
           let suite = UserDefaults(suiteName: "MySuite")
           return suite?.object(forKey: key) as? T ?? defaultValue
       }
       set {
           let suite = UserDefaults(suiteName: "MySuite")
           suite?.set(newValue, forKey: key)
       }
    }
}

在我的App 模块(主项目)中,我声明客户端使用MyUserDefaultWrapper

import Common

public class MyUserDefaultsCommon: NSObject {
    @objc static let shared = MyUserDefaultsCommon()
    @MyUserDefaultWrapper("yearOfBirth", defaultValue: 1980)
    static var yearOfBirth: Int
}

并使用like,

MyUserDefaultsCommon.shared.yearOfBirth = 2001

它产生构建错误。

未知属性“MyUserDefaultWrapper”

如何解决这个问题?

【问题讨论】:

  • 你确实导入了项目,对吧?
  • 是的,我在桥接头和文件顶部都用#import关键字导入了

标签: ios swift module build-error property-wrapper


【解决方案1】:

我使用了您的代码,需要进行一些修改才能使其正常工作。我的最终解决方案如下:

@propertyWrapper
public class MyUserDefaultWrapper<T> {
    let key: String
    let defaultValue: T

    public init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    public var wrappedValue: T {
        get {
            let suit = UserDefaults.standard
            return suit.object(forKey: key) as? T ?? defaultValue
        }
        set {
            let suit = UserDefaults.standard
            suit.set(newValue, forKey: key)
        }
    }
}

大部分public 关键字丢失。但是我对你如何实现你的框架感到困惑,这样你就不会得到正确的错误。

我是怎么做到的:

首先创建一个新项目。修改ViewController为:

import UIKit
import PropertyWrapperFramework

class ViewController: UIViewController {

    struct MyUserDefaultsCommon{
        @MyUserDefaultWrapper("yearOfBirth", defaultValue: 1980)
        static var yearOfBirth: Int
    }

}

第二创建一个新的工作区。最好是项目文件所在的位置并且具有相同的名称(不同的扩展名)。关闭所有项目。打开工作区。将您的项目文件拖到您的工作区项目导航器中。

第三创建一个新项目并选择框架。选择文件夹时,还要选择底部的“添加到:”以将其插入您的工作区。

第四将您的产品包装器拖到“框架、库和嵌入式内容”下的项目中(参见屏幕截图)。您只需抓住“产品”下的“.framework”文件并将其一直向下拖动。确保您已选择主项目 -> 目标,如屏幕截图所示。

第五向您的框架添加代码。创建一个新文件并为其添加逻辑:

@propertyWrapper
public class MyUserDefaultWrapper<T> {
    let key: String
    let defaultValue: T

    public init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    public var wrappedValue: T {
        get {
            let suit = UserDefaults.standard
            return suit.object(forKey: key) as? T ?? defaultValue
        }
        set {
            let suit = UserDefaults.standard
            suit.set(newValue, forKey: key)
        }
    }
}

最后构建并运行您的应用。

【讨论】:

  • 没有解决我的问题。我已经正确链接了框架,因为其他公共 api 可以毫无问题地访问。
  • @SazzadHissainKhan 不幸的是,如果没有额外的信息,这可能无法解决。我使用了您发布的所有代码并设法在我的应用程序中运行它。也许您的框架需要明确重建?
  • 我很抱歉我的旧帖子中的错误代码 sn-p。请尝试在我的原始帖子中更新新代码 sn-p。你能不能试着让这个现在可以构建?
  • @SazzadHissainKhan 你没有收到任何错误吗?对suit 的2 次调用报告错误,因为suit 不是可选的。在 2 种情况下应该是 suit. 而不是 suit?.
  • 我已经更新了代码。我试图在没有我的生产代码的情况下添加最小的示例。感谢您指出。请看我现在使用let suite = UserDefaults(suiteName: "MySuite")
猜你喜欢
  • 2020-01-24
  • 1970-01-01
  • 2020-03-14
  • 2013-11-23
  • 2011-01-28
  • 1970-01-01
  • 2022-01-20
  • 2021-02-05
  • 1970-01-01
相关资源
最近更新 更多