Skip to content

Instantly share code, notes, and snippets.

@gauravkeshre
Last active April 3, 2018 15:11
Show Gist options
  • Save gauravkeshre/b3844b22e6c9567d4c12390552bc24bc to your computer and use it in GitHub Desktop.
Save gauravkeshre/b3844b22e6c9567d4c12390552bc24bc to your computer and use it in GitHub Desktop.
Proposal: Data Handover Mechanism among UIViewControllers

Proposal for Data handover accross ViewControllers

Passing dependencies across controllers

What

This mechanism gives us a framework (and discipline) to pass data from one conroller to another.

How does it work

Protocols

Every controller conforms to DataReciever protocol which means that it will have a property model that can be set from the caller scope. Although, the controllers will not have to define a property again and again ‽, they still have to implement the prepare(with:) methhod from the protocol

‽ - The property is injected into the View controllers at the runtime using Associated Objects.

Sample

Please refer SampleVC.swift

Analytics

xAssociatedObjects.swift

Ignore the x in the file name this was a conspiracy to keep readme.md on the top of the gist

//
// HelloVC.swift
// Research
//
// Created by Gaurav Keshre on 23/11/17.
// Copyright © 2017 Gaurav. All rights reserved.
//
import UIKit
class HelloVC: UIViewController, DataReceiver {
typealias ModelType = String
@IBOutlet private weak var lblName : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK:- DataReceiver
//--------------------------
func prepare(with model: String?) {
lblName.text = model
}
}
//
// UIViewController+DaHo.swift
// Research
//
// Created by Gaurav Keshre on 29/11/17.
// Copyright © 2017 Gaurav. All rights reserved.
//
import Foundation
import UIKit
fileprivate var ModelTypeAssociationKey: UInt = 0
public protocol DataReceiver: class {
associatedtype ModelType
var model: ModelType? { get set }
func prepare(with model: ModelType?)
}
extension DataReceiver where Self: UIViewController {
var model: ModelType? {
get {
return ObjCAssociation.get(associatedObject: self, key: &ModelTypeAssociationKey)
}
set(newModel) {
guard let model = newModel else{
ObjCAssociation.remove(associatedObject: self, key: &ModelTypeAssociationKey)
return
}
ObjCAssociation.set(associatedObject: self, value: model, key: &ModelTypeAssociationKey)
}
}
}
//
// AssociatedObjects.swift
// Research
//
// Created by Gaurav Keshre on 29/11/17.
// Copyright © 2017 Gaurav. All rights reserved.
//
import Foundation
private var AssociagedObjKey: UInt = 0
class ObjCAssociation {
private final class AssociatedObjWrapper<T> {
let value: T
init(_ val: T) {
self.value = val
}
}
static func set<T>(associatedObject object: Any, value: T, key: UnsafeRawPointer,
policy: objc_AssociationPolicy = .OBJC_ASSOCIATION_RETAIN_NONATOMIC) {
let finalValue: Any
if type(of: value) is AnyClass {
finalValue = value
}else {
/// Only classes can be saved as associated objects
finalValue = AssociatedObjWrapper(value)
}
objc_setAssociatedObject(object, key, finalValue, policy)
}
static func get<T>(associatedObject object: Any, key: UnsafeRawPointer) -> T? {
let fetchedValue = objc_getAssociatedObject(object, key)
if let v = fetchedValue as? T {
return v
}else if let v = fetchedValue as? AssociatedObjWrapper<T> {
return v.value
}
return nil
}
static func remove(associatedObject object: Any, key: UnsafeRawPointer){
objc_setAssociatedObject(object, key, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment