[Swift超入門]UI部品のOutletとActionをボタンによる動作で確認する
##使用UI部品
buttonとlabelのみ
##OutletとActionの違いについて
ドキュメントアウトラインからコードに接続する際に(controlキーを押しながらドラック&ドロップの作業)、写真のようなダイアログが出てくるかと思います。
この際、Connectionの部分でOutletまたはActionを選択することになります。この2つの違いを理解していない場合に起こるエラーを実体験とともに書き下して行こうと思います。
まずその前にOutletとActionの違いを文面的に書くと、
Outlet: UI部品をプロパティとして接続する。
Action:UI部品をメソッドとして接続する。
つまり、
Outletはその部品に関して他の関数やメソッドなどで行われる動作をコードに書く時に
Actionはその部品が行う処理の内容を書く時に
それぞれ接続、定義する必要があります。
例を挙げます。ボタンで考えると、そのボタンを押すことで行われる動作の定義はActionで、他のボタンを押したりすることで特定のボタンに影響を与える(ボタンを押すことを不可能にする、そのボタンを見えなくさせる)などと言った動作の定義にはOutletを用いることになるのです。
文章ではよくわからないかと思いますので、実際の処理を見ていきましょう。
##ボタンのOutletを接続しなかった場合
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var time: UILabel!
var selectedTime = 0
var count = 0
//1秒追加する
@IBAction func timer1(_ sender: Any) {
selectedTime += 1
time.text = "\(selectedTime)" //変数展開を行い、時間を表示する
}
//10秒追加する
@IBAction func timer10(_ sender: UIButton) {
selectedTime += 10
time.text = "\(selectedTime)"
}
//設定された時間によるタイマーをスタートさせる
@IBAction func timeStart(_ sender: UIButton) {
//スタートボタンを押すと時間追加ボタンを触れなくする
count += 1
if count % 2 == 1{
timer1.isEnabled = false
timer10.isEnabled = false
//ストップを押した時に時間追加ボタンを触れるようにする
}else{
timer1.isEnabled = true
timer10.isEnabled = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
このようなコードを書くことで、1秒ボタン、10秒ボタンを押した際に計測時間に数値が加算されています。(実際のタイマーの作成に関してはまだ未完成です。)
ですが、今のままでは、
//スタートボタンを押すと時間追加ボタンを触れなくする
count += 1
if count % 2 == 1{
timer1.isEnabled = false
timer10.isEnabled = false
//ストップを押した時に時間追加ボタンを触れるようにする
}else{
timer1.isEnabled = true
timer10.isEnabled = true
}
の部分に関して、次のエラーが生じます。(本来はここで、スタートストップボタンを押すことで、タイマーの動作中は他の二つのボタンが機能しなくなることを目的としています。)
これは、現状では1秒追加ボタン、10秒追加ボタンともに定義しているのはActionのみであり、Actionではそのボタンを押すことで行う動作を記入ことを可能にしているものだからです。
そこで、それぞれのボタンでActionだけではなく、Outletを接続し直すことで、これらのエラーを解除することができました。
##今回用いたコード全体
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var time: UILabel!
@IBOutlet weak var timer1: UIButton!
@IBOutlet weak var timer10: UIButton!
var selectedTime:Int = 0
var count = 0
//1秒追加する
@IBAction func timer1(_ sender: Any) {
selectedTime += 1
time.text = "\(selectedTime)"
}
//10秒追加する
@IBAction func timer10(_ sender: UIButton) {
selectedTime += 10
time.text = "\(selectedTime)"
}
//設定された時間によるタイマーをスタートさせる
@IBAction func timeStart(_ sender: UIButton) {
//スタートボタンを押すと時間追加ボタンを触れなくする
count += 1
if count % 2 == 1{
timer1.isEnabled = false
timer10.isEnabled = false
//ストップを押した時に時間追加ボタンを触れるようにする
}else{
timer1.isEnabled = true
timer10.isEnabled = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
##まとめ
ActionとOutletをうまく使い分けることで、今回のようにボタンとラベルの連動、ボタン同士の連動を可能にすることができました。