LoginSignup
30
30

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-09-06

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
30
30
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
30