SlideShare a Scribd company logo
Class 04
iOS 應⽤用軟體設計
內容⼤大綱
•   Objective-C 陣列 (NSArray, NSMutableArray)
    •   QV008:陣列圖⽚片變換動畫

•   UIPickerView 與 Delegate 代理⽅方法

    •   QV009:以程式⽅方式產⽣生
    •   QV010:基本,以 xib ⽅方式使⽤用

    •   QV011:UIPickerView + UIDatePicker
    •   QV012:UIPickerView 多個區段選擇

•   其他 UIPickerView 特殊技巧與範例

    •   QV105:相依關聯的 Picker
    •   QV106:頭尾相連的 Picker

    •   QV107:吃⾓角⼦子⽼老⻁虎
    •   Samples:Pickers Demo
陣列類別
NSArray
NSArray (1/2)
•   可以把任何物件當做元素置⼊入

•   可依照順序存取
•   可直接存取指定位置元素
•   索引由 0 開始

•   元素裡可以混合相異的類別實體
•   可以多次含有相同的物件

•   不可以把 nil 做為元素
NSArray (2/2)

• NSArray 的實體產⽣生後......
 • 物件不可變更
 • 不可追加新物件
 • 不可刪除元素
(1) 陣列物件的初始化及產⽣生

•   -(id) array
•   -(id) arrayWithObject: (id) anObject
•   -(id) initWithObjects: (id) firstObj, ......
•   -(id) initWithObjects: (id *) objects count:
    (NSInteger) count
•   -(id) initWithArray: (NSArray *) anArray
•   -(id) initWithArray: (NSArray *) array copyItems:
    (BOOL) flag
(2) 陣列物件的存取

• -(NSUinteger) count
• -(NSUinteger) indexOfObject: (id)anObject
• -(id) objectAtIndex: (NSUInteger) index
• -(id) lastObject
• -(void) getObjects: (id) aBuffer
• -(NSArray *) subarrayWithRange: (NSRange)
  range
(3) ⽐比較



• -(BOOL) isEqualToArray: (id)anObject
• -(id) firstObjectCommonWithArray:
  (NSArray *) otherArray
(4) 增加新元素


• -(NSArray *) arrayByAddingObject:
  (id)anObject
• -(NSArray *)
  arrayByAddingObjectsFromArray:
  (NSArray *)anArray
(5) 排序


• -(NSArray *) sortedArrayUsingSelector:
  (SEL) comparator
• -(NSArray *) sortedArrayUsingFunction:
  (NSInteger (*)(id,id,void*)) comparator
  context: (void *)context
(6) 對元素的訊息傳送



• -(void) makeObjectsPerform:
  (SEL)aSelector
• -(void) makeObjectsPerform: (SEL)
  aSelector withObject: (id) anObj
(7) 字串元素的操作



• - (NSString *) componentsJoineByString:
  (NSString *) separator
• - (NSArray *) pathsMatchingExtensions:
  (NSArray *) filterTypes
(8) 檔案的輸出與輸⼊入


• -(NSString *) description
• -(id) initWithContentsOfFile: (NSString
  *)aPath
• -(BOOL) writeToFile: (NSString *) path
  atomically:(BOOL)flag
陣列類別
NSMutableArray
NSMutableArray
• 可變的陣列類別
• NSMutableArray 為 NSArray 的⼦子類別
 (可以使⽤用 NSArray 的所有⽅方法)

• 可以插⼊入新物件
• 可以前後移動元素物件
• 可以刪除物件 (不會有空格產⽣生)
(1) 陣列物件的初始化




• -(id) initWithCapacity: (NSUInteger)
  numItems
(2) 陣列的追加與置換

•   -(void) addObject: (id)anObject
•   -(void) addObjecsFromArray:
     (NSArray *)otherArray
•   -(void) insertObject: (id)anObject atIndex:(NSUInteger)
    index
•   -(void) replaceObjectAtIndex: (NSUInteger)index
    withObject:(id)anObject
•   -(void) setArray: (NSArray *)otherArray
•   -(void) exchangeObjectAtIndex: (NSUinteger)idx1
    withObjectAtIndex:(NSUInteger) idx2
(3) 物件的刪除

•   -(void) removeAllObjects

•   -(void) removeLastObject
•   -(void) removeObjectAtIndex: (NSUInteger)index
•   -(void) removeObjectsInRange: (NSRange)aRange
•   -(void) removeObject: (id)anObject
•   -(void) removeObjectsInArray:
    (NSArray *)otherArray
(4) 排序



• -(void) sortUsingSelector: (SEL)comparator
• -(void) sortUsingFunction:(NSInteger (*)
  (idid,void *))compare
  context:(void *)context
陣列快速列舉

• id obj;
  for (obj in group)
  {
    ...........
  }
列舉⼦子 NSEnumerator
•   對被存放在陣列、集合、字典等集合中的元素物
    件,可以依序存取的系統
•   Objective-C 2.0 後多被 for ...in 取代
•   ⽅方法......
    •   -(id) nextObject
    •   -(NSArray *) allObjects
    •   -(NSEnumerator *) objectEnumerator
    •   -(NSEnumerator *) reverseObjectEnumerator
範例:

連續圖⽚片呈現的動畫
Project QV008


UIImageView 的圖⽚片連
續動畫
I os 04
ViewController.m
- (void)viewDidLoad
{
    [super viewDidLoad];

    NSArray *myImages = [NSArray arrayWithObjects:
                         [UIImage imageNamed:@"01.jpg"],
                         [UIImage imageNamed:@"02.jpg"],
                         [UIImage imageNamed:@"03.jpg"],
                                                           ⽤用陣列定義
                         [UIImage imageNamed:@"04.jpg"],   多個圖檔
                         [UIImage imageNamed:@"05.jpg"],
                         [UIImage imageNamed:@"06.jpg"],
                         nil];

    UIImageView *myAnimatedView = [[UIImageView alloc]
                   initWithFrame:CGRectMake(90, 100, 140, 140)];

    myAnimatedView.animationImages = myImages;
    myAnimatedView.animationDuration = 3.0;
    myAnimatedView.animationRepeatCount = 0;
    [myAnimatedView startAnimating];
                                                           動畫設定
    [self.view addSubview:myAnimatedView];
}
UIPickerView
UIPickerView 挑選器

• 提供⼀一份清單給使⽤用者選擇
• Picker 本⾝身不會保存任何資料
 (需要⾃自⾏行建⽴立 NSArray 來保留資料)

• 它會呼叫 DataSource 和 Delegate 的⽅方法
 以取得要顯⽰示的資料
• UIPickerViewDataSource


• UIPickerViewDelegate
範例:

QV009:UIPickerView 顯⽰示資料 (code)
QV010:UIPickerView 顯⽰示資料 (xib)
QV011:⽐比較 UIPickerView 及 UIDatePicker
QV012:UIPickerView 多區段處理
Project QV009

以程式⽅方式產⽣生
UIPickerView
陣列指定
Objective-C 的協定
  UIPickerViewDelegate
  UIPickerViewDataSource
ViewController.h



#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
   <UIPickerViewDelegate, UIPickerViewDataSource>
{
    UIPickerView *myPickerView;
    NSArray *dataArray;                  使⽤用兩個協定
}

@property (retain, nonatomic) UIPickerView *myPickerView;
@property (retain, nonatomic) NSArray *dataArray;

@end
#import "ViewController.h"
                                                  ViewController.m (1/2)
@implementation ViewController
@synthesize myPickerView, dataArray;

- (void)viewDidLoad
{                                          寬度可調,但⾼高度固定
    [super viewDidLoad];

    myPickerView = [[UIPickerView alloc]
                        initWithFrame:CGRectMake(0, 0, 320, 240)];

    myPickerView.dataSource = self;                    物件的代理⼈人
    myPickerView.delegate = self;

    myPickerView.showsSelectionIndicator = YES;           其他屬性
    // 決定清單陣列
    NSArray *listArray = [[NSArray alloc] initWithObjects:
       @"AAAAA", @"BBBBB", @"CCCCC", @"DDDDD", @"EEEEE", @"FFFFF", nil];

    self.dataArray = listArray;

    [self.view addSubview:myPickerView];
}
                                                   項⺫⽬目清單另外存放
****** 省略部分程式 ******
@end
ViewController.m (2/2)


-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;                                共有幾個區段
}

-(NSInteger)pickerView:(UIPickerView *)pickView numberOfRowsInComponent:
(NSInteger)component
{
    return [dataArray count];               在區段內有幾個項⺫⽬目
}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
    // 此處尚無處理選取後的動作
}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:
(NSInteger)row forComponent:(NSInteger)component
{
    return [dataArray objectAtIndex:row];           各個項⺫⽬目的⽂文字
}
Project QV010


UIPickerView
改為 xib 顯⽰示畫⾯面
ViewController.xib




   連結線拉到
  File's Owner
ViewController.h



#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
<UIPickerViewDelegate, UIPickerViewDataSource>
{
    IBOutlet UIPickerView *myPickerView;
    NSArray *dataArray;
}

@property(retain, nonatomic) IBOutlet UIPickerView *myPickerView;
@property(retain, nonatomic) NSArray *dataArray;

@end
ViewController.m


#import "ViewController.h"

@implementation ViewController
@synthesize myPickerView, dataArray;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.dataArray = [[NSArray alloc] initWithObjects:
              @"AAAAA", @"BBBBBB", @"CCCCC",
              @"DDDDD", @"EEEEE" , @"FFFFF", nil];
}

****** 省略部分程式 ******
Project QV011

 UIPickerView
 UIDatePicker
 處理選取結果。⽐比較兩種
 Picker 的處理⽅方式
 (Delegate, Action)
ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIPickerViewDelegate,
UIPickerViewDataSource>
{
    IBOutlet UILabel *message;
    IBOutlet UIPickerView *myPickerView;
    IBOutlet UIDatePicker *myDatePicker;
    NSArray *dataArray;
}

@property   (retain,   nonatomic)   IBOutlet UILabel *message;
@property   (retain,   nonatomic)   IBOutlet UIPickerView *myPickerView;
@property   (retain,   nonatomic)   IBOutlet UIDatePicker *myDatePicker;
@property   (retain,   nonatomic)   NSArray *dataArray;

-(IBAction)dateSelect:(id)sender;

@end
ViewController.m

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

-(NSInteger)pickerView: (UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
{
    return [dataArray count];
}

-(void)pickerView: (UIPickerView *) pickerView didSelectRow:
(NSInteger)row inComponent:(NSInteger)component
{
    NSInteger r = [myPickerView selectedRowInComponent:component];
    NSString *item = [dataArray objectAtIndex:row];

    message.text = [NSString stringWithFormat:
                        @"%d, %d : %@", component,    r, item];
}

-(NSString *)pickerView: (UIPickerView *)pickerView titleForRow:
(NSInteger)row forComponent:(NSInteger)component
{
    return [dataArray objectAtIndex:row];
}
ViewController.xib




 UIDatePicker
使⽤用Action的⽅方式
ViewController.m




-(IBAction)dateSelect:(id)sender
{
    NSDate *selected = [myDatePicker date];
    NSString *str = [[NSString alloc] initWithFormat:@"%@", selected];

    message.text = str;
}
Project QV012


 UIPickerView
 多個區段資料的處理
ViewController.h


#import <UIKit/UIKit.h>


@interface ViewController : UIViewController
<UIPickerViewDelegate, UIPickerViewDataSource>
{
    IBOutlet UILabel *message;
    IBOutlet UIPickerView *myPickerView;
    NSArray *dataArray1, *dataArray2;
}

@property (retain, nonatomic) IBOutlet UILabel *message;
@property (retain, nonatomic) IBOutlet UIPickerView *myPickerView;
@property (retain, nonatomic) NSArray *dataArray1, *dataArray2;

@end
ViewController.m (1/3)



#import "ViewController.h"

@implementation ViewController
@synthesize message, myPickerView, dataArray1, dataArray2;

- (void)viewDidLoad
{
    [super viewDidLoad];
!
    myPickerView.dataSource = self;
    myPickerView.delegate = self;

    dataArray1 = [[NSArray alloc]
            initWithObjects:@"AAA", @"BBB", @"CCC", @"DDD", nil];

    dataArray2 = [[NSArray alloc]
            initWithObjects:@"111", @"222", @"333", @"444", @"555", nil];
}
ViewController.m (2/3)

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{!
! return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:
(NSInteger)component
{!
    if (component==0)
    { return [dataArray1 count]; }
    else
    { return [dataArray2 count]; }
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:
(NSInteger)row forComponent:(NSInteger)component
{
    if(component==0)
    {
        return [dataArray1 objectAtIndex:row];
    }
    else
    {
        return [dataArray2 objectAtIndex:row];
    }
}
ViewController.m (3/3)




- (void)pickerView: (UIPickerView *) pickerView
     didSelectRow:(NSInteger)row
     inComponent:(NSInteger)component
{!
    NSInteger n1 = [myPickerView selectedRowInComponent:0];
    NSInteger n2 = [myPickerView selectedRowInComponent:1];

    NSString *str1 = [dataArray1 objectAtIndex:n1];
    NSString *str2 = [dataArray2 objectAtIndex:n2];

    NSString *str = [[NSString alloc]
               initWithFormat:@"%@ -- %@", str1, str2];
    message.text = str;
}
範例:

   區段間有相依關聯
(左邊的改變會重設右邊的項⺫⽬目)
Project QV105


製作有相依關聯的 Picker
利⽤用 NSDictionary 存放資料
#import <UIKit/UIKit.h>                  ViewController.h
@interface ViewController :
UIViewController<UIPickerViewDelegate>
{
    NSMutableDictionary *data;
    NSArray *keys;
                                           ViewController.xib
    IBOutlet UIPickerView *picker;
    IBOutlet UILabel *label;
}
@end
ViewController.m (1/4)



- (void)viewDidLoad
{
    [super viewDidLoad];

    [self prepareData];
}

- (void) prepareData
{
    data = [[NSMutableDictionary alloc] init];
    [data setValue:[NSArray arrayWithObjects:
                   @"可樂",@"沙⼠士",@"果汁",@"其他",nil] forKey:@"飲料"];
    [data setValue:[NSArray arrayWithObjects:
                   @"蛋糕",@"糖果",@"巧克⼒力",@"其他",nil] forKey:@"甜點"];
    keys =[[data allKeys] sortedArrayUsingComparator:
           (NSComparator)^(id obj1,id obj2)
           {
               return [obj1 caseInsensitiveCompare:obj2];
           }];
}
ViewController.m (3/4)



//設定滾輪總共有幾個欄位
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView
{
    return 2;
}

//設定滾輪總共有幾個項⺫⽬目
- (NSInteger)pickerView:(UIPickerView *)thePickerView
numberOfRowsInComponent:(NSInteger)component
{
    if (component==0)
    {
        return [keys count];
    }
    else
    {
        NSString *key = [keys objectAtIndex:
                 [thePickerView selectedRowInComponent:0]]; // 飲料或甜點
        NSArray *array = [data objectForKey:key];
        return [array count];
    }
}
ViewController.m (3/4)




//設定滾輪顯⽰示的⽂文字
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:
(NSInteger)row forComponent:(NSInteger)component
{
    if (component==0)
    {
        return[keys objectAtIndex:row];
    }
    else
    {
        NSString *key = [keys objectAtIndex:
                 [thePickerView selectedRowInComponent:0]]; // 飲料或甜點
        NSArray *array = [data objectForKey:key];
        return [array objectAtIndex:row];
    }
}
ViewController.m (4/4)




//設定滾輪顯⽰示的⽂文字
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:
(NSInteger)row forComponent:(NSInteger)component
{
    if (component==0)
    {
        return[keys objectAtIndex:row];
    }
    else
    {
        NSString *key = [keys objectAtIndex:
                [thePickerView selectedRowInComponent:0]]; // 飲料或甜點
        NSArray *array = [data objectForKey:key];
        return [array objectAtIndex:row];
    }
}
範例:

頭尾連續的選擇器
Project QV106
製作頭尾相接的滾輪選擇器
UIPickerView
採⽤用技巧
   假設項⺫⽬目⾮非常多,每次滾
   動時計算該顯⽰示的資料
   滾動結束時,重新移到中
   間相對應的位置
ViewController.m (1/2)


const int MAX_ROLL = 1000;

                                   宣告⼀一個很⼤大的數
- (void)viewDidLoad
{                                    形同有這麼多項
    [super viewDidLoad];

    list = [NSArray arrayWithObjects:@"AAA", @"BBB", @"CCC", @"DDD",
                             @"EEE", @"FFF", @"GGG", @"HHH", @"III",
                             @"JJJ", @"KKK", @"LLL", nil];

    [self pickerViewReLoad];
}

- (NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}

-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:
(NSInteger)component
{
    return MAX_ROLL;
}
ViewController.m (1/2)


                                           計算相對應的元素位置

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:
(NSInteger)row forComponent:(NSInteger)component
{
    return [list objectAtIndex:(row%[list count])];
}

-(void) pickerView:(UIPickerView *)pickerView didSelectRow:
(NSInteger)row inComponent:(NSInteger)component
{
    [self pickerViewReLoad];                        重新移到中間但
}
                                                    相對應元素位置
-(void) pickerViewReLoad
{
    NSUInteger max = MAX_ROLL;
    NSUInteger base = (max/2) - (max/2)%[list count];
    [myPickerView selectRow:[myPickerView
                selectedRowInComponent:0]%[list count]+base
                           inComponent:0 animated:NO];
}
範例:

吃⾓角⼦子⽼老⻁虎
Project QV107


 以圖⽚片做為 UIPickerView
 的內容
 吃⾓角⼦子⽼老⻁虎
ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
<UIPickerViewDelegate, UIPickerViewDataSource>
{
    IBOutlet UIPickerView *pickerView;
    IBOutlet UILabel *statusLabel;

    NSArray *column1;
    NSArray *column2;
    NSArray *column3;

    UIButton *spinButton;
}
@property (nonatomic, retain) IBOutlet UIPickerView *pickerView;
@property (nonatomic, retain) IBOutlet UILabel *statusLabel;
@property (nonatomic, retain) NSArray *column1, *column2,
*column3;

- (IBAction) spin:(id)sender;

@end
ViewController.m (1/3)
- (void)viewDidLoad
{
    [super viewDidLoad];

    UIImage   *img1   =   [UIImage   imageNamed:@"32_Twitter.png"];
    UIImage   *img2   =   [UIImage   imageNamed:@"32_Elephant.png"];
    UIImage   *img3   =   [UIImage   imageNamed:@"32_Babelfish.png"];
    UIImage   *img4   =   [UIImage   imageNamed:@"32_Panda.png"];
    UIImage   *img5   =   [UIImage   imageNamed:@"32_Penguin.png"];
    UIImage   *img6   =   [UIImage   imageNamed:@"32_Duckling.png"];

    for (int i=1; i<=3; i++)
    {
        UIImageView *imgView1         =   [[UIImageView   alloc]   initWithImage:img1];
        UIImageView *imgView2         =   [[UIImageView   alloc]   initWithImage:img2];
        UIImageView *imgView3         =   [[UIImageView   alloc]   initWithImage:img3];
        UIImageView *imgView4         =   [[UIImageView   alloc]   initWithImage:img4];
        UIImageView *imgView5         =   [[UIImageView   alloc]   initWithImage:img5];
        UIImageView *imgView6         =   [[UIImageView   alloc]   initWithImage:img6];

        NSArray *array = [[NSArray alloc] initWithObjects:
        imgView1, imgView2, imgView3, imgView4, imgView5, imgView6, nil];

        NSString *aryName = [[NSString alloc] initWithFormat:@"column%d", i];
        [self setValue:array forKey:aryName];
    }
}                                                             Picker 內的資料為圖
-(IBAction) spin:(id)sender
                                                        ViewController.m (2/3)
{
    BOOL win = NO;
    int numInRow = 1;
    int lastValue = -1;
                                             重新指定 Picker 內指到的位置
    for(int i=0; i<3; i++)
    {
        int newValue = arc4random() % [self.column1 count];
        numInRow = (newValue==lastValue) ? (numInRow+1) : 1;
        lastValue = newValue;

        [pickerView selectRow:newValue inComponent:i animated:YES];
        [pickerView reloadComponent:i];

        if(numInRow>=2)
        {
            win = YES;
        }                           "連續" 兩個相同的為贏
    }
    statusLabel.hidden = YES;
    spinButton.hidden = YES;
    if(win)
    {
         [self performSelector:@selector(playerWin) withObject:nil afterDelay:0.5];
    }
    else
    {
         [self performSelector:@selector(showButton) withObject:nil afterDelay:0.5];
    }
    statusLabel.text = @"LOSE....";
}
ViewController.m (3/3)



#pragma mark - UIPickerView Delegate

-(NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 3;
}

-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:
(NSInteger)component
{
    return [self.column1 count];
}

-(UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row
forComponent:(NSInteger)component reusingView:(UIView *)view
{
    NSString *arrayName = [NSString stringWithFormat:@"column%d", component+1];
    NSArray *array = [self valueForKey:arrayName];
    return [array objectAtIndex:row];
}
範例觀摩:
  PickersDemo
(綜合多種 Picker 的⽰示範)
I os 04
......

More Related Content

I os 04

  • 2. 內容⼤大綱 • Objective-C 陣列 (NSArray, NSMutableArray) • QV008:陣列圖⽚片變換動畫 • UIPickerView 與 Delegate 代理⽅方法 • QV009:以程式⽅方式產⽣生 • QV010:基本,以 xib ⽅方式使⽤用 • QV011:UIPickerView + UIDatePicker • QV012:UIPickerView 多個區段選擇 • 其他 UIPickerView 特殊技巧與範例 • QV105:相依關聯的 Picker • QV106:頭尾相連的 Picker • QV107:吃⾓角⼦子⽼老⻁虎 • Samples:Pickers Demo
  • 4. NSArray (1/2) • 可以把任何物件當做元素置⼊入 • 可依照順序存取 • 可直接存取指定位置元素 • 索引由 0 開始 • 元素裡可以混合相異的類別實體 • 可以多次含有相同的物件 • 不可以把 nil 做為元素
  • 5. NSArray (2/2) • NSArray 的實體產⽣生後...... • 物件不可變更 • 不可追加新物件 • 不可刪除元素
  • 6. (1) 陣列物件的初始化及產⽣生 • -(id) array • -(id) arrayWithObject: (id) anObject • -(id) initWithObjects: (id) firstObj, ...... • -(id) initWithObjects: (id *) objects count: (NSInteger) count • -(id) initWithArray: (NSArray *) anArray • -(id) initWithArray: (NSArray *) array copyItems: (BOOL) flag
  • 7. (2) 陣列物件的存取 • -(NSUinteger) count • -(NSUinteger) indexOfObject: (id)anObject • -(id) objectAtIndex: (NSUInteger) index • -(id) lastObject • -(void) getObjects: (id) aBuffer • -(NSArray *) subarrayWithRange: (NSRange) range
  • 8. (3) ⽐比較 • -(BOOL) isEqualToArray: (id)anObject • -(id) firstObjectCommonWithArray: (NSArray *) otherArray
  • 9. (4) 增加新元素 • -(NSArray *) arrayByAddingObject: (id)anObject • -(NSArray *) arrayByAddingObjectsFromArray: (NSArray *)anArray
  • 10. (5) 排序 • -(NSArray *) sortedArrayUsingSelector: (SEL) comparator • -(NSArray *) sortedArrayUsingFunction: (NSInteger (*)(id,id,void*)) comparator context: (void *)context
  • 11. (6) 對元素的訊息傳送 • -(void) makeObjectsPerform: (SEL)aSelector • -(void) makeObjectsPerform: (SEL) aSelector withObject: (id) anObj
  • 12. (7) 字串元素的操作 • - (NSString *) componentsJoineByString: (NSString *) separator • - (NSArray *) pathsMatchingExtensions: (NSArray *) filterTypes
  • 13. (8) 檔案的輸出與輸⼊入 • -(NSString *) description • -(id) initWithContentsOfFile: (NSString *)aPath • -(BOOL) writeToFile: (NSString *) path atomically:(BOOL)flag
  • 15. NSMutableArray • 可變的陣列類別 • NSMutableArray 為 NSArray 的⼦子類別 (可以使⽤用 NSArray 的所有⽅方法) • 可以插⼊入新物件 • 可以前後移動元素物件 • 可以刪除物件 (不會有空格產⽣生)
  • 16. (1) 陣列物件的初始化 • -(id) initWithCapacity: (NSUInteger) numItems
  • 17. (2) 陣列的追加與置換 • -(void) addObject: (id)anObject • -(void) addObjecsFromArray: (NSArray *)otherArray • -(void) insertObject: (id)anObject atIndex:(NSUInteger) index • -(void) replaceObjectAtIndex: (NSUInteger)index withObject:(id)anObject • -(void) setArray: (NSArray *)otherArray • -(void) exchangeObjectAtIndex: (NSUinteger)idx1 withObjectAtIndex:(NSUInteger) idx2
  • 18. (3) 物件的刪除 • -(void) removeAllObjects • -(void) removeLastObject • -(void) removeObjectAtIndex: (NSUInteger)index • -(void) removeObjectsInRange: (NSRange)aRange • -(void) removeObject: (id)anObject • -(void) removeObjectsInArray: (NSArray *)otherArray
  • 19. (4) 排序 • -(void) sortUsingSelector: (SEL)comparator • -(void) sortUsingFunction:(NSInteger (*) (idid,void *))compare context:(void *)context
  • 20. 陣列快速列舉 • id obj; for (obj in group) { ........... }
  • 21. 列舉⼦子 NSEnumerator • 對被存放在陣列、集合、字典等集合中的元素物 件,可以依序存取的系統 • Objective-C 2.0 後多被 for ...in 取代 • ⽅方法...... • -(id) nextObject • -(NSArray *) allObjects • -(NSEnumerator *) objectEnumerator • -(NSEnumerator *) reverseObjectEnumerator
  • 25. ViewController.m - (void)viewDidLoad { [super viewDidLoad]; NSArray *myImages = [NSArray arrayWithObjects: [UIImage imageNamed:@"01.jpg"], [UIImage imageNamed:@"02.jpg"], [UIImage imageNamed:@"03.jpg"], ⽤用陣列定義 [UIImage imageNamed:@"04.jpg"], 多個圖檔 [UIImage imageNamed:@"05.jpg"], [UIImage imageNamed:@"06.jpg"], nil]; UIImageView *myAnimatedView = [[UIImageView alloc] initWithFrame:CGRectMake(90, 100, 140, 140)]; myAnimatedView.animationImages = myImages; myAnimatedView.animationDuration = 3.0; myAnimatedView.animationRepeatCount = 0; [myAnimatedView startAnimating]; 動畫設定 [self.view addSubview:myAnimatedView]; }
  • 27. UIPickerView 挑選器 • 提供⼀一份清單給使⽤用者選擇 • Picker 本⾝身不會保存任何資料 (需要⾃自⾏行建⽴立 NSArray 來保留資料) • 它會呼叫 DataSource 和 Delegate 的⽅方法 以取得要顯⽰示的資料
  • 29. 範例: QV009:UIPickerView 顯⽰示資料 (code) QV010:UIPickerView 顯⽰示資料 (xib) QV011:⽐比較 UIPickerView 及 UIDatePicker QV012:UIPickerView 多區段處理
  • 31. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> { UIPickerView *myPickerView; NSArray *dataArray; 使⽤用兩個協定 } @property (retain, nonatomic) UIPickerView *myPickerView; @property (retain, nonatomic) NSArray *dataArray; @end
  • 32. #import "ViewController.h" ViewController.m (1/2) @implementation ViewController @synthesize myPickerView, dataArray; - (void)viewDidLoad { 寬度可調,但⾼高度固定 [super viewDidLoad]; myPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)]; myPickerView.dataSource = self; 物件的代理⼈人 myPickerView.delegate = self; myPickerView.showsSelectionIndicator = YES; 其他屬性 // 決定清單陣列 NSArray *listArray = [[NSArray alloc] initWithObjects: @"AAAAA", @"BBBBB", @"CCCCC", @"DDDDD", @"EEEEE", @"FFFFF", nil]; self.dataArray = listArray; [self.view addSubview:myPickerView]; } 項⺫⽬目清單另外存放 ****** 省略部分程式 ****** @end
  • 33. ViewController.m (2/2) -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 1; 共有幾個區段 } -(NSInteger)pickerView:(UIPickerView *)pickView numberOfRowsInComponent: (NSInteger)component { return [dataArray count]; 在區段內有幾個項⺫⽬目 } -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { // 此處尚無處理選取後的動作 } -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component { return [dataArray objectAtIndex:row]; 各個項⺫⽬目的⽂文字 }
  • 35. ViewController.xib 連結線拉到 File's Owner
  • 36. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> { IBOutlet UIPickerView *myPickerView; NSArray *dataArray; } @property(retain, nonatomic) IBOutlet UIPickerView *myPickerView; @property(retain, nonatomic) NSArray *dataArray; @end
  • 37. ViewController.m #import "ViewController.h" @implementation ViewController @synthesize myPickerView, dataArray; - (void)viewDidLoad { [super viewDidLoad]; self.dataArray = [[NSArray alloc] initWithObjects: @"AAAAA", @"BBBBBB", @"CCCCC", @"DDDDD", @"EEEEE" , @"FFFFF", nil]; } ****** 省略部分程式 ******
  • 38. Project QV011 UIPickerView UIDatePicker 處理選取結果。⽐比較兩種 Picker 的處理⽅方式 (Delegate, Action)
  • 39. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> { IBOutlet UILabel *message; IBOutlet UIPickerView *myPickerView; IBOutlet UIDatePicker *myDatePicker; NSArray *dataArray; } @property (retain, nonatomic) IBOutlet UILabel *message; @property (retain, nonatomic) IBOutlet UIPickerView *myPickerView; @property (retain, nonatomic) IBOutlet UIDatePicker *myDatePicker; @property (retain, nonatomic) NSArray *dataArray; -(IBAction)dateSelect:(id)sender; @end
  • 40. ViewController.m -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 2; } -(NSInteger)pickerView: (UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return [dataArray count]; } -(void)pickerView: (UIPickerView *) pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component { NSInteger r = [myPickerView selectedRowInComponent:component]; NSString *item = [dataArray objectAtIndex:row]; message.text = [NSString stringWithFormat: @"%d, %d : %@", component, r, item]; } -(NSString *)pickerView: (UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component { return [dataArray objectAtIndex:row]; }
  • 42. ViewController.m -(IBAction)dateSelect:(id)sender { NSDate *selected = [myDatePicker date]; NSString *str = [[NSString alloc] initWithFormat:@"%@", selected]; message.text = str; }
  • 43. Project QV012 UIPickerView 多個區段資料的處理
  • 44. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> { IBOutlet UILabel *message; IBOutlet UIPickerView *myPickerView; NSArray *dataArray1, *dataArray2; } @property (retain, nonatomic) IBOutlet UILabel *message; @property (retain, nonatomic) IBOutlet UIPickerView *myPickerView; @property (retain, nonatomic) NSArray *dataArray1, *dataArray2; @end
  • 45. ViewController.m (1/3) #import "ViewController.h" @implementation ViewController @synthesize message, myPickerView, dataArray1, dataArray2; - (void)viewDidLoad { [super viewDidLoad]; ! myPickerView.dataSource = self; myPickerView.delegate = self; dataArray1 = [[NSArray alloc] initWithObjects:@"AAA", @"BBB", @"CCC", @"DDD", nil]; dataArray2 = [[NSArray alloc] initWithObjects:@"111", @"222", @"333", @"444", @"555", nil]; }
  • 46. ViewController.m (2/3) - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {! ! return 2; } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component {! if (component==0) { return [dataArray1 count]; } else { return [dataArray2 count]; } } - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component { if(component==0) { return [dataArray1 objectAtIndex:row]; } else { return [dataArray2 objectAtIndex:row]; } }
  • 47. ViewController.m (3/3) - (void)pickerView: (UIPickerView *) pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {! NSInteger n1 = [myPickerView selectedRowInComponent:0]; NSInteger n2 = [myPickerView selectedRowInComponent:1]; NSString *str1 = [dataArray1 objectAtIndex:n1]; NSString *str2 = [dataArray2 objectAtIndex:n2]; NSString *str = [[NSString alloc] initWithFormat:@"%@ -- %@", str1, str2]; message.text = str; }
  • 48. 範例: 區段間有相依關聯 (左邊的改變會重設右邊的項⺫⽬目)
  • 50. #import <UIKit/UIKit.h> ViewController.h @interface ViewController : UIViewController<UIPickerViewDelegate> { NSMutableDictionary *data; NSArray *keys; ViewController.xib IBOutlet UIPickerView *picker; IBOutlet UILabel *label; } @end
  • 51. ViewController.m (1/4) - (void)viewDidLoad { [super viewDidLoad]; [self prepareData]; } - (void) prepareData { data = [[NSMutableDictionary alloc] init]; [data setValue:[NSArray arrayWithObjects: @"可樂",@"沙⼠士",@"果汁",@"其他",nil] forKey:@"飲料"]; [data setValue:[NSArray arrayWithObjects: @"蛋糕",@"糖果",@"巧克⼒力",@"其他",nil] forKey:@"甜點"]; keys =[[data allKeys] sortedArrayUsingComparator: (NSComparator)^(id obj1,id obj2) { return [obj1 caseInsensitiveCompare:obj2]; }]; }
  • 52. ViewController.m (3/4) //設定滾輪總共有幾個欄位 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { return 2; } //設定滾輪總共有幾個項⺫⽬目 - (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component { if (component==0) { return [keys count]; } else { NSString *key = [keys objectAtIndex: [thePickerView selectedRowInComponent:0]]; // 飲料或甜點 NSArray *array = [data objectForKey:key]; return [array count]; } }
  • 53. ViewController.m (3/4) //設定滾輪顯⽰示的⽂文字 - (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component { if (component==0) { return[keys objectAtIndex:row]; } else { NSString *key = [keys objectAtIndex: [thePickerView selectedRowInComponent:0]]; // 飲料或甜點 NSArray *array = [data objectForKey:key]; return [array objectAtIndex:row]; } }
  • 54. ViewController.m (4/4) //設定滾輪顯⽰示的⽂文字 - (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component { if (component==0) { return[keys objectAtIndex:row]; } else { NSString *key = [keys objectAtIndex: [thePickerView selectedRowInComponent:0]]; // 飲料或甜點 NSArray *array = [data objectForKey:key]; return [array objectAtIndex:row]; } }
  • 56. Project QV106 製作頭尾相接的滾輪選擇器 UIPickerView 採⽤用技巧 假設項⺫⽬目⾮非常多,每次滾 動時計算該顯⽰示的資料 滾動結束時,重新移到中 間相對應的位置
  • 57. ViewController.m (1/2) const int MAX_ROLL = 1000; 宣告⼀一個很⼤大的數 - (void)viewDidLoad { 形同有這麼多項 [super viewDidLoad]; list = [NSArray arrayWithObjects:@"AAA", @"BBB", @"CCC", @"DDD", @"EEE", @"FFF", @"GGG", @"HHH", @"III", @"JJJ", @"KKK", @"LLL", nil]; [self pickerViewReLoad]; } - (NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 1; } -(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component { return MAX_ROLL; }
  • 58. ViewController.m (1/2) 計算相對應的元素位置 -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component { return [list objectAtIndex:(row%[list count])]; } -(void) pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component { [self pickerViewReLoad]; 重新移到中間但 } 相對應元素位置 -(void) pickerViewReLoad { NSUInteger max = MAX_ROLL; NSUInteger base = (max/2) - (max/2)%[list count]; [myPickerView selectRow:[myPickerView selectedRowInComponent:0]%[list count]+base inComponent:0 animated:NO]; }
  • 60. Project QV107 以圖⽚片做為 UIPickerView 的內容 吃⾓角⼦子⽼老⻁虎
  • 61. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> { IBOutlet UIPickerView *pickerView; IBOutlet UILabel *statusLabel; NSArray *column1; NSArray *column2; NSArray *column3; UIButton *spinButton; } @property (nonatomic, retain) IBOutlet UIPickerView *pickerView; @property (nonatomic, retain) IBOutlet UILabel *statusLabel; @property (nonatomic, retain) NSArray *column1, *column2, *column3; - (IBAction) spin:(id)sender; @end
  • 62. ViewController.m (1/3) - (void)viewDidLoad { [super viewDidLoad]; UIImage *img1 = [UIImage imageNamed:@"32_Twitter.png"]; UIImage *img2 = [UIImage imageNamed:@"32_Elephant.png"]; UIImage *img3 = [UIImage imageNamed:@"32_Babelfish.png"]; UIImage *img4 = [UIImage imageNamed:@"32_Panda.png"]; UIImage *img5 = [UIImage imageNamed:@"32_Penguin.png"]; UIImage *img6 = [UIImage imageNamed:@"32_Duckling.png"]; for (int i=1; i<=3; i++) { UIImageView *imgView1 = [[UIImageView alloc] initWithImage:img1]; UIImageView *imgView2 = [[UIImageView alloc] initWithImage:img2]; UIImageView *imgView3 = [[UIImageView alloc] initWithImage:img3]; UIImageView *imgView4 = [[UIImageView alloc] initWithImage:img4]; UIImageView *imgView5 = [[UIImageView alloc] initWithImage:img5]; UIImageView *imgView6 = [[UIImageView alloc] initWithImage:img6]; NSArray *array = [[NSArray alloc] initWithObjects: imgView1, imgView2, imgView3, imgView4, imgView5, imgView6, nil]; NSString *aryName = [[NSString alloc] initWithFormat:@"column%d", i]; [self setValue:array forKey:aryName]; } } Picker 內的資料為圖
  • 63. -(IBAction) spin:(id)sender ViewController.m (2/3) { BOOL win = NO; int numInRow = 1; int lastValue = -1; 重新指定 Picker 內指到的位置 for(int i=0; i<3; i++) { int newValue = arc4random() % [self.column1 count]; numInRow = (newValue==lastValue) ? (numInRow+1) : 1; lastValue = newValue; [pickerView selectRow:newValue inComponent:i animated:YES]; [pickerView reloadComponent:i]; if(numInRow>=2) { win = YES; } "連續" 兩個相同的為贏 } statusLabel.hidden = YES; spinButton.hidden = YES; if(win) { [self performSelector:@selector(playerWin) withObject:nil afterDelay:0.5]; } else { [self performSelector:@selector(showButton) withObject:nil afterDelay:0.5]; } statusLabel.text = @"LOSE...."; }
  • 64. ViewController.m (3/3) #pragma mark - UIPickerView Delegate -(NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 3; } -(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component { return [self.column1 count]; } -(UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { NSString *arrayName = [NSString stringWithFormat:@"column%d", component+1]; NSArray *array = [self valueForKey:arrayName]; return [array objectAtIndex:row]; }