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

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

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

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

1回答

4287閲覧

UICollectionView xibに配置したボタンをタップして画像をモーダル表示させたい

退会済みユーザー

退会済みユーザー

総合スコア0

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

0クリップ

投稿2017/02/13 02:14

編集2017/02/15 08:44

###前提・実現したいこと
xcode8 swift3 iPad
UICollectionViewを使用して、画像のスライドショーみたいなものを作っています。
各セルのサイズはフルスクリーンです。
各セルのレイアウトは違っていて、indexPathごとにカスタムセルでxibを使っています。
セルにボタンを配置してボタンをタップしたら、画像をモーダル表示したいです。

storyboardにViewControllerをUICollecitonViewを配置したものとは別に、新たに配置しています。
xibのボタンから新たに配置したViewControllerに遷移させたいです。

###発生している問題・エラーメッセージ
xibにボタンを配置しましたが、そこからのモーダル表示が上手くいきません。
UICollectionViewCellクラスからの遷移方法がわからず、色々と試していますが、上手くいっておりません。
selfのところでエラーとなっていますが、UICollectionViewクラスではないからと思いましたが、解決方法がわかっておりません。

###該当のソースコード

swift

1 2// カスタムセルクラス 3class CollectionViewCell2: CommonCollectionViewCell { 4 5 @IBOutlet weak var mainImage: UIImageView! 6 7 override func awakeFromNib() { 8 super.awakeFromNib() 9 // Initialization code 10 } 11 12 func setCell(imageName: String) { 13 self.mainImage.image = UIImage(named: imageName) 14 } 15 16}

swift

1// ViewControllerクラス 2class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { 3 4 var screenHeight: CGFloat! 5 var screenWidth: CGFloat! 6 7 let screenNames = ["main01", "main02", "main03", "main09", "main02", "main03", "main09", "main02"] 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 12 let statusBar = UIView(frame:CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 20.0)) 13 statusBar.backgroundColor = UIColor.white 14 view.addSubview(statusBar) 15 self.automaticallyAdjustsScrollViewInsets = false 16 17 self.collectionView!.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "cell1") 18 self.collectionView!.register(UINib(nibName: "CollectionViewCell2", bundle: nil), forCellWithReuseIdentifier: "cell2") 19 } 20 21 // 希望のセルサイズを返す 22 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 23 24 let screenSize: CGRect = UIScreen.main.bounds 25 screenWidth = screenSize.width 26 screenHeight = screenSize.height 27 let returnSize = CGSize(width: screenSize.width, height: screenSize.height) 28 29 return returnSize 30 } 31 32 //セルのアイテムのマージンを設定 33 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 34 return UIEdgeInsetsMake(20.0 , 0.0 , 0.0 , 0.0 ) //マージン(top , left , bottom , right) 35 } 36 37 //セル間のマージンを削除 38 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 39 return 0.0 40 } 41 42 //データの個数を返す 43 override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 44 { 45 return screenNames.count 46 } 47 48 //データを返す 49 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 50 { 51 var cell: CommonCollectionViewCell! 52 if(indexPath.row == 0 || indexPath.row == 1) { 53 let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath as IndexPath) as! CollectionViewCell 54 cell1.setCell(imageName: screenNames[indexPath.row]) 55 cell = cell1 56 } 57 else { 58 let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath as IndexPath) as! CollectionViewCell2 59 cell2.setCell(imageName: screenNames[indexPath.row]) 60 cell = cell2 61 } 62 63 return cell 64 } 65 66 // ボタンタップで実行されるメソッド 67 @IBAction func modalView(_ sender: UIButton) { 68 print("tapButtonA") 69 } 70 71 override func didReceiveMemoryWarning() { 72 super.didReceiveMemoryWarning() 73 // Dispose of any resources that can be recreated. 74 } 75} 76 77

###コンソールでbtコマンドをたたいたときのログ

* thread #1: tid = 0x9380f, 0x0000000196863bdc libobjc.A.dylib`objc_msgSend + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x110000) frame #0: 0x0000000196863bdc libobjc.A.dylib`objc_msgSend + 28 frame #1: 0x000000018988d398 UIKit`-[UIApplication sendAction:to:from:forEvent:] + 96 frame #2: 0x0000000189876474 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 612 frame #3: 0x000000018988cd34 UIKit`-[UIControl touchesEnded:withEvent:] + 592 frame #4: 0x000000018988c9c0 UIKit`-[UIWindow _sendTouchesForEvent:] + 700 frame #5: 0x0000000189885efc UIKit`-[UIWindow sendEvent:] + 684 frame #6: 0x0000000189859120 UIKit`-[UIApplication sendEvent:] + 264 frame #7: 0x0000000189afa2b8 UIKit`_UIApplicationHandleEventFromQueueEvent + 15424 frame #8: 0x0000000189857634 UIKit`_UIApplicationHandleEventQueue + 1716 frame #9: 0x0000000184d98240 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 frame #10: 0x0000000184d974e4 CoreFoundation`__CFRunLoopDoSources0 + 264 frame #11: 0x0000000184d95594 CoreFoundation`__CFRunLoopRun + 712 frame #12: 0x0000000184cc12d4 CoreFoundation`CFRunLoopRunSpecific + 396 frame #13: 0x000000018e5df6fc GraphicsServices`GSEventRunModal + 168 frame #14: 0x00000001898bef40 UIKit`UIApplicationMain + 1488 * frame #15: 0x00000001000419f0 advicebook`main + 140 at AppDelegate.swift:12 frame #16: 0x0000000196efaa08 libdyld.dylib`start + 4

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

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

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

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

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

