CKSwift/ViewModelState.swift (25 lines of code) (raw):

/* * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ import Foundation import ComponentKit @propertyWrapper public class ViewModelState<Value> : ScopeHandleAssignable { private var handle: CKComponentScopeHandle? public init(wrappedValue valueProvider: @escaping @autoclosure () -> Value) { self.wrappedValue = valueProvider() } /// Should only be called during component build or on the main thread thereafter public var wrappedValue: Value { didSet { // Permit changing the view model state's value before it is linked. // which would be the case if the view model state is re-assigned before // its owning view has rendered (and thus read the values). handle.flatMap(CKSwiftUpdateViewModelState) } } public var projectedValue: Binding<Value> { Binding(get: { self.wrappedValue }, set: { self.wrappedValue = $0 }) } // MARK: ScopeHandleAssignable func assign(handle: CKComponentScopeHandle) { // Storing the handle would result in a retain cycle (@ViewModelState -> @ViewModel -> Component -> // State which it turn is owned by CKComponentScopeHandle). Keeping a weak reference would also not work since // after a few generations the the scope handle wouldn't be owned by anyone else. @ViewModelState only gets // assigned the first time around as it's only created once. As soon as D21332674 lands we can refactor this. self.handle = handle.newStateless() } } extension ViewModelState : Equatable where Value : Equatable { static public func ==(lhs: ViewModelState, rhs: ViewModelState) -> Bool { lhs.wrappedValue == rhs.wrappedValue } }