

swiftでsegueの遷移時の処理で分からないので分かる方教えて下さい。

segueをIBを使うのではなくidentifierを設定してプログラムで使います。  
2つの画面ViewControllerとPuzzleViewControllerがありperformSegueWithIdentifierを使って遷移させます。遷移方法は画像を作成してそちらからonClickButtonのアクションで移動します。TouchUpInsideする画像によって次の画面でのアクションが異なるため画像を設置した際にtag(cTag)を設定します。そこで質問ですがprepareFoSegueメソッド内にsender?.tagを設定したのですがなぜかnilが返ってきます。onClickButtonメソッド内でsender?.tagを設定するとちゃんとしたタグの数値が返ってくるのですがprepareFoSegueメソッドが発生した時点で参照範囲外になってしまうからでしょうか？またどういった考え方をすればいいでしょうか？

[code]

    func cImageMake(cImageName:String,cTag:Int,cWideth:CGFloat,cHeight:CGFloat,cText:String){
        //アイコン画像の生成
        let cImage:UIImage = UIImage(named: cImageName) as UIImage!
        let cImageButton = UIButton()
        cImageButton.tag = cTag
        cImageButton.frame = CGRectMake(0, 0, 75, 75)
        cImageButton.layer.position = CGPoint(x: self.view.frame.width/4 * cWideth , y: self.view.frame.height/4 * cHeight)
        cImageButton.setImage(cImage, forState: .Normal)
        cImageButton.addTarget(self, action: "onClickCButton:", forControlEvents: .TouchUpInside)
        self.view.addSubview(cImageButton)
        //アイコン文字の生成
        var cTextField:UITextField = UITextField(frame: CGRectMake(0, 0, 75, 75))
        cTextField.text = cText
        cTextField.textAlignment = NSTextAlignment.Center
        cTextField.enabled = false
        cTextField.layer.position = CGPoint(x: self.view.frame.width/4 * cWideth, y: self.view.frame.height/4 * cHeight )
        self.view.addSubview(cTextField)
    }
    
    //ボタンイベントPuzzleViewControllerを表示
    func onClickCButton(sender: AnyObject){
        self.performSegueWithIdentifier("goPuzzleSegue", sender: sender.tag)
    }
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "goPuzzleSegue"{
            let puzzleViewController:PuzzleViewController = segue.destinationViewController as! PuzzleViewController
            puzzleViewController.castleId = sender?.tag
    
[/code]


CC BY-SA 3.0
2015-07-23T00:13:19.407
12587
2015-07-23T01:45:17.350
2015-07-23T00:22:27.337
7362
10206
question
swift xcode6
segueをプログラム遷移する際のデータ移行

[code]

    //ボタンイベントPuzzleViewControllerを表示
    // func onClickCButton(sender: AnyObject){
    func onClickCButton(sender: UIButton) { // senderの型をUIButtonに「決めつけ」る。
        self.performSegueWithIdentifier("goPuzzleSegue", sender: sender) // sender.tag → sender
    }
    
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "goPuzzleSegue"{
            // Optional Bindingを採用。
            if let theButton = sender as? UIButton {
                let puzzleViewController:PuzzleViewController = segue.destinationViewController as! PuzzleViewController
                puzzleViewController.castleId = theButton.tag
            }
    
[/code]

メソッドの引数で、`sender`の型を`AnyObject`としていることに注目してください。`AnyObject`に`tag`というプロパティはありませんので、`sender.tag`は意味をなしません。  
`tag`というプロパティを持っているのは、`UIView`とそのサブクラス（`UIButton`も含まれる）なので、`sender`を`UIView`ないし`UIButton`にダウンキャストする必要があります。  
`func onClickCButton(sender: UIButton)`は、直接引数の型を変更しています。  
`if let theButton = sender as? UIButton`は、Optional
Bindingを使ってダウンキャストしています。ダウンキャストに失敗すると、`theButton`には、`nil`が入ります。

※メソッド・関数の引数に限らず、`Any`や`AnyObject`という型が出てきたら、なんらかのダウンキャストが必要なんだろうなと、予測しておくといいでしょう。たとえば、配列`Array`や辞書`Dictionary`の要素を、`AnyObject`型としておくことはよくあります。要素を取り出したときに、ダウンキャストしないと、そのままでは使えないことがよくあります。


CC BY-SA 3.0
2015-07-23T01:45:17.350
12592
2015-07-23T01:45:17.350
7362
12587
answer