Last active
February 22, 2016 14:00
-
-
Save rizumita/d8d48eca74137fed1c1e to your computer and use it in GitHub Desktop.
SegueOperatorはSegueに取り付けられる交換手クラスです。BundlesWireframeはVIPERアーキテクチャの遷移を司るクラスです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* SwinjectでSegueにInjectするSegueOperatorTypeを指定する。 | |
* nameにSegueのIdentifierを指定する。 | |
*/ | |
container.register(SegueOperatorType.self, name: "BundlesSegue") { _ in | |
return SegueOperator { | |
_, _ in | |
print("test") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
/* | |
* VIPERアーキテクチャのWireframe。遷移を担当する。 | |
* Wireframeを利用せずにViewController内部で全ての処理を行っても良いのですが、遷移元のコントローラが遷移先の情報を持つようにしたくなかったのでWireframeを利用しています。 | |
*/ | |
class BundlesWireframe: BundlesWireframeType { | |
var viewController: BundlesViewController? | |
/* | |
* 遷移するときにViewControllerから呼ぶ | |
*/ | |
func showBundle(withID id: String?) { | |
let segueOperator = SegueOperator { (s, d: BundleViewController) in | |
d.id = id | |
} # 引数のクロージャでdestinationViewControllerを設定する | |
viewController?.performSegueWithIdentifier(R.segue.bundlesViewController.bundleSegue.identifier, | |
sender: segueOperator) # senderにSegueOperatorを渡す | |
} | |
} | |
protocol BundlesWireframeType: WireframeType { | |
var viewController: BundlesViewController? { get set } | |
func showBundle(withID id: String?) | |
} | |
protocol WireframeType: class { | |
/* | |
* ViewControllerのprepareForSegueから呼ぶ | |
*/ | |
func prepare(forSegue segue: UIStoryboardSegue, sender: AnyObject?) | |
} | |
extension WireframeType { | |
func prepare(forSegue segue: UIStoryboardSegue, sender: AnyObject?) { | |
switch sender { | |
case let segueOperator as SegueOperatorType: | |
segue.segueOperator = segueOperator | |
default: () | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
protocol SegueOperatorType: class { | |
func operate(source source: UIViewController, destination: UIViewController) | |
} | |
/* | |
* UIStoryboardSegueに取り付ける交換手クラス | |
*/ | |
class SegueOperator<Source: UIViewController, Destination: UIViewController>: SegueOperatorType { | |
typealias Operation = (Source, Destination) -> () | |
let operation: Operation | |
init(operation: Operation) { | |
self.operation = operation | |
} | |
func operate(source source: UIViewController, destination: UIViewController) { | |
operation(source as! Source, destination as! Destination) | |
} | |
} | |
# | |
# UIStoryboardSegueにSegueOperatorTypeを取り付けられるようにする | |
# UIStoryboardSegueが作成された時にDIコンテナからSegueOperatorTypeをInjectする | |
# | |
import ObjectiveC | |
var AssociatedObjectHandle: UInt8 = 0 | |
extension UIStoryboardSegue { | |
var segueOperator: SegueOperatorType? { | |
get { | |
return objc_getAssociatedObject(self, &AssociatedObjectHandle) as? SegueOperatorType | |
} | |
set { | |
objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) | |
} | |
} | |
dynamic func performSwizzled() { | |
segueOperator?.operate(source: sourceViewController, destination: destinationViewController) | |
performSwizzled() | |
} | |
dynamic convenience init(swizzled_identifier: String?, source: UIViewController, destination: UIViewController) { | |
self.init(swizzled_identifier: swizzled_identifier, source: source, destination: destination) | |
segueOperator = assembler.resolver.resolve(SegueOperatorType.self, name: identifier) | |
} | |
override public class func initialize() { | |
super.initialize() | |
struct Static { | |
static var token: dispatch_once_t = 0; | |
} | |
// make sure this isn't a subclass | |
dispatch_once(&Static.token) { | |
swizzlePerform() | |
swizzleInit() | |
} | |
} | |
private static func swizzlePerform() { | |
let originalSelector = Selector("perform"); | |
let swizzledSelector = Selector("performSwizzled"); | |
swizzle(self, originalSelector: originalSelector, swizzledSelector: swizzledSelector) | |
} | |
private static func swizzleInit() { | |
let originalSelector = Selector("initWithIdentifier:source:destination:"); | |
let swizzledSelector = Selector("initWithSwizzled_identifier:source:destination:"); | |
swizzle(self, originalSelector: originalSelector, swizzledSelector: swizzledSelector) | |
} | |
} | |
private func swizzle(cls: AnyClass!, originalSelector: Selector, swizzledSelector: Selector) { | |
let originalMethod = class_getInstanceMethod(cls, originalSelector); | |
let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); | |
let didAddMethod = class_addMethod(cls, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); | |
if didAddMethod { | |
class_replaceMethod(cls, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); | |
} else { | |
method_exchangeImplementations(originalMethod, swizzledMethod); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment