prettyprint

2015年10月20日 星期二

Progress Demo


1. 新增專案

2. 新增 Progress 元件
3. 為顯示結果,亦拖曳 Label
4. 新增 Button 開啟 Progress
5. Label
6. Progress
7. Button
8. 完整程式

//
//  ViewController.swift
//  ProgressDemo
//
//  Created by Elvis Meng on 2015/10/18.
//  Copyright © 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    var time:Float = 0.0
    var timer = NSTimer()
    
    @IBOutlet weak var showProgress: UILabel!
    @IBOutlet weak var progress: UIProgressView!
    @IBOutlet weak var buttonStatus: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        progress.frame.size.width = 200
        progress.progressTintColor = UIColor.redColor()
        progress.trackTintColor = UIColor.greenColor()
        progress.progress = Float(0)
    }

    @IBAction func startProgress(sender: UIButton) {
        timer = NSTimer.scheduledTimerWithTimeInterval(0.1, 
                                                       target: self, 
                                                       selector:Selector("setProgress"),
                                                       userInfo: nil, 
                                                       repeats: true)
        buttonStatus.enabled = false
    }
    
    func setProgress() {
        time += 1.0
        progress.progress = time / 100
        showProgress.text = "\(time)%"
        if time >= 100 {
            timer.invalidate()
            buttonStatus.enabled = true
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
9. 測試
後記: Progress 這專案中,timer 的設定是關鍵,除此要知道目前現況時,就要設定類別為UIProgressView的 .progress 這屬性。 參考: 1. Progress View Tutorialin iOS8 with Swift , http://www.ioscreator.com/tutorials/progress-view-tutorial-in-ios8-with-swift 2. Swift Demo – Add Progress Bar, http://rshankar.com/swift-demo-add-progress-bar/ 3. Swift-Creating a Progress Bar, http://stackoverflow.com/questions/31432777/swift-creating-a-progress-bar

2015年10月18日 星期日

Stepper Demo


1. 新增專案

2. 尋找 UI Stepper 元件
3. 連結 UI Stepper 元件至 Code
4. 新增 UI Label 顯示 Stepper 的結果
5. 製作增加 increase 事件
6. 設定 Stepper 的事件 Action
7. 完整程式

//
//  ViewController.swift
//  StepperDemo
//
//  Created by Elvis Meng on 2015/10/18.
//  Copyright © 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var stepper: UIStepper!
    @IBOutlet weak var showStepper: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        stepper.minimumValue = 0
        stepper.maximumValue = 10
        stepper.stepValue = 1
        stepper.value = 0
        
        showStepper.text = "Your value :" + String(stepper.value)
    }

    @IBAction func stepperClick(sender: UIStepper) {
        showStepper.text = "Your value :" + String(stepper.value)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
8. 測試
後記: UI Stepper 這元件有 + 與 - 這 2 個方向,剛開始會以為需要設定 2 個 Action,一個處理正向 + 增加值,另一個處理負向 - 減少值。事實上只要新增一個 click action 即可,正負向由此元件來控制。 UI Stepper 這元件尺寸大小是固定,不能變更。 參考: 1. Stepper, https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/UIKitUICatalog/Stepper.html 2. UI Stepper Class, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIStepper_Class/ 3. String Format Specifiers, https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html

DatePicker Demo


日期與時間的設定常被用到。Apple 以類似賭場拉霸的滾筒式方式來設定日期與時間。在設定日期與時間前,我們要先決定好:

1. 模式 Mode: 是只設定日期或時間,或是兩者都要?
2. 時區 Locale: 這日期時間的時區是台北時間?還是其他地方的時區?
3. 滾筒的可選的日期/時間間隔 Interval
4. 最後日期 / 時間該如何呈現?

1. 新增專案

2. 拖曳一個 DatePicker 元件
3. 此時,Apple 已幫我們設定好 Default 值
4. 將 UI 中的 DataPiker 元件與 Code 連結
5. 為顯示設定日期/時間結果,新增 Label
6. 連結後的 Code
7. 新增當 DataPicker 的設定更改時,被啟發的事件 event
8. 設定此事件 event 為 dateUpdate
9. 完整程式

//
//  ViewController.swift
//  DatePickerDemo
//
//  Created by Elvis Meng on 2015/10/18.
//  Copyright © 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    var dateFormatter = NSDateFormatter()

    @IBOutlet weak var datePicker: UIDatePicker!
    @IBOutlet weak var showDatePicker: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        datePicker.datePickerMode = UIDatePickerMode.DateAndTime
        datePicker.locale = NSLocale(localeIdentifier: "zh_TW")
        datePicker.date = NSDate()
        
        dateFormatter.dateFormat = "西元 y 年 M 月 d 日 hh 點 mm 分 ss 秒"
        showDatePicker.text = dateFormatter.stringFromDate(datePicker.date)
    }

    @IBAction func dateUpdate(sender: UIDatePicker) {
        showDatePicker.text = dateFormatter.stringFromDate(datePicker.date)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
10. 測試
後記 日期 / 時間呈現時,顯示格式的設定很重要。例如:在這 demo 中以 var dateFormatter = NSDateFormatter() 宣告一個 dataFormatter 變數,而以 dateFormatter.dateFormat = "西元 y 年 M 月 d 日 hh 點 mm 分 ss 秒" 來設定。這裡更改 DatePicker 日期 / 時間並不會顯示,程式要另外修改屬性。 參考: 1. Date Picker, https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/UIKitUICatalog/DatePicker.html 2. NSDate, https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/ 3. DatePicker, https://developer.apple.com/library/prerelease/mac/samplecode/DatePicker/Introduction/Intro.html 4. NSDateFormatter, https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/

修改 Image 的圖層 Layer 邊框


1. 修改 Image 元件的 Layer 屬性

2. 完整程式

//
//  ViewController.swift
//  ImageViewDemo
//
//  Created by Elvis Meng on 2015/10/17.
//  Copyright © 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    var arrayNames = ["人間失格","改變成真","Steve Jobs"]
    var arrayImages:Array = []
    var imageIndex = 0
    var count = 0
    
    @IBOutlet weak var ImageNow: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        ImageNow.image = UIImage(named: "人間失格")
        count = arrayNames.count
        for var i = 0; i < count ; i++ {
            arrayImages.append(UIImage(named: arrayNames[i])!)
        }
        
        ImageNow.animationImages = arrayImages
        ImageNow.animationDuration = 12 // 2 seconds
    
        ImageNow.layer.borderColor = UIColor.orangeColor().CGColor
        ImageNow.layer.borderWidth = 5
        ImageNow.layer.cornerRadius = 30
        ImageNow.layer.masksToBounds = true
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func startClick(sender: UIButton) {
        ImageNow.startAnimating()
    }
    
    @IBAction func stopClick(sender: UIButton) {
        ImageNow.stopAnimating()
    }
    
    @IBAction func prevClick(sender: UIButton) {
        
        if  --imageIndex < 0 {
            imageIndex = count - 1
        }
        //ImageNow.image = UIImage(named: arrayNames[imageIndex])
        ImageNow.image = arrayImages[imageIndex]
    }

    @IBAction func nextClick(sender: UIButton) {
        
        if ++imageIndex == count {
            imageIndex = 0
        }
        //ImageNow.image = UIImage(named: arrayNames[imageIndex])
        ImageNow.image = arrayImages[imageIndex]
    }
}
3. 測試
參考: 1. UIImageView, https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIImageView_Class/ 2. View Programming Guide for iOS, https://developer.apple.com/library/prerelease/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009503 3. Image Views, https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/UIKitUICatalog/UIImageView.html#//apple_ref/doc/uid/TP40012857-UIImageView

改寫 UIImage ,定期播放 Image


1. 為讓 image 定期播放,新增 2 個按鈕 

2. 新增按鈕 Stop 與程式的連結
3. 同樣,新增按牛 Start 與程式的連結,連結後程式
4. 把所有影像都包裝起來
5. 設定將動態顯示的影像,以及下一張影像出現前等待的秒數
6. 寫啟動 Start 與停止 Stop 按鈕的程式
7. 完整程式

//
//  ViewController.swift
//  ImageViewDemo
//
//  Created by Elvis Meng on 2015/10/17.
//  Copyright © 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    var arrayNames = ["人間失格","改變成真","Steve Jobs"]
    var arrayImages:Array = []
    var imageIndex = 0
    var count = 0
    
    @IBOutlet weak var ImageNow: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        ImageNow.image = UIImage(named: "人間失格")
        count = arrayNames.count
        for var i = 0; i < count ; i++ {
            arrayImages.append(UIImage(named: arrayNames[i])!)
        }
        
        ImageNow.animationImages = arrayImages
        ImageNow.animationDuration = 12 // 2 seconds
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func startClick(sender: UIButton) {
        ImageNow.startAnimating()
    }
    
    @IBAction func stopClick(sender: UIButton) {
        ImageNow.stopAnimating()
    }
    
    @IBAction func prevClick(sender: UIButton) {
        
        if  --imageIndex < 0 {
            imageIndex = count - 1
        }
        //ImageNow.image = UIImage(named: arrayNames[imageIndex])
        ImageNow.image = arrayImages[imageIndex]
    }

    @IBAction func nextClick(sender: UIButton) {
        
        if ++imageIndex == count {
            imageIndex = 0
        }
        //ImageNow.image = UIImage(named: arrayNames[imageIndex])
        ImageNow.image = arrayImages[imageIndex]
    }
}
8. 測試

2015年10月17日 星期六

ImageView Demo


1. 新增專案

2. 將照片丟入 Assets.xcassets 資料夾
3. 找尋 Image View 這 UI 元件
4. 將 Image View 拖曳至 View 中,並在 UI 屬性 Image View 中 Image 設定 Default 影像
5. 增加 2 個 Button 按鈕
6. 將 UI Image 元件與 Code 程式連接
7. 將 UI Button 元件與 Code 程式連接
8. 完整程式

//
//  ViewController.swift
//  ImageViewDemo
//
//  Created by Elvis Meng on 2015/10/17.
//  Copyright © 2015年 Elvis Meng. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    var arrayNames = ["人間失格","改變成真","Steve Jobs"]
    var imageIndex = 0
    var count = 0
    
    @IBOutlet weak var ImageNow: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        ImageNow.image = UIImage(named: "人間失格")
        count = arrayNames.count
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func prevClick(sender: UIButton) {
        
        if  --imageIndex < 0 {
            imageIndex = count - 1
        }
        ImageNow.image = UIImage(named: arrayNames[imageIndex])
    }

    @IBAction func nextClick(sender: UIButton) {
        
        if ++imageIndex == count {
            imageIndex = 0
        }
        ImageNow.image = UIImage(named: arrayNames[imageIndex])
    }
}