guest

回答1

0

ベストアンサー

その1

なぜUINavigationControllerを挟んでいるのでしょうか?

swift

1let modalView = ModalViewController() 2// 画面遷移. 3self.present(modalView, animated: true, completion: nil)

これでダメですか?

その2

ViewControllerからpresentして下さい。
cellじゃダメです。

その3

タップ後の処理を、CollectionViewCell1の中ではなく、ViewControllerに書いて下さい。
セル内のボタンだからといって、セルの中にタップ処理を書く必要はありません。

その4

xibのFile's OwnerのCustom ClassにViewControllerを設定した後、xibのボタンからActionを作成して下さい。

その5

ボタンイベントをコードで追加します。
setCellを呼んでいる前後(どっちでもいいです)に、下記のコードを追加して下さい。
(xib上で繋いだActionや、その4で設定したCustom Classは削除して下さい)

swift

1cell1.button.addTarget(self, action: #selector(ViewController.modalView(_:)), for: .touchUpInside)

投稿2017/02/13 06:14

編集2017/02/16 01:31
fuzzball

総合スコア16731

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

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

退会済みユーザー

退会済みユーザー

2017/02/13 07:46

ご回答ありがとうございます。 UINavigationControllerは、色々と試行錯誤しているときにそのまま消し忘れていました。 ご回答にある部分をViewControllerに記述し、 xibに設置したボタンが押されたら、カスタムセルクラスからViewControllerのpresentが書かれたメソッドを呼ぶようにしました。 しかし、ボタンをタップするとエラーになってしまいます。 ViewControllerクラスのメソッドに書いたprint文は実行されています エラー内容 ``` Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter' ``` 初回表示時にレイアウトの設定をしていますが、その設定が反映されていなくてエラーになっているのでしょうか?
fuzzball

2017/02/13 07:51

ModalViewControllerの親クラスは何でしょうか?
退会済みユーザー

退会済みユーザー

2017/02/13 08:04

UIViewControllerクラスです。
fuzzball

2017/02/13 08:08

「カスタムセルクラスからViewControllerのpresentが書かれたメソッドを呼ぶようにしました」のコードを書いて下さい。
退会済みユーザー

退会済みユーザー

2017/02/13 09:38 編集

※質問に追記のため削除
fuzzball

2017/02/13 08:44

ここに書かないで下さい。見にくいです。
退会済みユーザー

退会済みユーザー

2017/02/13 09:01

失礼しました。 質問に追記しました。
fuzzball

2017/02/13 09:34

こっちのコードは削除して下さい。見にくいです。 で、セルでViewControllerのインスタンスを新たに生成していますが、それではダメです。すでにあるViewControllerのインスタンスに対してmodalView()を呼ばないといけません。
退会済みユーザー

退会済みユーザー

2017/02/13 10:01

> ViewControllerのインスタンスに対してmodalView()を呼ばないといけません。 これを実現するにはどのようにすれば良いでしょうか? 調べてみましたが、よくわかりませんでした。
fuzzball

2017/02/14 00:41

その3を書きました。 元のActionを削除するのを忘れずに。
退会済みユーザー

退会済みユーザー

2017/02/14 07:22 編集

元のActionを削除しました。 しかし、xibのボタンをcontrol+クリックで線をViewControllerに持っていっても接続できないのですが、何か設定が必要なのでしょうか?
fuzzball

2017/02/14 07:44 編集

xibはほとんど使ったことがないので分かりません。
fuzzball

2017/02/14 07:47

xibの、 ・ViewのCustom Class ・File's OwnerのCustom Class を教えて下さい。
退会済みユーザー

退会済みユーザー

2017/02/14 08:09

> ・ViewのCustom Class  CollectionViewCell(カスタムセルクラス)  上記、xibに配置したcollectionviewcellのCustom Classですが、これがViewという認識でよろしいでしょうか? >・File's OwnerのCustom Class  何も書いていません。(NSObjectと薄く書かれています。)
fuzzball

2017/02/14 08:12 編集

ちょっとxibってみました。その4を書いたので見て下さい。
退会済みユーザー

退会済みユーザー

2017/02/14 09:14

ありがとうございます。 何度もすみません。 > xibのFile's OwnerのCustom ClassにViewControllerを設定した後、xibのボタンからActionを作成して下さい。 こちらの作業のあと、アクションのメソッドにprint("test")と書いてビルドしました。 しかし、ボタンを押してもコンソールにtestと表示されずに、 Thread1: EXC_BAD_ACCESS(code=.......... となって、実機が固まってしまいます。
fuzzball

2017/02/14 09:16

どこで落ちているのでしょうか?
fuzzball

2017/02/14 09:18

あと、質問内のコードは常に最新にして下さい。
退会済みユーザー

退会済みユーザー

2017/02/14 09:38

失礼しました。 コードはビューコントローラーとカスタムセルクラスを最新の状態にし、クラスの内容を全て書きました。 落ちる場所はThread1のmainで、AppDelegateクラスにThread1: EXC_BAD_ACCESS(code=.......... となっております。
fuzzball

2017/02/14 10:13

とりあえずですが、register(セルの登録)はviewDidLoadで行って下さい。最初に一度やっておけばいいです。 続きは明日になります。
退会済みユーザー

退会済みユーザー

2017/02/14 12:51

> とりあえずですが、register(セルの登録)はviewDidLoadで行って下さい。最初に一度やっておけばいいです。 質問のコードを更新しました。 ありがとうございます。 よろしくお願いします。
fuzzball

2017/02/15 00:28

こちらでは質問のコード(ほぼ)そのままで正常に動作しました。 下記の回答を参考にして、どこで落ちているか特定して下さい。 https://teratail.com/questions/30571
退会済みユーザー

退会済みユーザー

2017/02/15 07:12

すみません。 何度も呼んでみましたが、あまり理解できませんでした。
fuzzball

2017/02/15 07:36

・Breakpoint Navigatorを表示(Command+7) ・左下の+を押して「Add Exception Breakpoint...」を選択 ・設定の吹き出しが出ますが何もせずに閉じる(ESCを押す、など) これで設定できますので、この状態で実行してみて下さい。
退会済みユーザー

退会済みユーザー

2017/02/15 08:31

ご丁寧に有難うございます。 > 左下の+を押して「Add Exception Breakpoint...」を選択 この部分で「Add Exception Breakpoint...」という項目がなく、「Exception Breakpoint...」があったのでこちらを選択して実行してみました。 しかし、エラー内容も全く同じで何も変わりませんでした。
fuzzball

2017/02/15 08:37

落ちた後、Console(下部の黒いところ)で、btと打ち込んでEnterを押して表示されるログを教えて下さい。
退会済みユーザー

退会済みユーザー

2017/02/15 08:44

質問に追記いたしました。
fuzzball

2017/02/15 08:55 編集

接続の切れているAction/Event/Outletの残骸が無いかどうか調べてみて下さい。 Connections inspectorを表示させておくと良いです。(Option+Command+6) 昨日、「元のActionを削除しました」と書いていましたが、コードを削除するだけじゃダメですよ。
退会済みユーザー

退会済みユーザー

2017/02/15 09:23

調べてみましたが、特に接続が切れていたりはしてないと思います。
fuzzball

2017/02/15 09:27 編集

二種類のセルの両方ともタップすると落ちるのでしょうか?
退会済みユーザー

退会済みユーザー

2017/02/15 10:10 編集

落ちる方のセルにしかボタンを配置しておりません。 試しにもう一種類のセルにも配置しましたが、やはり同じように落ちました。。
fuzzball

2017/02/15 10:10

ボタンだけではなく、セルなどの他のUIにも残骸が無いか調べてみて下さい。
退会済みユーザー

退会済みユーザー

2017/02/15 13:48

全て見ましたが、残骸などは見つけられませんでした。 ずっと実機でテストしていたんですが、シミュレーターでは動くことが確認できました。 しっかりとprintの内容がコンソールに出ていました。 実機のみで固まってしまうようです。。。
fuzzball

2017/02/15 13:56

ちなみにiPadの何でしょうか? 実機と同じ機種のシミュレータではどうなりますか? OSのバージョンも教えて下さい。 あと、実機の方で、一度アプリを削除してから試してみて下さい。
退会済みユーザー

退会済みユーザー

2017/02/16 00:27

実機のOSとバージョン iPad Air 2 iOS8.4 実機と同じシミュレータでも、動きます。 アプリを一度削除してビルドし直しましたが、実機のみで落ちてしまいます。
fuzzball

2017/02/16 00:30

一度クリーンしてみて下さい。 Shift+Command+Option+K です。 そろそろネタ切れです。
fuzzball

2017/02/16 00:46

8.4だと落ちるのを確認しました。機種は関係ないです。 ちょっと調べてみます。
fuzzball

2017/02/16 01:31

その5を書きました。 原因が分かりそうにないので、ボタンイベントをコードで追加するようにしました。
退会済みユーザー

退会済みユーザー

2017/02/16 01:50

できました! printの内容がコンソールに出力されました。 日をまたいでご指導いただきありがとうございます。 とても助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問