简体   繁体   中英

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. 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. 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:

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.

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

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.

Will this pattern work, with modifications, or do I need to pass all UserState values to the framework individually?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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