Class 06iOS 應⽤用軟體設計
內容⼤大綱•   時間控制 Timer    •   QV063:基本的 Timer 應⽤用 (⼩小時鐘)    •   QV064:指定 Timer 物件 (碼錶控制)    •   QV065:精確的時間計算 (碼錶)•   UIView ...
時間控制 Timer
NSTimer 使⽤用時機• 強迫隔⼀一段時間後再執⾏行某段程式• 間隔⼀一段時間重覆執⾏行某段程式• 遊戲程式主迴圈內經常使⽤用
NSTimer 原理 (1)• Cocoa Touch 的 Foundation 框架內的類別• 與 NSRunLoop (主要執⾏行迴圈) 配合來處 理定時和排程⼯工作• 可直接使⽤用主執⾏行緒的 run loop,也能 ⼿手動執⾏行其他⾮非...
NSTimer 原理 (2)• 計時器並⾮非即時的機制,是在 run loop 運作且被觸發的時間到了,才會被觸發• 設定的時間『不是固定保証會執⾏行』, ⽽而是『最⼩小的間隔時間』,或是『最早 的觸發時間』
NSTimer 觸發誤差 (1)在這之前 run loop不會檢視,所以不  可能觸發                50~100 毫秒                 延後誤差     預計觸發時間                 實際觸發時間
NSTimer 觸發誤差 (2)         預計        預計       預計開始計時       第⼀一次觸發    第⼆二次觸發   第三次觸發                 預計觸發時間                 不...
NSTimer 使⽤用•   很簡單,只要指定    •   間隔的時間 (秒)    •   要執⾏行的函式 (target, method, selector)    •   是否要重覆 (repeat)    •   (進階) 傳遞⼀一些...
NSTimer ⽤用法[NSTimer scheduledTimerWithTimeInterval:0.01                    target:self                  selector:@selector...
範例:基本的 NSTimer 使⽤用      (⼩小時鐘)
Project QV063使⽤用 NSTimer⽏毋需宣告 NSTimer 物件⼩小時鐘:顯⽰示現在⽇日期時間簡易碼錶計次
ViewController.h#import <UIKit/UIKit.h>@interface ViewController : UIViewController{    IBOutlet UILabel *myLabel1, *myLab...
ViewController.xib
ViewController.m (1/2)- (void)viewDidLoad{    [super viewDidLoad];    //[self showTime:nil];    count = 0;    [NSTimer sch...
ViewController.m (1/2)- (void)showTime:(NSTimer *)theTimer{    // 顯⽰示時間    NSDateFormatter *dateFormat = [[NSDateFormatter...
ViewController.m (2/2) ⼀一些額外的練習// 其他練習// ⽤用 C 語⾔言的⽅方法取得時間及格式,當然是不建議time_t currentTime = time(NULL);struct tm timeStruct;lo...
範例:NSTimer 使⽤用(必須指定 NSTimer 物件之情形)
Project QV064碼錶計時的功能暫時採⽤用 count 次數累加的⽅方式,準度會有問題按鍵具有不同功能的切換(暫停及繼續)
ViewController.h#import <UIKit/UIKit.h>@interface ViewController : UIViewController{    NSTimer *timer;    IBOutlet UILabe...
ViewController.xib
- (void)viewDidLoad                               ViewController.m (1/2){    [super viewDidLoad];    count = 0;}- (void) s...
ViewController.m (1/2)- (IBAction) pauseCount:(id)sender{    if([timer isValid])    {        [btnPause setTitle:@"繼續" forS...
範例:精確的時間計算   (碼錶)
Project QV065處理碼錶顯⽰示的正確做法(兩個時間點相減的⽅方式)
⾃自訂的 TimerElapsed 類別
TimerElapsed.hTimerElapsed 類別宣告       #import <Foundation/Foundation.h>       @interface TimerElapsed : NSObject       {  ...
#import "TimerElapsed.h"                                TimerElapsed.m (1/2)@implementation TimerElapsed- (id) init{    se...
TimerElapsed.m (2/2)...... 前有程式 ......- (double) timeElapsedInSeconds{    return [end timeIntervalSinceDate:begin];}- (dou...
TimeElapsed 類別的 method - (void) beginPoint (設定計時開始點) - (void) endPoint (設定計時結束點) - (double) timeElapsedInSeconds       (傳回...
單純測試 TimerElapsed 類別的功能                                                ViewController.m- (void)viewDidLoad{    [super view...
ViewController.h#import <UIKit/UIKit.h>#import "TimerElapsed.h"@interface ViewController : UIViewController{    IBOutlet U...
ViewController.xib
結合⾺馬錶開關的範例碼                                                     ViewController.m- (IBAction) timerStart:(id)sender{    [ti...
NSTimer 記憶體使⽤用問題Note also the point on Memory Management at the bottom of the article:Because the run loop maintains the t...
挑戰練習• 倒數計時• 同時使⽤用多個計時器• ⾮非固定時間的排程
參考資料補充• How do I use NSTimer  (http://stackoverflow.com/questions/1449035/how-do-i-use-nstimer)• 計算碼錶經過的時間差  (http://stacko...
UIView 基本觀念
Architecture of the Views
UIView 階層
UIView 座標
View CoordinatesCGFloatCGPoint   C struct with two CGFloats in it: x and y.   CGPoint p = CGPointMake(34.5, 22.0);   p.x +...
UIView 位置與尺⼨寸
建⽴立 UIView• 由 Interface Builder 建⽴立• 由程式產⽣生  CGRect viewRect = CGRectMake(0, 0, 100, 100);  UIView* myView = [[UIView allo...
UIView Properties•   alpha, hidden, opaque, backgroundColor•   bounds, frame, center•   transform•   autoresizingMask, aut...
UIView tag 屬性• tag 屬性,為⼀一整數值• 取得特定物件的⽅方法 viewWithTab:• 速度快• 預設 tag 為 0
UIView 增加、刪除與移動• addSubview:• insertSubview...• bringSubviewToFront:• sendSubviewToBack:• exchangeSubviewAtIndex:  withSub...
UIView 隱藏•   常⽤用⽅方法    •   alpha (0.0 ~ 1.0) (適合⽤用在動畫效果上)    •   hidden (YES / NO)•   隱藏的 UIView 物件    •   不會接受 touch 觸控  ...
UIView 待續......• 動畫效果• 座標轉換 (平移、旋轉、尺⼨寸)• 觸控處理
範例:UIView 的功能操作
Project QV077UIView 解說⽤用程式UIView 基本 method  AddSubview  RemoveFromSuperview  BringSubviewToFront  SendSubviewToBack  Excha...
@interface ViewController : UIViewController{                                              ViewController.h    IBOutlet UI...
ViewController.m (1/2)- (IBAction) buttonAddR:(id)sender{    [self.view addSubview:viewR];}- (IBAction) buttonRemoveR:(id)...
ViewController.m (2/2)- (IBAction) change01:(id)sender{    [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];}    ...
範例:  UIView 的 tag
Project QV030多個按鈕,都執⾏行同⼀一段程式,如何知道按下哪⼀一個按鈕?利⽤用 UIView 的 tag 屬性
ViewController.h                ViewController.xib#import <UIKit/UIKit.h>@interface ViewController :UIViewController{    I...
- (IBAction)updateLabel:(id)sender{                                    ViewController.m    switch ([sender tag])    {     ...
補充tag 屬性的設定亦可在 xib 檔裡設定思考問題:按鈕若更多,可以設定按鈕物件的陣列嗎?
範例:UISegmentedControl
Project QV069UISegmentedControl
ViewController.h#import <UIKit/UIKit.h>@interface ViewController : UIViewController{    IBOutlet UIImageView *imageView;}-...
ViewController.xib
ViewController.m- (IBAction) buttonAction: (UISegmentedControl *) sender{    // 取得按下何鍵    NSInteger index = sender.selecte...
範例:  1~9 快速按鍵遊戲    (陣列的應⽤用)
Project QV078遊戲程式:數字快按NSMutableArray......
#import <UIKit/UIKit.h>                         ViewController.hstatic const int NUM_TOTAL = 9;@interface ViewController :...
ViewController.xib (1/2)  每個數字按鍵的 tag 屬性都要設定
ViewController.xib (2/2)    每個數字按鍵都   指定到同樣的事件
ViewController.m (1/9)程式開始的設定- (void)viewDidLoad{    [super viewDidLoad];    listArray = [[NSMutableArray alloc] initWithO...
重建數字排列,指定到各個按鍵                                ViewController.m (2/9)- (IBAction) buildList:(id)sender{    // 陣列打散         ...
- (IBAction) buildList:(id)sender                 ViewController.m (2/9){    ****** 省略部份程式 ******    // 起始設定    currentNum...
ViewController.m (1/9)    每次按鍵後的程式-(IBAction) buttonClick:(id)sender{    UIButton *button = (UIButton *)sender;    int val...
遊戲時間的計算- (void) beginPoint                             ViewController.m (1/9){    begin = [NSDate date];}- (void) endPoint...
⾃自我練習 最佳成績的保存... 將⼀一場遊戲設為連玩三次、九次... 開始前加⼊入⼀一段倒數計時... 不⽤用數字,改⽤用英⽂文順序,或是⼀一段 詩詞句⼦子等...
......
Upcoming SlideShare
Loading in …5
×

I os 06

668 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
668
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

I os 06

  1. 1. Class 06iOS 應⽤用軟體設計
  2. 2. 內容⼤大綱• 時間控制 Timer • QV063:基本的 Timer 應⽤用 (⼩小時鐘) • QV064:指定 Timer 物件 (碼錶控制) • QV065:精確的時間計算 (碼錶)• UIView 物件 • QV077:UIView 的操作⽅方法 • QV030:UIView 的 tag 屬性⽤用法 • QV069:UISegmented Control• NSMutableArray 陣列 • QV078:數字快按遊戲
  3. 3. 時間控制 Timer
  4. 4. NSTimer 使⽤用時機• 強迫隔⼀一段時間後再執⾏行某段程式• 間隔⼀一段時間重覆執⾏行某段程式• 遊戲程式主迴圈內經常使⽤用
  5. 5. NSTimer 原理 (1)• Cocoa Touch 的 Foundation 框架內的類別• 與 NSRunLoop (主要執⾏行迴圈) 配合來處 理定時和排程⼯工作• 可直接使⽤用主執⾏行緒的 run loop,也能 ⼿手動執⾏行其他⾮非主執⾏行緒的 run loop
  6. 6. NSTimer 原理 (2)• 計時器並⾮非即時的機制,是在 run loop 運作且被觸發的時間到了,才會被觸發• 設定的時間『不是固定保証會執⾏行』, ⽽而是『最⼩小的間隔時間』,或是『最早 的觸發時間』
  7. 7. NSTimer 觸發誤差 (1)在這之前 run loop不會檢視,所以不 可能觸發 50~100 毫秒 延後誤差 預計觸發時間 實際觸發時間
  8. 8. NSTimer 觸發誤差 (2) 預計 預計 預計開始計時 第⼀一次觸發 第⼆二次觸發 第三次觸發 預計觸發時間 不受前次的影 實際觸發 實際觸發 (第⼀一次) (第⼆二次) 第⼆二次觸發時間超過 第三次預計觸發時間 (不會重覆兩次)
  9. 9. NSTimer 使⽤用• 很簡單,只要指定 • 間隔的時間 (秒) • 要執⾏行的函式 (target, method, selector) • 是否要重覆 (repeat) • (進階) 傳遞⼀一些資料給 Timer 函式• 可直接引⽤用,可以不⽤用移除• 可指定多個計時器
  10. 10. NSTimer ⽤用法[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showTime:) userInfo:nil repeats:YES]; - (void)showTime:(NSTimer *)theTimer { // 固定執⾏行的程式寫在此 // 在內部讓 timer 停⽌止 if(count>=500) { [theTimer invalidate]; theTimer = nil; } }
  11. 11. 範例:基本的 NSTimer 使⽤用 (⼩小時鐘)
  12. 12. Project QV063使⽤用 NSTimer⽏毋需宣告 NSTimer 物件⼩小時鐘:顯⽰示現在⽇日期時間簡易碼錶計次
  13. 13. ViewController.h#import <UIKit/UIKit.h>@interface ViewController : UIViewController{ IBOutlet UILabel *myLabel1, *myLabel2, *myLabel3; int count;}@end
  14. 14. ViewController.xib
  15. 15. ViewController.m (1/2)- (void)viewDidLoad{ [super viewDidLoad]; //[self showTime:nil]; count = 0; [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showTime:) userInfo:nil repeats:YES];}
  16. 16. ViewController.m (1/2)- (void)showTime:(NSTimer *)theTimer{ // 顯⽰示時間 NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate *now = [[NSDate alloc] init]; NSString *nowString = [dateFormat stringFromDate:now]; myLabel1.text = nowString; // 顯⽰示計數 count++; myLabel2.text = [NSString stringWithFormat:@"%d", count]; // 從計數改成時分秒的顯⽰示 (不建議採⽤用此種不精確的⽅方式) int ms, ss, mm, hh; ms = count % 100; ss = (int)(count / 100) % 60; mm = (int)(count / 6000) % 3600; hh = (int)(count / 360000) % 86400; myLabel3.text = [NSString stringWithFormat:@"%02d:%02d:%02d.%02d", hh, mm, ss, ms];}
  17. 17. ViewController.m (2/2) ⼀一些額外的練習// 其他練習// ⽤用 C 語⾔言的⽅方法取得時間及格式,當然是不建議time_t currentTime = time(NULL);struct tm timeStruct;localtime_r(&currentTime, &timeStruct);char buffer[20];strftime(buffer, 20, "%d-%m-%Y %H:%M:%S", &timeStruct);myLabel1.text = [NSString stringWithFormat:@"%s", buffer];// 在內部讓 timer 停⽌止if(count>=500){ [theTimer invalidate]; theTimer = nil;}
  18. 18. 範例:NSTimer 使⽤用(必須指定 NSTimer 物件之情形)
  19. 19. Project QV064碼錶計時的功能暫時採⽤用 count 次數累加的⽅方式,準度會有問題按鍵具有不同功能的切換(暫停及繼續)
  20. 20. ViewController.h#import <UIKit/UIKit.h>@interface ViewController : UIViewController{ NSTimer *timer; IBOutlet UILabel *display; int count; IBOutlet UIButton *btnPause;}- (void) showDisplay;- (IBAction) startCount:(id)sender;- (IBAction) pauseCount:(id)sender;- (IBAction) resetCount:(id)sender;@end
  21. 21. ViewController.xib
  22. 22. - (void)viewDidLoad ViewController.m (1/2){ [super viewDidLoad]; count = 0;}- (void) showDisplay{ count++; display.text = [NSString stringWithFormat:@"%d", count];}- (IBAction) startCount:(id)sender;{ if(!timer) 這個檢查務必要有 { timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showDisplay) userInfo:nil repeats:YES]; }}- (IBAction) resetCount:(id)sender{ [timer invalidate]; timer = nil; 這個指定務必要有 count = 0; display.text = [NSString stringWithFormat:@"%d", count];}
  23. 23. ViewController.m (1/2)- (IBAction) pauseCount:(id)sender{ if([timer isValid]) { [btnPause setTitle:@"繼續" forState:UIControlStateNormal]; [timer invalidate]; } else { [btnPause setTitle:@"暫停" forState:UIControlStateNormal]; timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showDisplay) userInfo:nil repeats:YES]; }}
  24. 24. 範例:精確的時間計算 (碼錶)
  25. 25. Project QV065處理碼錶顯⽰示的正確做法(兩個時間點相減的⽅方式)
  26. 26. ⾃自訂的 TimerElapsed 類別
  27. 27. TimerElapsed.hTimerElapsed 類別宣告 #import <Foundation/Foundation.h> @interface TimerElapsed : NSObject { NSDate *begin; NSDate *end; } - (void) beginPoint; - (void) endPoint; - (double) timeElapsedInMilliseconds; - (double) timeElapsedInSeconds; - (double) timeElapsedInMinutes; @end
  28. 28. #import "TimerElapsed.h" TimerElapsed.m (1/2)@implementation TimerElapsed- (id) init{ self = [super init]; if (self != nil) { begin = nil; TimerElapsed 類別的實作 end = nil; } return self;}- (void) beginPoint{ begin = [NSDate date];}- (void) endPoint{ end = [NSDate date];}...... 未完 ......
  29. 29. TimerElapsed.m (2/2)...... 前有程式 ......- (double) timeElapsedInSeconds{ return [end timeIntervalSinceDate:begin];}- (double) timeElapsedInMilliseconds{ return [self timeElapsedInSeconds] * 1000.0f;}- (double) timeElapsedInMinutes{ return [self timeElapsedInSeconds] / 60.0f;}@end
  30. 30. TimeElapsed 類別的 method - (void) beginPoint (設定計時開始點) - (void) endPoint (設定計時結束點) - (double) timeElapsedInSeconds (傳回兩個時間點間之時間,單位為秒) - (double) timeElapsedInMilliseconds (傳回兩個時間點間之時間,單位為毫秒) - (double) timeElapsedInMinutes (傳回兩個時間點間之時間,單位為分)
  31. 31. 單純測試 TimerElapsed 類別的功能 ViewController.m- (void)viewDidLoad{ [super viewDidLoad]; // timerElapsed = [[TimerElapsed alloc] init]; // 測試 TimerElapsed 的功能 TimerElapsed *timerElapsed = [[TimerElapsed alloc] init]; [timerElapsed beginPoint]; // Do some work [timerElapsed endPoint]; NSLog(@"Total time was: %lf milliseconds", [timerElapsed timeElapsedInMilliseconds]); NSLog(@"Total time was: %lf seconds", [timerElapsed timeElapsedInSeconds]); NSLog(@"Total time was: %lf minutes", [timerElapsed timeElapsedInMinutes]);}
  32. 32. ViewController.h#import <UIKit/UIKit.h>#import "TimerElapsed.h"@interface ViewController : UIViewController{ IBOutlet UILabel *display; TimerElapsed *timerElapsed; NSTimer *timer;}- (void) showDisplay;- (IBAction) timerStart:(id)sender;- (IBAction) timerStop:(id)sender;@end
  33. 33. ViewController.xib
  34. 34. 結合⾺馬錶開關的範例碼 ViewController.m- (IBAction) timerStart:(id)sender{ [timerElapsed beginPoint]; if(!timer) { timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showDisplay) userInfo:nil repeats:YES]; }}- (IBAction) timerStop:(id)sender{ [timerElapsed endPoint]; [timer invalidate]; timer = nil;}- (void) showDisplay{ [timerElapsed endPoint]; display.text = [NSString stringWithFormat:@"%f", [timerElapsed timeElapsedInSeconds]];}
  35. 35. NSTimer 記憶體使⽤用問題Note also the point on Memory Management at the bottom of the article:Because the run loop maintains the timer, from the perspective of memorymanagement theres typically no need to keep a reference to a timerafter you’ve scheduled it. Since the timer is passed as an argumentwhen you specify its method as a selector, you can invalidate arepeating timer when appropriate within that method. In manysituations, however, you also want the option of invalidating the timer—perhaps even before it starts. In this case, you do need to keep areference to the timer, so that you can send it an invalidate messagewhenever appropriate. If you create an unscheduled timer (see“Unscheduled Timers”), then you must maintain a strong reference to thetimer (in a reference-counted environment, you retain it) so that it is notdeallocated before you use it.
  36. 36. 挑戰練習• 倒數計時• 同時使⽤用多個計時器• ⾮非固定時間的排程
  37. 37. 參考資料補充• How do I use NSTimer (http://stackoverflow.com/questions/1449035/how-do-i-use-nstimer)• 計算碼錶經過的時間差 (http://stackoverflow.com/questions/3519562/how-do-i-write-a-timer-in- objective-c)• 在 NSTimer 中使⽤用 userInfo (http://www.adamzucchi.com/blog/?p=41)
  38. 38. UIView 基本觀念
  39. 39. Architecture of the Views
  40. 40. UIView 階層
  41. 41. UIView 座標
  42. 42. View CoordinatesCGFloatCGPoint C struct with two CGFloats in it: x and y. CGPoint p = CGPointMake(34.5, 22.0); p.x += 20; / move right by 20 points /CGSize C struct with two CGFloats in it: width and height. CGSize s = CGSizeMake(100.0, 200.0); s.height += 50; / make the size 50 points taller /CGRect C struct with a CGPoint origin and a CGSize size. CGRect aRect = CGRectMake(45.0, 75.5, 300, 500); aRect.size.height += 45; / make the rectangle 45 points taller / aRect.origin.x += 30; / move the rectangle to the right 30 points /
  43. 43. UIView 位置與尺⼨寸
  44. 44. 建⽴立 UIView• 由 Interface Builder 建⽴立• 由程式產⽣生 CGRect viewRect = CGRectMake(0, 0, 100, 100); UIView* myView = [[UIView alloc] initWithFrame:viewRect];
  45. 45. UIView Properties• alpha, hidden, opaque, backgroundColor• bounds, frame, center• transform• autoresizingMask, autoresizesSubviews• contentMode, contentStretch, contentScaleFactor• gestureRecognizers, userInteractiionEnabled, multipleTouchEnabled, exclusiveTouch• subviews, drawRect:, layer
  46. 46. UIView tag 屬性• tag 屬性,為⼀一整數值• 取得特定物件的⽅方法 viewWithTab:• 速度快• 預設 tag 為 0
  47. 47. UIView 增加、刪除與移動• addSubview:• insertSubview...• bringSubviewToFront:• sendSubviewToBack:• exchangeSubviewAtIndex: withSubviewAtIndex:• removeFromSuperview
  48. 48. UIView 隱藏• 常⽤用⽅方法 • alpha (0.0 ~ 1.0) (適合⽤用在動畫效果上) • hidden (YES / NO)• 隱藏的 UIView 物件 • 不會接受 touch 觸控 • 仍會隨著畫⾯面階層 autoresizing • ⺫⽬目前為 first responder 的物件不會⾃自動 resign
  49. 49. UIView 待續......• 動畫效果• 座標轉換 (平移、旋轉、尺⼨寸)• 觸控處理
  50. 50. 範例:UIView 的功能操作
  51. 51. Project QV077UIView 解說⽤用程式UIView 基本 method AddSubview RemoveFromSuperview BringSubviewToFront SendSubviewToBack ExchangeSubview.....
  52. 52. @interface ViewController : UIViewController{ ViewController.h IBOutlet UIView *viewR; IBOutlet UIView *viewG; IBOutlet UIView *viewB;}- (IBAction) buttonAddR:(id)sender;- (IBAction) buttonAddG:(id)sender; 畫⾯面三個顏⾊色區塊- (IBAction) buttonAddB:(id)sender;- (IBAction) buttonRemoveR:(id)sender;- (IBAction) buttonRemoveG:(id)sender;- (IBAction) buttonRemoveB:(id)sender;- (IBAction) buttonToFrontR:(id)sender;- (IBAction) buttonToFrontG:(id)sender;- (IBAction) buttonToFrontB:(id)sender;- (IBAction) buttonToBackR:(id)sender;- (IBAction) buttonToBackG:(id)sender;- (IBAction) buttonToBackB:(id)sender;- (IBAction) change01:(id)sender;- (IBAction) moveLastThree:(id)sender;@end
  53. 53. ViewController.m (1/2)- (IBAction) buttonAddR:(id)sender{ [self.view addSubview:viewR];}- (IBAction) buttonRemoveR:(id)sender{ [viewR removeFromSuperview]; 與層次順序有關之} 主要 method- (IBAction) buttonToFrontR:(id)sender{ [self.view bringSubviewToFront:viewR];}- (IBAction) buttonToBackR:(id)sender{ [self.view sendSubviewToBack:viewR];}****** 省略部份程式 ******
  54. 54. ViewController.m (2/2)- (IBAction) change01:(id)sender{ [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];} 所有⼦子視圖 為陣列結構- (IBAction) moveLastThree:(id)sender{ int lastIndex = [[self.view subviews] count]; [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:(lastIndex-1)]; [self.view exchangeSubviewAtIndex:1 withSubviewAtIndex:(lastIndex-2)]; [self.view exchangeSubviewAtIndex:2 withSubviewAtIndex:(lastIndex-3)];}
  55. 55. 範例: UIView 的 tag
  56. 56. Project QV030多個按鈕,都執⾏行同⼀一段程式,如何知道按下哪⼀一個按鈕?利⽤用 UIView 的 tag 屬性
  57. 57. ViewController.h ViewController.xib#import <UIKit/UIKit.h>@interface ViewController :UIViewController{ IBOutlet UILabel *display; IBOutlet UIButton *btn1; IBOutlet UIButton *btn2; IBOutlet UIButton *btn3; IBOutlet UIButton *btn4; IBOutlet UIButton *btn5;}- (IBAction)updateLabel:(id)sender;@end
  58. 58. - (IBAction)updateLabel:(id)sender{ ViewController.m switch ([sender tag]) { case 1: display.text = @"111"; break; case 2: display.text = @"222"; break; // *** 部份內容省略 *** }}- (void)viewDidLoad 注意在⼀一開始做好設定{ [super viewDidLoad]; [btn1 setTag:1]; [btn2 setTag:2]; [btn3 setTag:3]; [btn4 setTag:4]; [btn5 setTag:5];}
  59. 59. 補充tag 屬性的設定亦可在 xib 檔裡設定思考問題:按鈕若更多,可以設定按鈕物件的陣列嗎?
  60. 60. 範例:UISegmentedControl
  61. 61. Project QV069UISegmentedControl
  62. 62. ViewController.h#import <UIKit/UIKit.h>@interface ViewController : UIViewController{ IBOutlet UIImageView *imageView;}- (IBAction) buttonAction: (UISegmentedControl *) sender;@end
  63. 63. ViewController.xib
  64. 64. ViewController.m- (IBAction) buttonAction: (UISegmentedControl *) sender{ // 取得按下何鍵 NSInteger index = sender.selectedSegmentIndex; // 指定圖檔名 NSString *show = [NSString stringWithFormat:@"cat%d.png", index]; // 顯⽰示圖 imageView.image = [UIImage imageNamed:show];}
  65. 65. 範例: 1~9 快速按鍵遊戲 (陣列的應⽤用)
  66. 66. Project QV078遊戲程式:數字快按NSMutableArray......
  67. 67. #import <UIKit/UIKit.h> ViewController.hstatic const int NUM_TOTAL = 9;@interface ViewController : UIViewController{ IBOutlet UILabel *scoreLabel; 存放各個位置內的 NSMutableArray *listArray; 實際 (顯⽰示) 數字 int currentNumber; NSDate *begin; ⺫⽬目前按到哪個數字 NSDate *end;}- (void) beginPoint; ⽤用來記錄時間點- (void) endPoint;- (IBAction) buildList:(id)sender;- (IBAction) buttonClick:(id)sender;@end
  68. 68. ViewController.xib (1/2) 每個數字按鍵的 tag 屬性都要設定
  69. 69. ViewController.xib (2/2) 每個數字按鍵都 指定到同樣的事件
  70. 70. ViewController.m (1/9)程式開始的設定- (void)viewDidLoad{ [super viewDidLoad]; listArray = [[NSMutableArray alloc] initWithObjects:nil]; for(int i=0; i<NUM_TOTAL; i++) { [listArray addObject:[NSNumber numberWithInt:(i+1)]]; } [self buildList:nil];} 將陣列填⼊入 1~9 的數字
  71. 71. 重建數字排列,指定到各個按鍵 ViewController.m (2/9)- (IBAction) buildList:(id)sender{ // 陣列打散 重建陣列內容 (隨機打散) for (int i=0; i<NUM_TOTAL-1; i++) { int j = i + (arc4random() % (NUM_TOTAL-i)); [listArray exchangeObjectAtIndex:i withObjectAtIndex:j]; } // 指定各個按鈕的⽂文字 for (int i=0; i<[listArray count]; i++) { UIButton *button = (UIButton *)[self.view viewWithTag:(i+1)]; button.alpha = 1.0; button.enabled = YES; int value = [[listArray objectAtIndex:i] intValue]; [button setTitle:[NSString stringWithFormat:@"%d", value] forState:UIControlStateNormal]; } 取得各個按鍵 ****** 省略部份程式 ****** 第 i 個陣列元素值}
  72. 72. - (IBAction) buildList:(id)sender ViewController.m (2/9){ ****** 省略部份程式 ****** // 起始設定 currentNumber = 1; scoreLabel.text = @""; 設定時間點 取得陣列的各個元素 // 開始時間點記錄 (指定成⼀一個字串) [self beginPoint]; // debug NSString *str = [[NSString alloc] initWithString:@""]; // ⽅方法⼀一 for (int i=0; i<[listArray count]; i++) { str = [str stringByAppendingFormat:@"%1d", [[listArray objectAtIndex:i] integerValue]]; } // ⽅方法⼆二 for(NSNumber *obj in listArray) { str = [str stringByAppendingFormat:@"%1d", [obj integerValue]]; } NSLog(@"%@", str);}
  73. 73. ViewController.m (1/9) 每次按鍵後的程式-(IBAction) buttonClick:(id)sender{ UIButton *button = (UIButton *)sender; int value = [[[button titleLabel] text] intValue]; if(currentNumber==value) { 正確的按鍵,則變淡失效 button.alpha = 0.4; button.enabled = NO; currentNumber++;  遊戲結束的判斷 // NSLog(@"Next numbe: %d", currentNumber); if(currentNumber>NUM_TOTAL) { [self endPoint]; float timeElapsed = [end timeIntervalSinceDate:begin]; scoreLabel.text = [NSString stringWithFormat: @"Bingo!!! %6.2f 秒", timeElapsed]; } }}
  74. 74. 遊戲時間的計算- (void) beginPoint ViewController.m (1/9){ begin = [NSDate date];}- (void) endPoint{ end = [NSDate date];}- (IBAction) buildList:(id)sender{ 記錄開始時間點 ****** 省略部份程式 ****** [self beginPoint]; // 開始時間點記錄} 記錄結束時間點-(IBAction) buttonClick:(id)sender{ ****** 省略部份程式 ****** 兩個時間點的間隔 if(*** 遊戲結束的條件 ***) { [self endPoint]; float timeElapsed = [end timeIntervalSinceDate:begin]; scoreLabel.text = [NSString stringWithFormat: @"Bingo!!! %6.2f 秒", timeElapsed]; }}
  75. 75. ⾃自我練習 最佳成績的保存... 將⼀一場遊戲設為連玩三次、九次... 開始前加⼊入⼀一段倒數計時... 不⽤用數字,改⽤用英⽂文順序,或是⼀一段 詩詞句⼦子等...
  76. 76. ......

×