Обмен данными по ссылке на память между iOS-приложением и фреймворком - PullRequest
1 голос
/ 24 октября 2019

Я занимаюсь разработкой приложения, в котором используется одноэлементный шаблон для хранения данных состояния пользователя за один сеанс. Он использует каркас, который требует доступа к тем же данным, но в настоящее время каркас находит 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:

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

Во всем фреймворке и приложении я вызываю UserState.username для доступа к свойствам.

Я знаю, что передача по значению, а не по ссылке будет работать, но это гораздо более утомительно из-за количества свойств и необходимости обновлять их всякий раз, когда они изменяются в приложении.

Я изначальнопопытался сделать UserStateBase протоколом, но это не сработало бы, потому что он содержит несколько свойств, которые определены как протоколы для реализующего класса, чтобы иметь реализации, и компилятор жаловался, что ему нужно, чтобы реализации были объявлены таким же образом (например,locationManager в протоколе требуется, чтобы реализация объявила его как var locationManager : LocationManagerDelegate = LocationManager(), что означает, что мне придется приводить к LocationManager каждый раз, когда я хочу получить доступ к функции, не входящей в протокол LocationManagerDelegate).

Вот почему currentUser и currentPass объявляются дважды - мое намерение состоит в том, чтобы подкласс переопределил базовый класс, что, как я полагаю, и происходит, поскольку компилятор не жалуется на неоднозначные ссылки.

Будет ли работать этот шаблон с изменениями или мне нужно передать все значения UserState в среду по отдельности?

1 Ответ

0 голосов
/ 24 октября 2019

Поскольку все в Swift неявно internal, свойства в UserStateBase фактически не доступны приложению (хотя сам класс есть), поэтому 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()

И все работает, как ожидалось.

...