在 iOS 应用程序和框架之间通过内存引用共享数据

Sharing data by memory reference between iOS app and framework

我正在开发一个应用程序,它使用单例模式来存储单会话用户状态数据。它使用需要访问相同数据的框架,但目前该框架在尝试访问 class 属性时仅找到 nil。这是我目前的设置方式。

框架内:

open class UserStateBase {
    var locationManager : LocationManagerDelegate!
    var currentUser : String?
    var currentPass : String?
    // ... a dozen other properties
}

public var UserState : UserStateBase!

在应用程序中:

import Framework

class UserStateClass : UserStateBase {
    var locationManager = LocationManager()
    var currentUser : String?
    var currentPass : String?
    // ... many more properties
}

var UserState = UserStateClass()

在应用的 AppDelegate class:

func application(...) {
    // Override point for customisation after application launch
    Framework.UserState = App_Module.UserState
}

在整个框架和应用程序中,我调用 UserState.username 来访问属性。

我知道按值传递而不是按引用传递是可行的,但由于属性的数量以及每当它们在应用程序中发生更改时需要更新它们,这更加乏味。

我最初尝试使 UserStateBase 成为一个协议,但这行不通,因为它包含几个属性,这些属性被定义为用于实现 class 的协议,编译器抱怨它需要以相同的方式声明实现(例如,协议中的 locationManager 需要实现将其声明为 var locationManager : LocationManagerDelegate = LocationManager(),这意味着每次我都必须强制转换为 LocationManager想要访问不在 LocationManagerDelegate 协议中的函数)。

这就是 currentUsercurrentPass 被声明两次的原因 - 我的意图是让子 class 覆盖基数 class,我认为这就是正在发生的事情因为编译器不会抱怨不明确的引用。

此模式在修改后是否有效,或者我是否需要将所有 UserState 值分别传递给框架?

因为 Swift 中的所有内容都是隐式 internalUserStateBase 中的属性实际上并未公开给应用程序(尽管 class 本身公开),所以UserStateClass 无法覆盖它们(并且重新定义不会导致编译器错误),因此当框架被赋予对应用程序的 UserState 实例的引用时,它知道的所有属性( UserStateBase) 中的那些仍未初始化。

意识到这一点,我决定硬着头皮恢复使用协议。这是我使用的结果模式。

框架内:

public protocol UserStateDelegate {
    var locationManagerDelegate : LocationManagerDelegate { get }
    var currentUser : String? { get }
    var currentPass : String? { get }
    // ... a dozen other properties
}

public var UserState : UserStateDelegate!

在应用程序中:

import Framework

class UserStateClass : UserStateDelegate {
    var locationManagerDelegate : LocationManagerDelegate = LocationManager()
    // This computed property saves me from having to perform the cast everywhere it's used
    var locationManager : LocationManager { return locationManagerDelegate as! LocationManager }
    var currentUser : String?
    var currentPass : String?
    // ... many more properties
}

var UserState = UserStateClass()

一切都按预期进行。