Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Xcode6 beta7にしたらDelegateでハマった(Swift, Xcode6 beta7)

More than 5 years have passed since last update.

0.追記

@susieyy さんのご指摘により解決致しました。

Beta7にアップデートしてから、以下のコマンドは実施されましかたか?
Beta7以前の中間コンパイルがあるとうまく動作しないです

rm -rf ~/Library/Developer/Xcode/DerivedData

こちらを実行後、@objcを取り除いても、正常に動作しました。

TinderStyleApp.gif

1.はまったこと

beta7に変更してから、これまでのDelegateだとうまく通らならかったのでメモ。
ハマったプロジェクトは、この前投稿したこちらの記事(SwiftでTinderUIを実装してみた)です。

2.beta7に対応する前のコード

SwiftでTinderUIを実装してみた」にソースはほとんどおいているので(もしくはGithub)、下記コードは必要な部分のみを抜粋しています。

今回関連するファイルは2つで、DraggableView.swiftとDraggableViewBackground.swiftです。
それぞれのファイルのサマリーを先に書いておくと、

  • DraggableView.swiftでは、

    • 左右にスワイプされたときに起こるカードのアクションを定義している
    • DraggableViewBackgroun.swiftで使うためのDelegateを用意している
  • DraggableViewBackground.swiftでは、

    • 背景やボタン、TinderUIのカードなどを描画する
    • カードに表示するテキストの生成、読み込みなどを行う
    • 左右にスワイプされたときに、表示するテキストを変える
    • DraggableView.swiftで用意されたprotocolを継承している

という感じです。

それで、下記コードがbeta7に対応する前のコードです。

DraggableView.swift
// このファイルでは、TinderUIで言うところのカードのViewを生成し、ドラッグされた時の挙動を定義しています。

// Delegate先で使う予定のfunctionをprotocolで宣言しておきます。
protocol DraggableViewDelegate  {
    func cardSwipedLeft(card: UIView)
    func cardSwipedRight(card: UIView)
}

class DraggableView: UIView {

    var delegate: DraggableViewDelegate?
    .
    .
    .
    func rightAction() { // カードが右にドラッグされたときの処理
        var finishPoint: CGPoint = CGPointMake(500, 2*yFromCenter + self.originalPoint.y) // ドラッグされて、手が話された場所を変数に入れておく

        // カードが画面から消えるようにする
        UIView.animateWithDuration(0.3, animations: {
            self.center = finishPoint
            }, completion: { (value: Bool) in
                self.removeFromSuperview()
        })
        delegate?.cardSwipedRight(self) // ここで、delegate先のDraggableViewBackground.swiftに書かれている関数を呼び出す
        NSLog("YES")
    }

    func leftAction() { // カードが左にドラッグされたときの処理
        var finishPoint: CGPoint = CGPointMake(-500, 2*yFromCenter + self.originalPoint.y) // ドラッグされて、手が話された場所を変数に入れておく
        // カードが画面から消えるようにする
        UIView.animateWithDuration(0.3, animations: {
            self.center = finishPoint
            }, completion: { (value: Bool) in
                self.removeFromSuperview()
        })
        delegate?.cardSwipedLeft(self) // ここで、delegate先のDraggableViewBackground.swiftに書かれている関数を呼び出す
        NSLog("NO")
    }
    .
    .
    .
}

DraggableViewBackground.swift
// このファイルでは、背景やその他のボタンを描画したり、カードの読み込みなどを行っています。
class DraggableViewBackground: UIView, DraggableViewDelegate{ // 先ほど用意したDelegateのためのprotocolを継承
    .
    .
    .

    // カードのViewを描画
    func createDraggableViewWithDataAtIndex(index: Int) -> DraggableView {
        var draggableView: DraggableView = DraggableView(frame:CGRectMake(30, 100, CARD_WIDTH, CARD_HEIGHT))
        draggableView.information.text = "\(exampleCardLabels[index])"
        draggableView.backgroundColor = UIColor.whiteColor()
        draggableView.delegate = self
        println("delegate = \(draggableView.delegate?)")
        return draggableView
    }

    // 宣言していたProtocolにあるfunctionの中身を書いていきます。
    func cardSwipedLeft(card: UIView) {
        loadedCards.removeObjectAtIndex(0)
        if ( cardsLoadedIndex < allCards.count ) {
            loadedCards.addObject(allCards.objectAtIndex(cardsLoadedIndex))
            cardsLoadedIndex++
            self.insertSubview(loadedCards.objectAtIndex(MAX_BUFFER_SIZE-1) as UIView, belowSubview: loadedCards.objectAtIndex(MAX_BUFFER_SIZE-2) as UIView)
        }
        if (cardsLoadedIndex == 5) {
            self.result.text = "hoge"
        }
    }

    func cardSwipedRight(card: UIView) {
        loadedCards.removeObjectAtIndex(0)
        println("allCards = \(allCards.count)")
        println("cardsLoadedIndex is /(cardsLoadedIndex)")
        println(loadedCards.count)
        if ( cardsLoadedIndex < allCards.count ) {
            loadedCards.addObject(allCards.objectAtIndex(cardsLoadedIndex))
            cardsLoadedIndex++
            self.insertSubview(loadedCards.objectAtIndex(MAX_BUFFER_SIZE-1) as UIView, belowSubview: loadedCards.objectAtIndex(MAX_BUFFER_SIZE-2) as UIView)
        }
        if (cardsLoadedIndex == 5) {
            self.result.text = "huga"
        }
    }
    .
    .   
    .
}

beta7以前は、これで動いていたのですが、beta7にしたら、
draggableView.dalegate? = selfがnilになり、
delegate?.cardSwipedLeft(self)もそのままnilなので、
func cardSwipedLeftが呼び出されなくなってしまいました。

3.対策

色々と調べてたのですが、対策は、

DraggableView.swift
@objc protocol DraggableViewDelegate  {
    func cardSwipedLeft(card: UIView)
    func cardSwipedRight(card: UIView)
}

というように@objcをprotocolの前につければさきほどのnilの部分に全てきちんとしたOptional型での値が入りました。

4.よくわからないこと

  • @objcをつけることによってナゼ解消されるのか?
  • そもそも設計上、このDelegateがベストプラクティスなのか? ご存知の方、是非教えて下さいm(_ _)m
kiiita
Software Engineer / UI Desiner
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away