控制器

时间:2018-02-05 22:11:55

标签: ios swift

我在ios应用程序中构建了一个状态管理,类似于javascript中的redux。它工作起来很愉快,但我希望在框架中抽象和分离一些部分,以便重用,测试和共享。

要添加一些上下文,主要想法是使用class storegetState方法创建dispatch。用户定义的结构State在商店初始化时传递。

/* Store signature: class MyStore<State>: MyStoreProcotol */

let store = MyStore(state: ApplicationState())`

初始化存储后,我正在尝试将其注入符合ConnectionProtocol的任何类(例如,但不是必需的UIViewController)。 在下面的代码中,我将控制器和存储传递给函数injectStoreInView。我正试图通过此函数func injectStoreInView<State>(viewController: UIViewController, store: MyStore<State>)

在控制器中注入商店

我尝试了几种使用泛型的方法,但没有成功。我已阅读“类型擦除”并按照教程,但我不确定它是否有助于此案例以及如何应用它。我有一些麻烦来处理injectStoreInView的参数store的类型,并且以后不能在控制器controller.connection.store中分配它。

这是代码,其中删除了很多部分来说明问题。 (此代码不起作用。)

框架部分:

import UIKit

/* store */

protocol MyStoreProcotol {

  associatedtype State

  func getState() -> State

}

class MyStore<State>: MyStoreProcotol {

  var state: State

  init(state: State) {
    self.state = state
  }

  func getState() -> State {
    return self.state
  }

}

/* connection */

protocol ConnectionProtocol {

  associatedtype State

  var connection: Connection<State> { get }

}

class Connection<State> {
  var store: MyStore<State>? = nil
}

func injectStoreInView<State>(
  viewController: UIViewController,
  store: MyStore<State>
) {
  if let controller = viewController /* as ConnectionProtocol */ {
    controller.connection.store = store

    print("yeah !")
  }
}

在申请部分:

struct ApplicationState {
  var counter = 0
}

class StartViewConnector: UIViewController, ConnectionProtocol {

  let connection = Connection<ApplicationState>()

}

func appDelegatedidFinishLaunchingWithOptions() -> Bool {

  let store = MyStore(state: ApplicationState())

  let controller = StartViewConnector() // connector can be any class who conform to ConnectionProtocol, StartViewConnector for test but self.window?.rootViewController in iOS App

  injectStoreInView(viewController: controller, store: store)

  return true
}

appDelegatedidFinishLaunchingWithOptions()

1 个答案:

答案 0 :(得分:0)

根据@Brandon关于associatedTypesprotocolInjection的建议解决了这个问题。他在评论中提供的链接非常有用(How to create generic protocols in Swift?)。

此代码有效:

框架:

import UIKit

/* store */

protocol MyStoreProcotol {

  associatedtype State

  func getState() -> State

}

class MyStore<State>: MyStoreProcotol {

  var state: State

  init(state: State) {
    self.state = state
  }

  func getState() -> State {
    return self.state
  }

}

/* connection */

protocol Connectable {

  associatedtype Store

  var connection: Connection<Store> { get }

}

protocol ConnectionProtocol {

  associatedtype Store

  var store: Store? { get set }

}

class Connection<Store>: ConnectionProtocol {

  var store: Store? = nil

}

func injectStoreInView
<
  Store: MyStoreProcotol,
  Controller: Connectable
>
(
  viewController: Controller,
  store: Store
) where Controller.Store == Store
{
  viewController.connection.store = store
}

应用程序中的用法:

struct ApplicationState {
  var counter = 0
}

class StartViewConnector: UIViewController, Connectable {

  let connection = Connection<MyStore<ApplicationState>>()

}

func appDelegatedidFinishLaunchingWithOptions() -> Bool {

  let store = MyStore(state: ApplicationState())

  let connector = StartViewConnector()

  injectStoreInView(viewController: connector, store: store)

  // Now the store is properly injected, connector.connection.store = store

  return true
}

appDelegatedidFinishLaunchingWithOptions()