iOS跨界面或无关联界面传参的探究

  1. 使用闭包传参
    闭包传参的优点显而易见:低重复性、高可交互性。如下
@dynamicCallable
public struct ParamFactory: CustomStringConvertible {
    public var closure: (KeyValuePairs) -> Any
    
    public init(_ closure: @escaping (KeyValuePairs) -> Any) {
        self.closure = closure
    }
    
    @discardableResult
    public func dynamicallyCall(withKeywordArguments args: KeyValuePairs) -> Any {
        return closure(args)
    }
}

结合dynamicCallable特性,产生无固定参数的效果,实现双端交互。

  1. 原数据持有者持有闭包
    public typealias ParamDictionary = Dictionary
class ViewController: BaseViewController {
  var dic = ParamDictionary()
}

这样做的好处是最大限度的节省资源,在不需要的时候确保释放。

  • 为了方便逻辑处理且达到无阻碍使用的效果,采用属性包装器propertyWrapper
  • 为了能够跨区使用,采用单例模式。
    单例:
internal final class Transmitter {
    static let share = Transmitter()
    
    var queue = [WeakParamPublisher]()
    
    static func awaken(param: ParamPublisher) {
        update(param: param)
    }
    
    static func update(param: ParamPublisher) {
        share.update(param: param)
    }
    
    func update(param: ParamPublisher) {
        let weakPublisher = WeakParamPublisher(publisher: param)
        
        if let i = queue.firstIndex(of: weakPublisher) {
            queue.swapAt(i, queue.count - 1)
        } else {
            queue.append(weakPublisher)
        }
    }
    
    subscript(key: String) -> ParamFactory! {
        let transitives = queue.compactMap({ $0.publisher?.wrappedValue })
        return transitives.compactMap({ $0[key] }).last
    }
    
    subscript(keys: String...) -> [ParamFactory?] {
        return keys.map({ self[$0] })
    }
    
    subscript(keys: [String]) -> [ParamFactory?] {
        return keys.map({ self[$0] })
    }
}

使用属性包装器:

@propertyWrapper
@dynamicMemberLookup
public final class ParamPublisher: Hashable, CustomStringConvertible {
    public var wrappedValue: ParamDictionary {
        get { value }
        set {
            value = newValue
            Transmitter.awaken(param: self)
        }
    }
    private var value: ParamDictionary
    
    public var description: String { String(describing: value) }
    
    public init(wrappedValue: ParamDictionary = .init()) {
        self.value = wrappedValue
        Transmitter.update(param: self)
    }
    
    deinit {
        Transmitter.share.queue.removeAll { [weak self] in $0.publisher == self }
    }
    
    public subscript(dynamicMember member: String) -> ((KeyValuePairs) -> Any)! {
        get { value[closure: member] }
        set { value[closure: member] = newValue }
    }
    
    public func hash(into hasher: inout Hasher) {
        let opaque = Unmanaged.passUnretained(self).toOpaque()
        hasher.combine("\(opaque)")
    }
    
    public static func == (lhs: ParamPublisher, rhs: ParamPublisher) -> Bool {
        lhs.hashValue == rhs.hashValue
    }
}

继而实现参数发布和参数提取的隔离,实现跨区域传参。
代码地址

你可能感兴趣的:(iOS跨界面或无关联界面传参的探究)