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

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

ただいまの
回答率

89.99%

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,918
退会済みユーザー

退会済みユーザー

前提・実現したいこと

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

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

発生している問題・エラーメッセージ

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

該当のソースコード

// カスタムセルクラス
class CollectionViewCell2: CommonCollectionViewCell {

    @IBOutlet weak var mainImage: UIImageView!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    func setCell(imageName: String) {
        self.mainImage.image = UIImage(named: imageName)
    }

}
// ViewControllerクラス
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    var screenHeight: CGFloat!
    var screenWidth: CGFloat!

    let screenNames = ["main01", "main02", "main03", "main09", "main02", "main03", "main09", "main02"]

    override func viewDidLoad() {
        super.viewDidLoad()

        let statusBar = UIView(frame:CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 20.0))
        statusBar.backgroundColor = UIColor.white
        view.addSubview(statusBar)
        self.automaticallyAdjustsScrollViewInsets = false

        self.collectionView!.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "cell1")
        self.collectionView!.register(UINib(nibName: "CollectionViewCell2", bundle: nil), forCellWithReuseIdentifier: "cell2")
    }

    // 希望のセルサイズを返す
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let screenSize: CGRect = UIScreen.main.bounds
        screenWidth = screenSize.width
        screenHeight = screenSize.height
        let returnSize = CGSize(width: screenSize.width, height: screenSize.height)

        return returnSize
    }

    //セルのアイテムのマージンを設定
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsetsMake(20.0 , 0.0 , 0.0 , 0.0 )  //マージン(top , left , bottom , right)
    }

    //セル間のマージンを削除
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0.0
    }

    //データの個数を返す
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        return screenNames.count
    }

    //データを返す
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        var cell: CommonCollectionViewCell!
        if(indexPath.row == 0 || indexPath.row == 1) {
            let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath as IndexPath) as! CollectionViewCell
            cell1.setCell(imageName: screenNames[indexPath.row])
            cell = cell1
        }
        else {
            let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath as IndexPath) as! CollectionViewCell2
            cell2.setCell(imageName: screenNames[indexPath.row])
            cell = cell2
        }

        return cell
    }

    // ボタンタップで実行されるメソッド
    @IBAction func modalView(_ sender: UIButton) {
        print("tapButtonA")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

コンソールで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
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

 その1

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

let modalView = ModalViewController()
// 画面遷移.
self.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は削除して下さい)

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/16 09:46

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

    キャンセル

  • 2017/02/16 10:31

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

    キャンセル

  • 2017/02/16 10:50

    できました!
    printの内容がコンソールに出力されました。

    日をまたいでご指導いただきありがとうございます。
    とても助かりました。

    キャンセル

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

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる