23929


プログラミング初心者です。  
現在、ボタンをタップするごとに画像が切り替わる機能を考えています。  
画像は、「1.png」「2.png」「3.png」「4.png」の4つです。  
ボタンをタップすると「1.png」表示が消え「2.png」が表示します。  
ボタンを繰り返しタップすると、以下のようにループします。1.png→2.png→3.png→4.png→1.png→2.png→以降もループ  
また、1〜4.pngの表示される座標はそれぞれ異なります。  
各座標は以下の通りです。  
1.pngは(x:150, y:150)  
2.pngは(x:100, y:360)  
3.pngは(x:70, y:500)  
4.pngは(x:100, y:200)

以上の様な機能を実装するために考えたコードは、下記のとおりです。

ViewController.swift

[code]

    class ViewController: UIViewController {    
    var imageNum: Int = 0
    var stampView:UIImageView!
    let stampImage = UIImage(named: "1.png")!
    省略
    var imageArray:[UIImage] = []
    override func viewDidLoad() {
        super.viewDidLoad()
        for i in 1...4 {
            imageArray.append(UIImage(named: "\(i).png")!)
        }
    省略
        stampView = UIImageView(image: stampImage)
        stampView.center = CGPointMake(150,150)
        view.addSubview(stampView)
        }
    省略
    @IBAction func imageSelect(sender: UIButton) {
    imageNum++
        if imageNum >= imageArray.count {
            imageNum = 0
        }
    }
    
[/code]

ここまでは考えたのですが、ここから先がわかりません。  
アプリの起動直後は、1.pngが座標(x:150, y:150)に表示されている仕様を考えております。  
ボタンをタップしたときimageArray.count番目の画像を各座標に描画するには  
どういったコーディングをすべきでしょうか。  
また、私のコードの書き方がおかしな点などございましたら、ご教示願います。


CC BY-SA 3.0
2016-04-11T10:47:31.610
23916
2016-04-12T01:33:15.200
2016-04-11T23:55:38.950
14329
14329
question
swift swift2 uiimage uiimageview
ボタンをタップするごとに画像が切り替わる機能の実装方法


あなたの現在のコードをできるだけ生かすようにコードを追加してみるとこんな感じになります。  
ちなみにポイントは
**UIImageViewには書き換え可能なプロパティ`image`と`center`があるんだから、それを都度、書き換えれば良い**という考え方です。

[code]

    class ViewController: UIViewController {
        var imageNum: Int = 0
        var stampView:UIImageView!
    //    let stampImage = UIImage(named: "1.png")! //不要?
        //省略
        var imageArray:[UIImage] = []
        let imageCoords = [
            (150, 150),
            (100, 360),
            (70, 500),
            (100, 200),
        ].map{CGPointMake($0, $1)}
        override func viewDidLoad() {
            super.viewDidLoad()
            for i in 1...4 {
                imageArray.append(UIImage(named: "\(i).png")!)
            }
            //省略
            stampView = UIImageView(image: imageArray[0])
            stampView.center = imageCoords[0]
            view.addSubview(stampView)
        }
        //省略
        @IBAction func imageSelect(sender: UIButton) {
            imageNum = (imageNum + 1) % imageArray.count //*1
            //stampViewのimageとcenterを新しいimageNumに合わせて書き換える
            stampView.image = imageArray[imageNum]
            stampView.center = imageCoords[imageNum]
        }
    }
    
[/code]

(`imageArray`と`imageCoords`の各要素が1対1に対応していることがコードを少し見ても読み取れないので、もう少し書き換えたいところですが、「元のコードを生かす」を優先しました。)

(*1) Xcode7.3(Swift2.2)では、`imageNum++`に警告が出るので、ついでに書き換えてみました。  
0...(N-1)の値を順次繰り返す場合によく見られる書き方です。わかりやすさという点では???なのですが、サンプルコードなどを見ていてもちょくちょく出てくる書き方なので使わせていただきました。`imageArray.count`の値が0の時に実行するとアプリが落ちますのでご注意ください。

* * *

ご提示のように固定座標で良いのなら **最初から4つともViewの中に配置しておいて、その表示・非表示だけを切り替える**
と言う考え方をとると、コードの方は少しコンパクトにできます。

[code]

    class ViewController: UIViewController {
        var imageNum: Int = 0
        @IBOutlet var stampViews: [UIImageView] = []
        //省略
        override func viewDidLoad() {
            super.viewDidLoad()
            //省略
        }
        @IBAction func rararaSelect(sender: UIButton) {
            imageNum = (imageNum + 1) % stampViews.count
            for view in stampViews {
                view.hidden = (view.tag != imageNum+1)
            }
        }
    }
    
[/code]

あらかじめInterface Builder上で

  * UIImageViewを(1.png〜4.pngに紐付けて)4つView内に配置しておき、
  * それぞれのTagの値を1〜4にし、
  * 2.png〜4.pngのUIImageViewはhidden属性(これもInterface Builder内でチェックボックスで変更できます)をtrueにしておく

ことで「起動直後は、1.pngが座標(x:150, y:150)に表示されている」を実現する、と言う想定です。  
(Swiftでは、`@IBOutlet`のデータ型を配列にしておくと、複数のUI要素をひとつの`@IBOutlet`変数に結び付けられるようになります。)

* * *

どちらにしろ、UIImageは意外と(あるいは予想通りに)メモリを食うものなので、「4つ」よりはるかに数が増える可能性があるのでしたら、配列などに保持せずにその都度ロードし直すようにしたほうが良いかもしれません。(その場合、上記のうち後者の方法は使えませんが。)

実際のアプリでは、まだ明文化されていない制約などがあって、どちらの方法もうまくいかないかもしれませんが、ご参考程度にはしていただけると思います。お試しください。


CC BY-SA 3.0
2016-04-12T01:33:15.200
23929
2016-04-12T01:33:15.200
13972
23916
answer