9. 測試
注意: 測試時,若要使用 iPhone 5s 這模擬器測試,需不勾選
此外,模擬器要勾選設定

2015年10月15日 星期四

以 Object Oriented 觀點看 2 個畫面如何傳遞參數


畫面切換,彼此間要傳遞參數這是常碰到的。在此我以物件導向 Object Oriented 的觀點,來看參數如何在 2 個畫面間傳遞。

既然是兩個畫面 View,每個UI 的 View 就會對應到一個 View Controller。所謂 "對應",就是 UI 的 View 會有屬性 ID 設定,指定這 View 屬於那一個類別 Class。

既然是類別,那就是談到 Code 的實作。Swift 大大改進 Objective-C,將類別的宣告 header file 與 類別的實作都放在同一個檔案 .swift 裏。

定義好 UI View 的類別,那 2 個 View 之間的變數又該如何傳遞 ? Apple 提供一個函式 prepardForSegue:sender , 即在前一個 View Controller 的類別中,我們呼叫此函式,將變數傳遞到下一個 View Controller。 

我們以一個範例來說明。

首先,我們會有兩個 View。 View 1 指定為 FirstViwController, View 2 指定為 SecondViewController。 這兩個類別都是繼承 UIViewController。 雖然它們的父類別 Parent Class 都繼承相同類別,但,由於 FirstViewController 與 SecondViewController 的"長相"不同,所以需設定 2 個不同的類別。這裡所謂"長相",即它們各自的屬性 Property 與能提供的功能 Function (或 Method) 都不相同,當然要設計成 2 個不同的類別。每個類別將 Property 與 Method 封裝 Encapsulate 起來,這是 Object Oriented 最基本的概念。

假設我們設定 FirstViewController 有屬性 senderVar 被宣告如下:


import UIKit
class FirstViewController:UIViewController {
   override fun viewDidLoad() {
      var senderVar:String = "test"
   }
   ...
}
而在 SecondViewController 有屬性 receiverVar 被宣告如下:

import UIKit
class SecondViewController:UIViewController {
     var receiverVar:String
     println("Receive Var : \(receiverVar)")
}
現在我們也知道 Apple 提供 prepardForSegue:sender 這函式,但,該如何使用呼叫 ? 同樣我們以 code 來說明。

import UIKit
class FirstViewController:UIViewController {
   override func prepareForSeque(seque:UIStoryboardSeque, sender:AnyObject!) { 
      var secondViewController = seque.destinationViewController as SecondViewController
      secondViewController.receiverVar = senderVar
   }
   ...
}
看到沒? 我們在第一個類別 FirstViewController 透過呼叫 prepardForSegue:sender 這函式, 宣告一個 SecondViewController 物件為 secondViewController,然後將 FirstViewController 的變數 senderVar 指定給 SecondViewController 的變數 receiverVar,而在第二個 View 顯示出來。 在 Object Oriented 的觀念裡,外人的物件 Object 是無法直接使用,必須透過物件才可。 後記: 知道這設計的概念,對以後類似不同類別間的呼叫就能得心上手。 Code 只是表面,但 Code 裡面所包含的觀念若很清楚,寫程式就相對輕鬆多了。例如: Object Oriented 的設計與語法必須熟練,畢竟現在無論是 UI 或 Code 的設計,其中心觀念都圍繞在 Object Oriented。

2015年10月14日 星期三

Tab Bar Controller


Tab Bar 即是在 iPhone 下方的功能選項列表。有 2 個方式製作 Tab Bar: (1) 在 View Controller 上拖曳一個 Tab Bar Controller 元件 (2) 直接使用 Apple 已寫好的 Template, 即 Tabbed Application。

使用 Tab Bar 好處是無論 View 如何透過 Segue 切換,它都被顯示。 我們把 Tab Bar Controller 當成 Container,此 Container 已嵌入一個 Tab Bar 元件。所有被放在此 Container 的 View 屬於 Layer 1,但, Tab Bar 卻屬於 Layer 2。因此,View 無論如何切換,Tab Bar 永遠顯示在最上層。這概念與 Photoshop 的塗層 layer 概念相同。 Tab Bar Controller 是個非常特殊的 Container。若我們新增一個 View Controller 到此 Tab Bar Controller 中, 其嵌入的Tab Bar 元件就會新增一個 Button 與此 View Controller 呼應。也就是說,每個 Tab Bar 上的 Button 都會指向一個特定的 View Controller。 Tab Bar 上的 Button 的圖示 icon 可透過 Feature 這屬性客製化。 參考: 1. UITabBarController,https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITabBarController_Class/ 2. Tab Bar Controllers,https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/TabBarControllers.html

Navigator Controller Demo


新增專案:

新增 1 個 Navigator Controller 及 1 個 View Controller:
接下來將 Veiw 連結起來。此時,在第一個 View 新增 Button。之後,選此 Button, 按下 Control 鍵不放,將其拖曳到第二個 View,此時設定 Seque Action 選 Modal:
接著,在第三個 View 新增 Bar Button Item,之後,選此 Bar Button Item, 按下 Control 鍵不放,將其拖曳到第二個 View,此時設定 Seque Action 選 Push:
檢查 Bar Button Item 的放置位置:
測試: 1. 按下 Push 按鈕:
2. 按下 Item 按鈕:
3. 按下 Back 按鈕:
在 iPhone 6 會顯示 Root View Controller 按鈕 後記: Bar Button Item 拖曳擺放的位置要正確,若畫面上無法選取此 UI 元件,則在 UI Navigator 上點選此 UI 元件,然後點選 Triggered Seque,將此 UI 元件連結至第四個 View 即可,如下:
看起來一個很簡單的測試,卻帶出一個重要的概念。注意到沒?在 Storyboard 我們看到 4 個 View,但在測試時只看到 3 個 View。嚴格說,事實上第二個 UI 元件 Navigator Controller 不是 View,而是一個 View Container。所謂 View Container 就是它可以含有一個以上的 View。在這 Demo 只有含一個 View,即第三個 View。所以這個 Demo 無法真正看出 Navigator Controller 當初被設計出來的用意,即無法看到 View Container 與 View 之間的 Layer 關係。Apple 的 UI 元件一般在 View Controller 前有特定指名,都算是 View Container。例如:Table View Controller, Collection View Controller,Tab Bar Controller 等。
prettyPrint();