Swift
時計

リフレッシュのためにSwiftで時計を作った

More than 3 years have passed since last update.


はじめに

最近ずっとC++とかUnityのC#とか触り続けていて疲れたので、久しぶりに違う言語で遊びたくなったのでSwiftで時計を作ってみました。

ただ、Objective-Cはバリバリ使ってたのですが、Swiftはほぼ使ったことがなかったので少し調べつつでしたが...。(まぁ、最近Objective-C使ってないのでこちらも今はできないに等しいですが(^^;))

ちなみにStoryboardを利用していますが、その部分については解説はしないのですみませんが自身で勉強して下さいm(_ _)m


完成品

時計.png

『年、月、日、曜日、時間、分、秒』を表示するだけのシンプルなものです。


プログラム


ViewController.swift


import Cocoa

class ViewController: NSViewController {

@IBOutlet weak var yearLabel: NSTextField!
@IBOutlet weak var monthLabel: NSTextField!
@IBOutlet weak var daysLabel: NSTextField!
@IBOutlet weak var dayOfTheWeekLabel: NSTextField!
@IBOutlet weak var hourLabel: NSTextField!
@IBOutlet weak var minutesLabel: NSTextField!
@IBOutlet weak var secondLabel: NSTextField!

override func viewDidLoad() {
super.viewDidLoad()
nowTime()
var timer = NSTimer.scheduledTimerWithTimeInterval(1/60, target: self, selector: "update", userInfo: nil, repeats: true)
}

override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}

//NSTimerを利用して60分の1秒ごとに呼びたす。
func update() {
nowTime()
}

func nowTime(){
let myDate: NSDate = NSDate()//現在時刻を取得
let myCalendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!//カレンダーを取得
let myComponetns = myCalendar.components(NSCalendarUnit.CalendarUnitYear |
NSCalendarUnit.CalendarUnitMonth |
NSCalendarUnit.CalendarUnitDay |
NSCalendarUnit.CalendarUnitHour |
NSCalendarUnit.CalendarUnitMinute |
NSCalendarUnit.CalendarUnitSecond |
NSCalendarUnit.CalendarUnitWeekday,
fromDate: myDate)//取得するコンポーネントを決める
let weekdayStrings: Array = ["nil","日","月","火","水","木","金","土","日"]//曜日の配列
/*Storyboardに表示*/
yearLabel.stringValue = "\(myComponetns.year)"
monthLabel.stringValue = addZero(String(myComponetns.month), timeNuber: myComponetns.month)
daysLabel.stringValue = addZero(String(myComponetns.day), timeNuber: myComponetns.day)
dayOfTheWeekLabel.stringValue = "\(weekdayStrings[myComponetns.weekday])"
hourLabel.stringValue = addZero(String(myComponetns.hour), timeNuber: myComponetns.hour)
minutesLabel.stringValue = addZero(String(myComponetns.minute), timeNuber: myComponetns.minute)
secondLabel.stringValue = addZero(String(myComponetns.second), timeNuber: myComponetns.second)

}

//1桁のものには0をつける。例えば1秒なら01秒に。
func addZero(timeString:String,timeNuber:Int)->String{
if(countElements(timeString)==1){
return ("0\(timeNuber)")
}else{
return ("\(timeNuber)")
}
}

}



プログラムの説明

ほぼコメントアウトで説明をしているので不要かもしれませんが、ちょっとだけ。


Storyboardへの出力の準備

    @IBOutlet weak var yearLabel: NSTextField!

@IBOutlet weak var monthLabel: NSTextField!
@IBOutlet weak var daysLabel: NSTextField!
@IBOutlet weak var dayOfTheWeekLabel: NSTextField!
@IBOutlet weak var hourLabel: NSTextField!
@IBOutlet weak var minutesLabel: NSTextField!
@IBOutlet weak var secondLabel: NSTextField!

これについては『Xcode6/Swiftで、ボタンを押すとラベルが変わるだけのアプリを作る』でLabelの設定の仕方などが紹介されていたのでこちらを参考にしてもらえば大丈夫かも?

ただ、ここで少し自分がハマった点がありました。

それはNSTextField

iOS側ではUILabelでできていた(はず?)ので困惑してしまいました。

まぁ、この問題を解決してくれたのはこちらの記事↓

Swiftで簡単なアプリ実装してみた

ちゃんと紹介はされていなかったのですが、コードを見たら

変数名.stringValue = "文字列"

でできるらしいのがわかったので実装したら出来ました(^^;)


update関数の作成

次に、60分の1秒ごとに更新されるupdate関数の作成を作成しました。

そちらがこれ↓


update()関数

