我有一个BaseViewController
,它被我的应用程序中的所有其他视图控制器子类化。
我有一些状态变量,它们必须在所有视图控制器中保持一致,所以我计划编写代码,以便在BaseViewController
中来回传递这些状态变量一次。为此,我提供了一个用于前向传递的辅助函数pushStatefulViewControllerWithIdentifier()
,并使用StatePassBackDelegate
用于后向传递。
import UIKit
class BaseViewController: UIViewController, StatePassBackDelegate {
class State {
var connected = false
var loggedIn = false
}
var state = State()
weak var delegate: StatePassBackDelegate? = nil
// MARK: Lifecycle
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if self.isMovingFromParentViewController() == true {
delegate?.passBackState(state)
}
}
// MARK: StatePassBackDelegate functions
func passBackState(state: AnyObject) {
self.state = state as! State
}
// MARK: Helpers
final func pushStatefulViewControllerWithIdentifier(identifier: String) {
let vc = storyboard?.instantiateViewControllerWithIdentifier(identifier) as! BaseViewController
vc.state = state
vc.delegate = self
navigationController!.pushViewController(vc, animated: true)
}
}
protocol StatePassBackDelegate: class {
func passBackState(state: AnyObject)
}
- 我这里有强参考周期吗
- 我应该在这里使用singleton模式吗
-
我在您的代码中看不到保留循环。如果你担心某个对象没有在预期的时间内销毁,你可以记录它的释放以检查:
deinit { print("deinit of (self)") }
-
同意,您需要引入一些模型级别的实体来进行状态关怀,而不是将其放在控制器层。如果您不打算用单元测试来覆盖相关的逻辑,那么Singleton是可以的。
已编辑
您可以将共享对象存储在应用程序委派中。
不确定我是否完全理解您的应用程序对象模型。我假设状态应该在所有应用程序中共享,所以最好将一些SystemStateMachine注入所有感兴趣的组件中。希望能有所帮助:
@UIApplicationMain
class MyAppDelegate: UIResponder, UIApplicationDelegate {
var controllersFactory: IViewControllersFactory! = nil
func applicationDidFinishLaunching(application: UIApplication) {
let storyboard = UIStoryboard(name:NSBundle.mainBundle().infoDictionary!["UIMainStoryboardFile"] as! String , bundle: NSBundle.mainBundle())
controllersFactory = ViewControllersFactory(storyboard: storyboard, stateMachine: SystemStateMachine())
}
}
struct SystemState : OptionSetType {
let rawValue: Int
static let None = SystemState(rawValue: 0)
static let Connected = SystemState(rawValue: 1 << 0)
static let LoggedIn = SystemState(rawValue: 1 << 1)
}
protocol ISystemStateMachine {
var currentState: SystemState { get set }
}
class SystemStateMachine: ISystemStateMachine {
var currentState: SystemState = .None
}
protocol IViewControllersFactory {
func instantiateViewController(identifier: String) -> BaseViewController?
}
class ViewControllersFactory: IViewControllersFactory {
let _storyboard: UIStoryboard
let _stateMachine: ISystemStateMachine
init(storyboard: UIStoryboard, stateMachine: ISystemStateMachine) {
_storyboard = storyboard
_stateMachine = stateMachine
}
func instantiateViewController(identifier: String) -> BaseViewController? {
if let vc = _storyboard.instantiateViewControllerWithIdentifier(identifier) as? BaseViewController {
vc.stateMachine = _stateMachine
return vc
}
return nil
}
}
class BaseViewController: UIViewController {
var stateMachine: ISystemStateMachine!
// MARK: Lifecycle
func somethingWorthHappen() {
//switch state
stateMachine.currentState.insert(.Connected)
}
func somethingWorth2Happen() {
//switch state
stateMachine.currentState.insert(.LoggedIn)
guard let appDelegate = UIApplication.sharedApplication().delegate as? MyAppDelegate else {
//log an error
return
}
if let vc = appDelegate.controllersFactory.instantiateViewController("myViewController") {
navigationController!.pushViewController(vc, animated: true)
}
}
}