简体   繁体   English

通过 iOS 应用程序和框架之间的 memory 引用共享数据

[英]Sharing data by memory reference between iOS app and framework

I'm developing an app which uses a singleton pattern to store single-session user state data.我正在开发一个应用程序,它使用 singleton 模式来存储单会话用户 state 数据。 It uses a framework which requires access to the same data, but currently the framework only finds nil when trying to access the class properties.它使用需要访问相同数据的框架,但目前该框架仅在尝试访问 class 属性时才找到nil Here's how I have it set up currently.这是我目前的设置方式。

In the framework:在框架中:

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

public var UserState : UserStateBase!

In the app:在应用程序中:

import Framework

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

var UserState = UserStateClass()

In the app's AppDelegate class:在应用程序的AppDelegate class 中:

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

Throughout both the framework and the app, I call UserState.username to access the properties.在整个框架和应用程序中,我调用UserState.username来访问属性。

I know passing by value instead of by reference would work, but it's much more tedious due to the number of properties and the need to update them whenever they change in the app.我知道通过值而不是通过引用传递会起作用,但是由于属性的数量以及每当它们在应用程序中发生更改时都需要更新它们,它会更加乏味。

I originally tried making UserStateBase a protocol, but that wouldn't work because it contains several properties which are defined as protocols for the implementing class to have implementations of, and the compiler complained it needed the implementations to be declared in the same way (eg locationManager in the protocol needs the implemention to declare it as var locationManager: LocationManagerDelegate = LocationManager() , meaning I'd have to cast to LocationManager every time I want to access a function not in the LocationManagerDelegate protocol).我最初尝试将UserStateBase协议,但这不起作用,因为它包含几个属性,这些属性被定义为实现 class 的协议,编译器抱怨它需要以相同的方式声明实现(例如协议中的locationManager需要实现将其声明为var locationManager: LocationManagerDelegate = LocationManager() ,这意味着每次我想访问不在LocationManagerDelegate协议中的 function 时,我都必须转换为LocationManager

This is why currentUser and currentPass are declared twice - my intention is for the subclass to override the base class, which I assume is what's happening since the compiler isn't complaining about ambiguous references.这就是为什么currentUsercurrentPass被声明两次的原因——我的意图是让子类覆盖基础 class,我认为这是正在发生的事情,因为编译器没有抱怨不明确的引用。

Will this pattern work, with modifications, or do I need to pass all UserState values to the framework individually?这种模式是否可以通过修改工作,还是我需要将所有 UserState 值单独传递给框架?

Because everything in Swift is implicitly internal , the properties in UserStateBase aren't actually exposed to the app (though the class itself is), so UserStateClass can't override them (and the redefinitions don't cause a compiler error), hence when the framework is given a reference to the app's UserState instance, all of the properties it knows about (the ones in UserStateBase ) are still uninitialised.因为 Swift 中的所有内容都是隐式internal ,所以UserStateBase中的属性实际上并没有暴露给应用程序(尽管 class 本身就是),所以UserStateClass不能覆盖它们(并且重新定义不会导致编译器错误),因此当框架获得了对应用程序UserState实例的引用,它知道的所有属性(在UserStateBase中的属性)仍未初始化。

Realising this, I decided to bite the bullet and revert to using a protocol.意识到这一点,我决定硬着头皮恢复使用协议。 This is the resulting pattern I used.这是我使用的结果模式。

In the framework:在框架中:

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

public var UserState : UserStateDelegate!

In the app:在应用程序中:

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

And everything works as expected.一切都按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM