SlideShare une entreprise Scribd logo
1  sur  76
Class 06
iOS 應⽤用軟體設計
內容⼤大綱
•   時間控制 Timer
    •   QV063:基本的 Timer 應⽤用 (⼩小時鐘)
    •   QV064:指定 Timer 物件 (碼錶控制)
    •   QV065:精確的時間計算 (碼錶)

•   UIView 物件
    •   QV077:UIView 的操作⽅方法
    •   QV030:UIView 的 tag 屬性⽤用法
    •   QV069:UISegmented Control

•   NSMutableArray 陣列
    •   QV078:數字快按遊戲
時間控制 Timer
NSTimer 使⽤用時機


• 強迫隔⼀一段時間後再執⾏行某段程式
• 間隔⼀一段時間重覆執⾏行某段程式

• 遊戲程式主迴圈內經常使⽤用
NSTimer 原理 (1)

• Cocoa Touch 的 Foundation 框架內的類別
• 與 NSRunLoop (主要執⾏行迴圈) 配合來處
 理定時和排程⼯工作

• 可直接使⽤用主執⾏行緒的 run loop,也能
 ⼿手動執⾏行其他⾮非主執⾏行緒的 run loop
NSTimer 原理 (2)

• 計時器並⾮非即時的機制,是在 run loop
 運作且被觸發的時間到了,才會被觸發

• 設定的時間『不是固定保証會執⾏行』,
 ⽽而是『最⼩小的間隔時間』,或是『最早
 的觸發時間』
NSTimer 觸發誤差 (1)

在這之前 run loop
不會檢視,所以不
  可能觸發
                50~100 毫秒
                 延後誤差




     預計觸發時間                 實際觸發時間
NSTimer 觸發誤差 (2)
         預計        預計       預計
開始計時
       第⼀一次觸發    第⼆二次觸發   第三次觸發




                 預計觸發時間
                 不受前次的影
        實際觸發               實際觸發
        (第⼀一次)             (第⼆二次)

                      第⼆二次觸發時間超過
                      第三次預計觸發時間
                       (不會重覆兩次)
NSTimer 使⽤用

•   很簡單,只要指定
    •   間隔的時間 (秒)
    •   要執⾏行的函式 (target, method, selector)
    •   是否要重覆 (repeat)
    •   (進階) 傳遞⼀一些資料給 Timer 函式
•   可直接引⽤用,可以不⽤用移除

•   可指定多個計時器
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;
                   }
               }
範例:基本的 NSTimer 使⽤用

      (⼩小時鐘)
Project QV063

使⽤用 NSTimer
⽏毋需宣告 NSTimer 物件
⼩小時鐘:顯⽰示現在⽇日期時間
簡易碼錶計次
ViewController.h



#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    IBOutlet UILabel *myLabel1, *myLabel2, *myLabel3;
    int count;
}

@end
ViewController.xib
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];

}
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];
}
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;
}
範例:NSTimer 使⽤用

(必須指定 NSTimer 物件之情形)
Project QV064

碼錶計時的功能
暫時採⽤用 count 次數累加的
⽅方式,準度會有問題
按鍵具有不同功能的切換
(暫停及繼續)
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
ViewController.xib
- (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];
}
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];
    }
}
範例:精確的時間計算

   (碼錶)
Project QV065


處理碼錶顯⽰示的正確做法
(兩個時間點相減的⽅方式)
⾃自訂的 TimerElapsed 類別
TimerElapsed.h
TimerElapsed 類別宣告


       #import <Foundation/Foundation.h>

       @interface TimerElapsed : NSObject
       {
           NSDate *begin;
           NSDate *end;
       }

       -   (void) beginPoint;
       -   (void) endPoint;
       -   (double) timeElapsedInMilliseconds;
       -   (double) timeElapsedInSeconds;
       -   (double) timeElapsedInMinutes;

       @end
#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];
}

...... 未完 ......
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
TimeElapsed 類別的 method

 - (void) beginPoint (設定計時開始點)
 - (void) endPoint (設定計時結束點)


 - (double) timeElapsedInSeconds
       (傳回兩個時間點間之時間,單位為秒)
 - (double) timeElapsedInMilliseconds
       (傳回兩個時間點間之時間,單位為毫秒)
 - (double) timeElapsedInMinutes
       (傳回兩個時間點間之時間,單位為分)
單純測試 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]);

}
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
ViewController.xib
結合⾺馬錶開關的範例碼
                                                     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]];
}
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 memory
management there's typically no need to keep a reference to a timer
after you’ve scheduled it. Since the timer is passed as an argument
when you specify its method as a selector, you can invalidate a
repeating timer when appropriate within that method. In many
situations, however, you also want the option of invalidating the timer—
perhaps even before it starts. In this case, you do need to keep a
reference to the timer, so that you can send it an invalidate message
whenever appropriate. If you create an unscheduled timer (see
“Unscheduled Timers”), then you must maintain a strong reference to the
timer (in a reference-counted environment, you retain it) so that it is not
deallocated before you use it.
挑戰練習

• 倒數計時
• 同時使⽤用多個計時器
• ⾮非固定時間的排程
參考資料補充
• 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)
UIView 基本觀念
Architecture of the Views
UIView 階層
UIView 座標
View Coordinates
CGFloat

CGPoint
   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
                          /
UIView 位置與尺⼨寸
建⽴立 UIView


• 由 Interface Builder 建⽴立
• 由程式產⽣生
  CGRect viewRect = CGRectMake(0, 0, 100, 100);
  UIView* myView = [[UIView alloc] initWithFrame:viewRect];
UIView Properties
•   alpha, hidden, opaque, backgroundColor

•   bounds, frame, center
•   transform
•   autoresizingMask, autoresizesSubviews
•   contentMode, contentStretch, contentScaleFactor
•   gestureRecognizers, userInteractiionEnabled,
    multipleTouchEnabled, exclusiveTouch
•   subviews, drawRect:, layer
UIView tag 屬性


• tag 屬性,為⼀一整數值
• 取得特定物件的⽅方法 viewWithTab:
• 速度快
• 預設 tag 為 0
UIView 增加、刪除與移動
• addSubview:
• insertSubview...
• bringSubviewToFront:
• sendSubviewToBack:
• exchangeSubviewAtIndex:
  withSubviewAtIndex:
• removeFromSuperview
UIView 隱藏
•   常⽤用⽅方法
    •   alpha (0.0 ~ 1.0) (適合⽤用在動畫效果上)
    •   hidden (YES / NO)
•   隱藏的 UIView 物件
    •   不會接受 touch 觸控
    •   仍會隨著畫⾯面階層 autoresizing
    •   ⺫⽬目前為 first responder 的物件不會⾃自動 resign
UIView 待續......


• 動畫效果
• 座標轉換 (平移、旋轉、尺⼨寸)
• 觸控處理
範例:

UIView 的功能操作
Project QV077
UIView 解說⽤用程式
UIView 基本 method
  AddSubview
  RemoveFromSuperview
  BringSubviewToFront
  SendSubviewToBack
  ExchangeSubview.....
@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
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];
}

****** 省略部份程式 ******
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)];
}
範例:

  UIView 的 tag
Project QV030

多個按鈕,都執⾏行同⼀一段
程式,如何知道按下哪⼀一
個按鈕?
利⽤用 UIView 的 tag 屬性
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
- (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];
}
補充

tag 屬性的設定亦可在 xib 檔裡設定


思考問題:按鈕若更多,可以設定按鈕
物件的陣列嗎?
範例:

UISegmentedControl
Project QV069



UISegmentedControl
ViewController.h




#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    IBOutlet UIImageView *imageView;
}

- (IBAction) buttonAction: (UISegmentedControl *) sender;

@end
ViewController.xib
ViewController.m




- (IBAction) buttonAction: (UISegmentedControl *) sender
{
    // 取得按下何鍵
    NSInteger index = sender.selectedSegmentIndex;

    // 指定圖檔名
    NSString *show = [NSString stringWithFormat:@"cat%d.png", index];

    // 顯⽰示圖
    imageView.image = [UIImage imageNamed:show];
}
範例:

  1~9 快速按鍵遊戲
    (陣列的應⽤用)
Project QV078


遊戲程式:數字快按
NSMutableArray......
#import <UIKit/UIKit.h>                         ViewController.h

static 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
ViewController.xib (1/2)




  每個數字按鍵的
 tag 屬性都要設定
ViewController.xib (2/2)




    每個數字按鍵都
   指定到同樣的事件
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 的數字
重建數字排列,指定到各個按鍵                                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 個陣列元素值
}
- (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);
}
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];
        }
    }
}
遊戲時間的計算
- (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];
     }
}
⾃自我練習

 最佳成績的保存...
 將⼀一場遊戲設為連玩三次、九次...
 開始前加⼊入⼀一段倒數計時...
 不⽤用數字,改⽤用英⽂文順序,或是⼀一段
 詩詞句⼦子等...
......

Contenu connexe

Tendances

Result and screen shots
Result and screen shotsResult and screen shots
Result and screen shotsMukesh M
 
Testing in those hard to reach places
Testing in those hard to reach placesTesting in those hard to reach places
Testing in those hard to reach placesdn
 
05 - Qt External Interaction and Graphics
05 - Qt External Interaction and Graphics05 - Qt External Interaction and Graphics
05 - Qt External Interaction and GraphicsAndreas Jakl
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJSSandi Barr
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The LandingHaci Murat Yaman
 
Modern c++ Memory Management
Modern c++ Memory ManagementModern c++ Memory Management
Modern c++ Memory ManagementAlan Uthoff
 
Animation in Java
Animation in JavaAnimation in Java
Animation in JavaAlan Goo
 
C c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoC c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoKim Phillips
 
Js set timeout & setinterval
Js set timeout & setintervalJs set timeout & setinterval
Js set timeout & setintervalARIF MAHMUD RANA
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJSstefanmayer13
 
The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88Mahmoud Samir Fayed
 
NS2: AWK and GNUplot - PArt III
NS2: AWK and GNUplot - PArt IIINS2: AWK and GNUplot - PArt III
NS2: AWK and GNUplot - PArt IIIAjit Nayak
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopSages
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done rightPlatonov Sergey
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simplerAlexander Mostovenko
 

Tendances (20)

Result and screen shots
Result and screen shotsResult and screen shots
Result and screen shots
 
Testing in those hard to reach places
Testing in those hard to reach placesTesting in those hard to reach places
Testing in those hard to reach places
 
Rxjs kyivjs 2015
Rxjs kyivjs 2015Rxjs kyivjs 2015
Rxjs kyivjs 2015
 
05 - Qt External Interaction and Graphics
05 - Qt External Interaction and Graphics05 - Qt External Interaction and Graphics
05 - Qt External Interaction and Graphics
 
Lecture1 classes3
Lecture1 classes3Lecture1 classes3
Lecture1 classes3
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The Landing
 
2 презентация rx java+android
2 презентация rx java+android2 презентация rx java+android
2 презентация rx java+android
 
Predictable Java af Anders P Ravn, CISS og Hans Søndergaard, ViaUC
Predictable Java af Anders P Ravn, CISS og Hans Søndergaard, ViaUCPredictable Java af Anders P Ravn, CISS og Hans Søndergaard, ViaUC
Predictable Java af Anders P Ravn, CISS og Hans Søndergaard, ViaUC
 
Modern c++ Memory Management
Modern c++ Memory ManagementModern c++ Memory Management
Modern c++ Memory Management
 
Animation in Java
Animation in JavaAnimation in Java
Animation in Java
 
C c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoC c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdo
 
Js set timeout & setinterval
Js set timeout & setintervalJs set timeout & setinterval
Js set timeout & setinterval
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 
The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88
 
NS2: AWK and GNUplot - PArt III
NS2: AWK and GNUplot - PArt IIINS2: AWK and GNUplot - PArt III
NS2: AWK and GNUplot - PArt III
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done right
 
Tracing and awk in ns2
Tracing and awk in ns2Tracing and awk in ns2
Tracing and awk in ns2
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simpler
 

En vedette (14)

I os 03
I os 03I os 03
I os 03
 
I os 16
I os 16I os 16
I os 16
 
I os 15
I os 15I os 15
I os 15
 
I os 04
I os 04I os 04
I os 04
 
I os 08
I os 08I os 08
I os 08
 
I os 09
I os 09I os 09
I os 09
 
I os 02
I os 02I os 02
I os 02
 
I os 11
I os 11I os 11
I os 11
 
I os 05
I os 05I os 05
I os 05
 
課程規畫
課程規畫課程規畫
課程規畫
 
I os 07
I os 07I os 07
I os 07
 
I os 14
I os 14I os 14
I os 14
 
I os 10
I os 10I os 10
I os 10
 
I os 13
I os 13I os 13
I os 13
 

Similaire à I os 06

Timers in Unix/Linux
Timers in Unix/LinuxTimers in Unix/Linux
Timers in Unix/Linuxgeeksrik
 
Military time and Standard time, JavaOne of the assignments given .pdf
Military time and Standard time, JavaOne of the assignments given .pdfMilitary time and Standard time, JavaOne of the assignments given .pdf
Military time and Standard time, JavaOne of the assignments given .pdfmarketing413921
 
lecture10.ppt fir class ibect fir c++ fr opps
lecture10.ppt fir class ibect fir c++ fr oppslecture10.ppt fir class ibect fir c++ fr opps
lecture10.ppt fir class ibect fir c++ fr oppsmanomkpsg
 
倒计时优化点滴
倒计时优化点滴倒计时优化点滴
倒计时优化点滴j5726
 
Modify the Time classattached to be able to work with Date.pdf
Modify the Time classattached to be able to work with Date.pdfModify the Time classattached to be able to work with Date.pdf
Modify the Time classattached to be able to work with Date.pdfaaseletronics2013
 
How to Create a Countdown Timer in Python.pdf
How to Create a Countdown Timer in Python.pdfHow to Create a Countdown Timer in Python.pdf
How to Create a Countdown Timer in Python.pdfabhishekdf3
 
JAVA.Q4 Create a Time class. This class will represent a point in.pdf
JAVA.Q4 Create a Time class. This class will represent a point in.pdfJAVA.Q4 Create a Time class. This class will represent a point in.pdf
JAVA.Q4 Create a Time class. This class will represent a point in.pdfkarymadelaneyrenne19
 
import java.awt.; import java.awt.event.; import javax.swing..pdf
import java.awt.; import java.awt.event.; import javax.swing..pdfimport java.awt.; import java.awt.event.; import javax.swing..pdf
import java.awt.; import java.awt.event.; import javax.swing..pdfaparnawatchcompany
 
Csphtp1 08
Csphtp1 08Csphtp1 08
Csphtp1 08HUST
 
Advanced patterns in asynchronous programming
Advanced patterns in asynchronous programmingAdvanced patterns in asynchronous programming
Advanced patterns in asynchronous programmingMichael Arenzon
 
JSR 310. New Date API in Java 8
JSR 310. New Date API in Java 8JSR 310. New Date API in Java 8
JSR 310. New Date API in Java 8Serhii Kartashov
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...DroidConTLV
 
Implement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create eventsImplement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create eventsKaty Slemon
 
iOS Effective Coding: Run Loops & UI
iOS Effective Coding: Run Loops & UIiOS Effective Coding: Run Loops & UI
iOS Effective Coding: Run Loops & UIJ.M. Schaeffer
 
Cassandra 3.0 Awesomeness
Cassandra 3.0 AwesomenessCassandra 3.0 Awesomeness
Cassandra 3.0 AwesomenessJon Haddad
 

Similaire à I os 06 (20)

Timers in Unix/Linux
Timers in Unix/LinuxTimers in Unix/Linux
Timers in Unix/Linux
 
Military time and Standard time, JavaOne of the assignments given .pdf
Military time and Standard time, JavaOne of the assignments given .pdfMilitary time and Standard time, JavaOne of the assignments given .pdf
Military time and Standard time, JavaOne of the assignments given .pdf
 
lecture10.ppt
lecture10.pptlecture10.ppt
lecture10.ppt
 
lecture10.ppt
lecture10.pptlecture10.ppt
lecture10.ppt
 
lecture10.ppt fir class ibect fir c++ fr opps
lecture10.ppt fir class ibect fir c++ fr oppslecture10.ppt fir class ibect fir c++ fr opps
lecture10.ppt fir class ibect fir c++ fr opps
 
倒计时优化点滴
倒计时优化点滴倒计时优化点滴
倒计时优化点滴
 
Modify the Time classattached to be able to work with Date.pdf
Modify the Time classattached to be able to work with Date.pdfModify the Time classattached to be able to work with Date.pdf
Modify the Time classattached to be able to work with Date.pdf
 
How to Create a Countdown Timer in Python.pdf
How to Create a Countdown Timer in Python.pdfHow to Create a Countdown Timer in Python.pdf
How to Create a Countdown Timer in Python.pdf
 
Ping to Pong
Ping to PongPing to Pong
Ping to Pong
 
Timer Interceptor in Mule part 2
Timer Interceptor in Mule part 2Timer Interceptor in Mule part 2
Timer Interceptor in Mule part 2
 
JAVA.Q4 Create a Time class. This class will represent a point in.pdf
JAVA.Q4 Create a Time class. This class will represent a point in.pdfJAVA.Q4 Create a Time class. This class will represent a point in.pdf
JAVA.Q4 Create a Time class. This class will represent a point in.pdf
 
import java.awt.; import java.awt.event.; import javax.swing..pdf
import java.awt.; import java.awt.event.; import javax.swing..pdfimport java.awt.; import java.awt.event.; import javax.swing..pdf
import java.awt.; import java.awt.event.; import javax.swing..pdf
 
Csphtp1 08
Csphtp1 08Csphtp1 08
Csphtp1 08
 
Advanced patterns in asynchronous programming
Advanced patterns in asynchronous programmingAdvanced patterns in asynchronous programming
Advanced patterns in asynchronous programming
 
JSR 310. New Date API in Java 8
JSR 310. New Date API in Java 8JSR 310. New Date API in Java 8
JSR 310. New Date API in Java 8
 
Lab 1 izz
Lab 1 izzLab 1 izz
Lab 1 izz
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
 
Implement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create eventsImplement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create events
 
iOS Effective Coding: Run Loops & UI
iOS Effective Coding: Run Loops & UIiOS Effective Coding: Run Loops & UI
iOS Effective Coding: Run Loops & UI
 
Cassandra 3.0 Awesomeness
Cassandra 3.0 AwesomenessCassandra 3.0 Awesomeness
Cassandra 3.0 Awesomeness
 

Plus de 信嘉 陳

Plus de 信嘉 陳 (13)

Processing 06
Processing 06Processing 06
Processing 06
 
Processing 05
Processing 05Processing 05
Processing 05
 
Processing 04
Processing 04Processing 04
Processing 04
 
Processing 03
Processing 03Processing 03
Processing 03
 
Processing 02
Processing 02Processing 02
Processing 02
 
Processing 01
Processing 01Processing 01
Processing 01
 
Processing 09
Processing 09Processing 09
Processing 09
 
Processing 08
Processing 08Processing 08
Processing 08
 
Processing 07
Processing 07Processing 07
Processing 07
 
I os 01
I os 01I os 01
I os 01
 
Google 街景
Google 街景Google 街景
Google 街景
 
社群網站 Facebook
社群網站 Facebook社群網站 Facebook
社群網站 Facebook
 
網路搜尋
網路搜尋網路搜尋
網路搜尋
 

I os 06

  • 2. 內容⼤大綱 • 時間控制 Timer • QV063:基本的 Timer 應⽤用 (⼩小時鐘) • QV064:指定 Timer 物件 (碼錶控制) • QV065:精確的時間計算 (碼錶) • UIView 物件 • QV077:UIView 的操作⽅方法 • QV030:UIView 的 tag 屬性⽤用法 • QV069:UISegmented Control • NSMutableArray 陣列 • QV078:數字快按遊戲
  • 4. NSTimer 使⽤用時機 • 強迫隔⼀一段時間後再執⾏行某段程式 • 間隔⼀一段時間重覆執⾏行某段程式 • 遊戲程式主迴圈內經常使⽤用
  • 5. NSTimer 原理 (1) • Cocoa Touch 的 Foundation 框架內的類別 • 與 NSRunLoop (主要執⾏行迴圈) 配合來處 理定時和排程⼯工作 • 可直接使⽤用主執⾏行緒的 run loop,也能 ⼿手動執⾏行其他⾮非主執⾏行緒的 run loop
  • 6. NSTimer 原理 (2) • 計時器並⾮非即時的機制,是在 run loop 運作且被觸發的時間到了,才會被觸發 • 設定的時間『不是固定保証會執⾏行』, ⽽而是『最⼩小的間隔時間』,或是『最早 的觸發時間』
  • 7. NSTimer 觸發誤差 (1) 在這之前 run loop 不會檢視,所以不 可能觸發 50~100 毫秒 延後誤差 預計觸發時間 實際觸發時間
  • 8. NSTimer 觸發誤差 (2) 預計 預計 預計 開始計時 第⼀一次觸發 第⼆二次觸發 第三次觸發 預計觸發時間 不受前次的影 實際觸發 實際觸發 (第⼀一次) (第⼆二次) 第⼆二次觸發時間超過 第三次預計觸發時間 (不會重覆兩次)
  • 9. NSTimer 使⽤用 • 很簡單,只要指定 • 間隔的時間 (秒) • 要執⾏行的函式 (target, method, selector) • 是否要重覆 (repeat) • (進階) 傳遞⼀一些資料給 Timer 函式 • 可直接引⽤用,可以不⽤用移除 • 可指定多個計時器
  • 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; } }
  • 12. Project QV063 使⽤用 NSTimer ⽏毋需宣告 NSTimer 物件 ⼩小時鐘:顯⽰示現在⽇日期時間 簡易碼錶計次
  • 13. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController { IBOutlet UILabel *myLabel1, *myLabel2, *myLabel3; int count; } @end
  • 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. 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. 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; }
  • 19. Project QV064 碼錶計時的功能 暫時採⽤用 count 次數累加的 ⽅方式,準度會有問題 按鍵具有不同功能的切換 (暫停及繼續)
  • 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
  • 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. 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]; } }
  • 27. TimerElapsed.h TimerElapsed 類別宣告 #import <Foundation/Foundation.h> @interface TimerElapsed : NSObject { NSDate *begin; NSDate *end; } - (void) beginPoint; - (void) endPoint; - (double) timeElapsedInMilliseconds; - (double) timeElapsedInSeconds; - (double) timeElapsedInMinutes; @end
  • 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. 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. TimeElapsed 類別的 method - (void) beginPoint (設定計時開始點) - (void) endPoint (設定計時結束點) - (double) timeElapsedInSeconds (傳回兩個時間點間之時間,單位為秒) - (double) timeElapsedInMilliseconds (傳回兩個時間點間之時間,單位為毫秒) - (double) timeElapsedInMinutes (傳回兩個時間點間之時間,單位為分)
  • 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. 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
  • 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. 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 memory management there's typically no need to keep a reference to a timer after you’ve scheduled it. Since the timer is passed as an argument when you specify its method as a selector, you can invalidate a repeating timer when appropriate within that method. In many situations, however, you also want the option of invalidating the timer— perhaps even before it starts. In this case, you do need to keep a reference to the timer, so that you can send it an invalidate message whenever appropriate. If you create an unscheduled timer (see “Unscheduled Timers”), then you must maintain a strong reference to the timer (in a reference-counted environment, you retain it) so that it is not deallocated before you use it.
  • 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)
  • 42. View Coordinates CGFloat CGPoint 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 /
  • 44. 建⽴立 UIView • 由 Interface Builder 建⽴立 • 由程式產⽣生 CGRect viewRect = CGRectMake(0, 0, 100, 100); UIView* myView = [[UIView alloc] initWithFrame:viewRect];
  • 45. UIView Properties • alpha, hidden, opaque, backgroundColor • bounds, frame, center • transform • autoresizingMask, autoresizesSubviews • contentMode, contentStretch, contentScaleFactor • gestureRecognizers, userInteractiionEnabled, multipleTouchEnabled, exclusiveTouch • subviews, drawRect:, layer
  • 46. UIView tag 屬性 • tag 屬性,為⼀一整數值 • 取得特定物件的⽅方法 viewWithTab: • 速度快 • 預設 tag 為 0
  • 47. UIView 增加、刪除與移動 • addSubview: • insertSubview... • bringSubviewToFront: • sendSubviewToBack: • exchangeSubviewAtIndex: withSubviewAtIndex: • removeFromSuperview
  • 48. UIView 隱藏 • 常⽤用⽅方法 • alpha (0.0 ~ 1.0) (適合⽤用在動畫效果上) • hidden (YES / NO) • 隱藏的 UIView 物件 • 不會接受 touch 觸控 • 仍會隨著畫⾯面階層 autoresizing • ⺫⽬目前為 first responder 的物件不會⾃自動 resign
  • 49. UIView 待續...... • 動畫效果 • 座標轉換 (平移、旋轉、尺⼨寸) • 觸控處理
  • 51. Project QV077 UIView 解說⽤用程式 UIView 基本 method AddSubview RemoveFromSuperview BringSubviewToFront SendSubviewToBack ExchangeSubview.....
  • 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. 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. 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. 範例: UIView 的 tag
  • 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. - (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. 補充 tag 屬性的設定亦可在 xib 檔裡設定 思考問題:按鈕若更多,可以設定按鈕 物件的陣列嗎?
  • 62. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController { IBOutlet UIImageView *imageView; } - (IBAction) buttonAction: (UISegmentedControl *) sender; @end
  • 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. 範例: 1~9 快速按鍵遊戲 (陣列的應⽤用)
  • 67. #import <UIKit/UIKit.h> ViewController.h static 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. ViewController.xib (1/2) 每個數字按鍵的 tag 屬性都要設定
  • 69. ViewController.xib (2/2) 每個數字按鍵都 指定到同樣的事件
  • 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. 重建數字排列,指定到各個按鍵 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. - (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. 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. 遊戲時間的計算 - (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. ⾃自我練習 最佳成績的保存... 將⼀一場遊戲設為連玩三次、九次... 開始前加⼊入⼀一段倒數計時... 不⽤用數字,改⽤用英⽂文順序,或是⼀一段 詩詞句⼦子等...