###前提・実現したいこと
ViewControllerで複数のカスタムViewControllerを表示させたい(presentViewみたいな感じで)
↓
不特定多数のViewControllerで表示させたいのでUIWindowを使用して、どこでも呼べるようにしよう
↓
UIWindowを使用して表示する上で、objc_getAssociatedObject/objc_setAssociatedObject周りで
###発生している問題・エラーメッセージ
使用するkey(UnsafeRawPointer)をメソッドで渡し、
objc_setAssociatedObjectを行うが、
objc_getAssociatedObject時にnilが返却されてしまう
###該当のソースコード
class DialogBase: UIViewController { func show(viewController: UIViewController, key: UnsafeRawPointer) { window = UIWindow(frame: UIScreen.main.bounds) window.alpha = 0 window.rootViewController = viewController window.windowLevel = UIWindowLevelNormal window.makeKeyAndVisible() objc_setAssociatedObject(UIApplication.shared, key, window, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) // UIWindowを上にアニメーション window.alpha = 1.0 window.top = UIScreen.main.bounds.height UIView.transition(with: window, duration: 0.3, options: [], animations: { self.window.top = 0 }) { (_) in } } func close(key: UnsafeRawPointer) { // ここでobjectがnilになってしまう guard let window = objc_getAssociatedObject(UIApplication.shared, key) as? UIWindow else { return } // UIWindowを下にアニメーション UIView.transition(with: window, duration: 0.3, options: [], animations: { window.top = UIScreen.main.bounds.height }) { (finished) in window.rootViewController?.view.removeFromSuperview() window.rootViewController = nil objc_setAssociatedObject(UIApplication.shared, key, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) // 一つ前のwindowを表示する let windows = UIApplication.shared.windows guard let nextWindow = windows.last else { return } nextWindow.makeKeyAndVisible() } } } ------------------------------------------------------------------ class CustomDialog: DialogBase { static let getInstance: CustomDialog = CustomDialog() func show() { let viewController = UIStoryboard(name: "CustomDialog", bundle: nil).instantiateInitialViewController() super.show(viewController: viewController!, key: Utility.bridge(obj: self)) } func close() { super.close(key: Utility.bridge(obj: self)) } } ------------------------------------------------------------------ class SampleViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() CustomDialog.getInstance.show() } } ------------------------------------------------------------------ class Utility { static func bridge<T: AnyObject>(obj: T) -> UnsafeMutableRawPointer { return Unmanaged.passRetained(obj).toOpaque() } static func bridge<T: AnyObject>(ptr: UnsafeRawPointer) -> T { return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue() } }
###試したこと
- Baseクラスにstatic var Keyを記載して、そのKeyをobjc_getAssociatedObjectに&Keyで読み込むと正常に動作することからメソッドを介してKeyを渡すと同一のKeyではなくなってしまう・・・?
- BaseクラスにviewControllerごとにif文を書いて、それぞれのobjc_getAssociatedObject/objc_setAssociatedObjectを記載したが同様にobjc_getAssociatedObjectでnilが返却されてしまった
###補足情報(言語/FW/ツール等のバージョンなど)
- Xcode8.2
- Swift3
UIViewにExtensionしてます extension UIView { var top : CGFloat{ get{ return self.frame.origin.y } set{ var frame = self.frame frame.origin.y = newValue self.frame = frame } } var bottom : CGFloat{ get{ return frame.origin.y + frame.size.height } set{ var frame = self.frame frame.origin.y = newValue - self.frame.size.height self.frame = frame } } var right : CGFloat{ get{ return self.frame.origin.x + self.frame.size.width } set{ var frame = self.frame frame.origin.x = newValue - self.frame.size.width self.frame = frame } } var left : CGFloat{ get{ return self.frame.origin.x } set{ var frame = self.frame frame.origin.x = newValue self.frame = frame } } }
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/01/19 08:25
2017/01/19 08:30