override func viewDidLoad() {

var timer = NSTimer.scheduledTimerWithTimeInterval(1/60, target: self, selector: "update", userInfo: nil, repeats: true)
}

func update() {
nowTime()
}


これはNSTimerを利用して作ってます。

こちらの記事を参考にさせていただきました↓

SwiftでNSTimer。別クラス内でもタイマーを設定する。

この記事では1秒ごとに呼びだされるものでしたが、私はUnityのupdate関数と同じになんとなく一緒にしたかったので60分の1秒にしました(^^;)

ちなみに

NSTimer.scheduledTimerWithTimeInterval(秒間, target: self, selector: "関数名", userInfo: nil, repeats: true)

となっていて、秒間で1/60とすることで60分の1秒にしています。秒間を1にすれば1秒ごとに呼び出されます。(たぶん。)

そして、その秒間で実行されるのが関数名に書かれた関数です。

なので、update()関数を作成しとけばそれば呼び出されます。


時間の取得

これは結構サンプルが落ちていたのでそのまま流用されていただきました。

その記事がこちら↓

008 現在時間の取得

こちらの記事が書かれていたサイトにはSwiftの様々なサンプルコードが公開されているのでありがたいです(*´ω`*)

流用させていただいたところだけ抜き出すとこんな感じです。


nowTime()関数内

//現在時刻を取得.

let myDate: NSDate = NSDate()

//カレンダーを取得.
let myCalendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)

//取得するコンポーネントを決める.
let myComponetns = myCalendar.components(NSCalendarUnit.CalendarUnitYear |
NSCalendarUnit.CalendarUnitMonth |
NSCalendarUnit.CalendarUnitDay |
NSCalendarUnit.CalendarUnitHour |
NSCalendarUnit.CalendarUnitMinute |
NSCalendarUnit.CalendarUnitSecond |
NSCalendarUnit.CalendarUnitWeekday,
fromDate: myDate)

let weekdayStrings: Array = ["nil","日","月","火","水","木","金","土","日"]


現在の時間をNSDate()関数で取得して、カレンダー情報を取得して、そこから必要な情報を抜き出して、最後に曜日の配列を作成するという流れです。これは実はObjective-Cのときとほぼ同じ。

ただ、サンプルがこうしてあるとCopy&Pastで終わるのでありがたや。まぁ、全てをCopy&Pastでやってしまうと問題ですが。


labelに出力

Storyboard上で貼ったlabelに出力する方法は

labelの変数名.stringValue = "出力したい文字"

ちなみにIntのものを出力する際は

labelの変数名.stringValue = Int型などの変数や数値

そして、文字列と共に数値を表示したい場合は

labelの変数名.stringValue = "文字列\(Int型などの変数や数値)"

でいけるっぽいです。


1桁の数字の時は前に0を追加する。(例えば1秒なら01秒に。)

そちらを実装したのがこちらの関数


addZero()

func addZero(timeString:String,timeNuber:Int)->String{

if(countElements(timeString)==1){
return ("0\(timeNuber)")
}else{
return ("\(timeNuber)")
}
}

countElements()関数を利用して文字列の長さを調べてそれが1なら1桁ということなので、そのときは0を前に入れて返すという単純なものです。

参考になる記事:『Swiftで文字列長

ちなみに返す際にString型の場合は括弧()を付けないと怒られました(^^;)


ダメな例

return "\(timeNuber)"    //Errorが出る。



OKな例

return ("\(timeNuber)")  //Errorが出る。



関数に関して

上記の『1桁の数字の時は前に0を追加する。』の節で紹介している関数の書き方。

これはSwift独特?なものだったので少し困りました(^^;)

これに関してはこちらの記事を参考にしました↓

のんびりSwift : 関数 #1 : 導入


引数のある関数

(『のんびりSwift : 関数 #1 : 導入』より引用)


返り値の型の指定の仕方が独特...笑

これを知らなかったばかりに怒られました(^^;)


数値と文字列の相互変換

こちらは調べたら簡潔にわかりやすく書いてある記事があり簡単でした。

記事:『【swift】数字 文字列 の相互変換

今回は上記の『1桁の数字の時は前に0を追加する。』を実装するために数値から文字列に変換だけが必要なのでそれについてだけ。(myComponetnsから得られるのがInt型のため。)

サンプルがこちら↓


数値から文字列に変換

var x = 1             //Int型

var str = String(x) //string型
var str2 = "\(x)" //string型


最後に

簡単なアプリですが、ちょっとSwiftの勉強になったので良かったです。

やっぱり目に見える形で簡単に作れるのは楽しいなぁ。

どんなにしょぼくても。