質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

3154閲覧

protocol extensionを実装するクラスがUIViewのサブクラスであることを明示したい

kxphotographer

総合スコア37

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/06/03 10:37

編集2017/06/04 10:40

こんにちは。Swiftを書いていて少し疑問に思ったことがあったので、質問をさせて頂きたく思います。よろしくお願いいたします。

結論から申し上げると、protocolextensionに実装したメソッドから、このprotocolを実装したViewクラスのインスタンスを参照出来るか、あるいはそもそもオブジェクト指向的にそういう考えは誤りであるのか、という質問です。

最近iOS App開発で、Viewをxibファイルに分ける方法に挑戦しています。

当初、xibファイルを読み込んでサブビューとして追加する処理はViewクラスの中に書いていました。

lang

1// CustomView.swift 2@IBDesignable 3class CustomView: UIView { 4 private static let xibName = "CustomView" 5 6 override init(frame: CGRect) { 7 super.init(frame: frame) 8 self._loadXib() 9 } 10 required init?(coder aDecoder: NSCoder) { 11 super.init(coder: aDecoder) 12 self._loadXib() 13 } 14 15 private func _loadXib() { 16 let bundle = Bundle(for: type(of: self)) 17 let nib = UINib(nibName: CustomView.xibName, bundle: bundle) 18 let subView = nib.instantiate(withOwner: self, options: nil).first as! UIView 19 self.addSubview(subView) 20 21 // subViewをselfいっぱいに広げるためのConstraintsの設定 22 subView.translatesAutoresizingMaskIntoConstraints = false 23 let bindings = ["view": subView] 24 self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", 25 options:NSLayoutFormatOptions(rawValue: 0), 26 metrics:nil, 27 views: bindings)) 28 self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", 29 options:NSLayoutFormatOptions(rawValue: 0), 30 metrics:nil, 31 views: bindings)) 32 } 33}

しかし、xibファイルが増えてくると、それを表示するViewのクラスごとに全く同じ処理を書くことになるため、_loadXib()の部分を分離しようと考えました。

lang

1// ViewFromXib.swift 2protocol ViewFromXib { 3 var xibName: String { get } 4} 5extension ViewFromXib { 6 func loadXib(_ superView: UIView) { 7 let bundle = Bundle(for: type(of: superView)) 8 let nib = UINib(nibName: self.xibName, bundle: bundle) 9 let subView = nib.instantiate(withOwner: superView, options: nil).first as! UIView 10 superView.addSubview(subView) 11 12 subView.translatesAutoresizingMaskIntoConstraints = false 13 let bindings = ["view": subView] 14 superView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", 15 options:NSLayoutFormatOptions(rawValue: 0), 16 metrics:nil, 17 views: bindings)) 18 superView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", 19 options:NSLayoutFormatOptions(rawValue: 0), 20 metrics:nil, 21 views: bindings)) 22 } 23}

lang

1// CustomView.swift 2@IBDesignable 3class CustomView: UIView, ViewFromXib { 4 var xibName = "CustomView" 5 6 override init(frame: CGRect) { 7 super.init(frame: frame) 8 self.loadXib(self) 9 } 10 required init?(coder aDecoder: NSCoder) { 11 super.init(coder: aDecoder) 12 self.loadXib(self) 13 } 14}

現在の私の知見の範囲内で正常に動くコードがこれなのですが、CustomViewのイニシャライザでxibファイルを読み込むメソッドを呼ぶときにselfを2回書かなければならないのが少々気になります。

これは、protocolextensionのあとに: UIViewをつけるとコンパイルエラーになるためです(当然ではありますが…)。

また、当初privateな変数とメソッドであった部分がprivateでなくなってしまっているのも気になります。

extensionの中でselfUIViewのサブクラスであることを明示して、そのメソッドを使用できるようにすることで、CustomViewから引数にselfを渡さなくて済むようにしたいのですが、それは可能なのでしょうか。あるいは、オブジェクト指向の考え方として誤った認識があるのでしょうか。

ご教授いただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

extension の制約に where が利用できます。

swift

1 2extension ViewFromXib where Self: UIView { 3 4 func loadXib() { 5 let bundle = Bundle(for: type(of: self)) 6 let nib = UINib(nibName: xibName, bundle: bundle) 7 let subView = nib.instantiate(withOwner: self, options: nil).first as! UIView 8 addSubview(subView) 9 10 ... 11 12}

制約としてwhere Self: UIViewを加えることでselfUIViewのプロパティや関数を利用できます。

投稿2017/06/04 13:00

MasakiHori

総合スコア3384

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kxphotographer

2017/06/10 12:24

まさにこれです!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問