IOS開發入門(3)

承接上一節

簡單介紹一下屬性的另外兩個特性:
首先,在創建make時

@property NSString *make;

默認的是讀寫形式

我們可能不希望汽車對象創建後能夠修改make、model或year,這時候我們可以在聲明屬性的時候將其聲明爲只讀屬性

方法很簡單

@property (readonly) NSString *make;

這樣就聲明完成了,之後當我們在ViewController.m文件中試圖對創建完成的myCar或者是othercar對象,試圖修改其make值的時候,
系統會報錯

屬性聲明的一般形式如下:

@property <(qualifier1,qualifier2,...)> <type> <property_name>

另外,如果我們希望實現這些屬性在外部只讀,而在內部可以讀寫。也很簡單,因爲可以在.m文件中重新聲明屬性。可以通過在Car.m文件的
@implementation語句之前增加如下代碼,添加或覆蓋類的接口定義:

@interface Car()
@property (readwrite) int year;
@property NSString *make;
@property NSString *model;
@end

Car對象會使用新的實例變量定義。注意明確指定readwrite並不是必須的,默認值是readwrite。所以上面代碼中make與model跟year是一樣的,重定義後變成內部可讀寫。

Objective-C的語法之類的就不再多說了

現在介紹故事面板

(來自書上)對於用戶來說,界面就是我們的應用程序。它是用戶與爲應用程序提供動力的功能(即邏輯和數據)之間的主要門戶。通過創建一些信息型和實用性元素,包括屏幕和這些屏幕上所顯示的內容,可以設計與實現用戶體驗。我們所設計的每個屏幕可以實現如下功能:

  • 顯示信息,如CarValet應用程序中汽車對象的數量
  • 支持動作,如通過觸摸按鈕創建一輛新汽車
  • 請求輸入,如制定汽車的品牌
  • 顯示用戶活動的結果,其方式包括更新所展示的汽車,或者切換至一個支持用戶編輯汽車的屏幕

用戶每次使用應用程序時,就像是在體驗故事。故事所關注的內容可能是生活管理(Calender應用程序);與朋友聯繫(郵件、社交應用程序等)


根據我們一開始寫的Carvalet項目,我們爲他搭建場景

到這個地方來

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

改成——Headline

其餘的改變:

可視化元素 作用 類名
Total Cars 顯示停泊的汽車總數–Car對象的數量 UILabel
New Car 通過添加新的Car對象,停泊一輛車 UIButton
Divider 在增加汽車和查看汽車兩塊區域間添加一條視覺分割線,不會的話下面有圖解 UIView
Current Car Number 顯示當前所展示的汽車對象的索引數 UILabel
Car Information 顯示當前汽車的詳情 UILabel
Previous 讓泊車員瀏覽汽車,提供前一輛汽車的詳情(如果有車) UIButton
Next 提供下一輛車的詳情(如果有車) UIButton

這裏寫圖片描述

這裏寫圖片描述

運行如圖:(PS:New Car一開始我弄成Label,應該是Button,上面圖截得New Car顏色應該與Previous,Next顏色一樣,這裏我就不換圖了)

這裏寫圖片描述

好了,到目前爲止,我們的界面做出來了,但是隻有外表,內在啥也沒有,我們現在來添加的這些元素行爲

添加action和outlet

元素 類型 名稱
Total Car標籤 IBOutlet totalCarsLabel
Car NUmber標籤 IBOutlet CarNumberLabel
Car Info標籤 IBOutlet CarInfoLabel
New Car按鈕 IBAction newCar:
Previous Car按鈕 IBAction previousCar:
Next Car按鈕 IBAction nextCar:

方法如圖

這裏寫圖片描述

這裏寫圖片描述

拉過去後會跳出,對於label選擇Connection方式爲Outlet,Name根據上表

這裏寫圖片描述

weak表示對象的所有權,能夠幫助編譯器添加內存管理代碼。理解這些內存限定符的意義非常重要。

button也是用同樣的方法拉過去,不過跳出的對話框中要改成下圖樣式,Name根據上表

這裏寫圖片描述

這是添加完6個元素後

這裏寫圖片描述

你會發現在ViewController.m裏面,自動多出了點東西,那些是按鈕時間,每個按鈕如何操作都在相對應的按鈕方法裏面實現

這裏寫圖片描述

對於內存的介紹的話本文不多介紹,想了解更多自行谷歌(在這裏推薦一個翻牆的東東,Star VPN,可以在App Store裏面下載)

在ViewController.m

@implementation ViewController {
    NSMutableArray *arrayOfCars; //使用mutable array記錄所有汽車對象
    NSInteger displayedCarIndex; //指定靠下位置顯示的汽車的數組索引
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    arrayOfCars = [[NSMutableArray alloc] init];//初始化汽車的數組爲空數組
    displayedCarIndex = 0;//顯示創建的第一輛汽車
}

好了現在有保存新車的地方了,還需要創建它們,創建的方法是newCar:

newCar:方法

- (IBAction)newCar:(id)sender {
    Car *newCar = [[Car alloc] init];//用默認值創建新的Car對象,並將其添加到數組中
    [arrayOfCars addObject:newCar];//添加
    NSString *totalCarText;
    totalCarText = [NSString stringWithFormat:@"Total Cars: %d",[arrayOfCars count]];//基於當前的汽車數量,創建新的total Car Text字符串
    self.totalCarsLabel.text = totalCarText;//更新顯示泊車員字符串
}

運行一下,點擊new Car

這裏寫圖片描述

這裏我們會注意到,之前是999,我們只要到故事面板把他改成0就行了

加入顯示汽車行爲

顯示對象的信息是另一種常見的任務。UILabel能顯示字符串,通過界面中的text屬性,可以使用任何字體、大小以及指定顏色。當text屬性有所更改時,標籤也會更新。

使用UILabel顯示變化的信息需要4樣東西:標籤、標籤的關聯、用於顯示的字符串以及設置標籤文本的代碼。

我們已經在場景中添加好汽車的信息標籤,也已經關聯到標籤上。要添加對汽車的描述有幾種方法:一種是通過添加公共方法,另一種是使用read-only屬性和自定義的getter方法。要實現該屬性和getter方法,可以參照以下步驟:

  1. 在Car.h文件中,在fuelAmount的下方添加這行聲明屬性的代碼@property (readonlu)NSString *carInfo;
  2. 打開Car.m文件,在initWithMake:的下方添加實現自定義getter方法的代碼
- (NSString *)carInfo {
    return [NSString stringWithFormat:
            @"Car Info\n Make: %@\n Model: %@\n year: %d",self.make ? self.make :@"Unknown Make",self.model ? self.model :@"Unknown Model",self.year];
}

PS 三元運算符?,不懂自行谷歌

現在,可以獲得描述汽車信息的字符串,還需要一種方法,用於更新顯示汽車數量和信息的標籤的文本內容。可以一一設置每個標籤所要更新的信息。但是,更新顯示的汽車信息這種行爲會在多個地方發生。在這種情況下,抽出相關的代碼是良好的設計方式

在newCar:方法的上端,添加displayCurrentCarInfos方法

- (void)displayCurrentCarInfo {
    Car *currentCar;
    currentCar = [arrayOfCars objectAtIndex:displayedCarIndex];
    //對當前顯示的汽車對象進行加載。注意生產代碼應該覈對displayedCarIndex是否爲有效索引
    self.CarInfoLabel.text = currentCar.carInfo;
    //通過carInfo屬性獲得汽車的描述信息

    NSString *carIndexText;
    //更新汽車的標籤,注意將當前索引加1(數組從0開始)
    carIndexText = [NSString stringWithFormat:@"Car Number: %d",displayedCarIndex +1];
    self.CarNumberLabel.text = carIndexText;
}

在newCar:方法中,調用displayCurrentCarInfo

- (IBAction)newCar:(id)sender {
    Car *newCar = [[Car alloc] init];//用默認值創建新的Car對象,並將其添加到數組中
    [arrayOfCars addObject:newCar];//添加
    NSString *totalCarText;
    totalCarText = [NSString stringWithFormat:@"Total Cars: %d",[arrayOfCars count]];//基於當前的汽車數量,創建新的total Car Text字符串
    [self dispalyCurrentCarInfo];
    self.totalCarsLabel.text = totalCarText;//更新顯示泊車員字符串
}

運行結果

這裏寫圖片描述

發現只有”Car Info”只有一行,這是因爲我們在創建Car Information時,只弄了一行

在故事面板中如下修改(就是拉長拉寬了)

這裏寫圖片描述

再次運行

這裏寫圖片描述

現在操作上一輛跟下一輛

在這裏先寫一個changeDisplayedCar(用來令車信息改變)

因爲上一輛下一輛的實質上是改變當前顯示的信息

- (void)changeDisplayedCar:(NSInteger)newIndex {
    if(newIndex < 0) { //確保新的索引值是有效的索引。如果索引小於0,使值爲0
        newIndex = 0;
    } else if(newIndex >= [arrayOfCars count]) {//如果newIndex超出arrayOfCar的範圍,就將其設置爲最後一個
        newIndex = [arrayOfCars count] - 1;
    }
    if (displayedCarIndex != newIndex) {//僅更新索引值有變化的視圖
        displayedCarIndex = newIndex;
        [self displayCurrentCarInfo];
    }
}

previousCar:和nextCar:方法如下

- (IBAction)previousCar:(id)sender {
    [self changeDisplayedCar:displayedCarIndex - 1];
}

- (IBAction)nextCar:(id)sender {
    [self changeDisplayedCar:displayedCarIndex + 1];
}

運行結果
這裏寫圖片描述

- (void)updateLabel:(UILabel*)theLabel
     withBaseString:(NSString*)baseString
              count:(NSInteger)theCount {
    NSString *nexText;
    nexText = [NSString stringWithFormat:@"%@: %d",baseString,theCount];

    theLabel.text = nexText;
}

下面這些代碼是讓newCar和顯示車輛信息通過一個專門的更新標籤的方法來實現標籤的更新,這樣就不用每一個標籤寫一個專門的更改的方法了

- (void)displayCurrentCarInfo {
    Car *currentCar;
    currentCar = [arrayOfCars objectAtIndex:displayedCarIndex];
    //對當前顯示的汽車對象進行加載。注意生產代碼應該覈對displayedCarIndex是否爲有效索引
    self.CarInfoLabel.text = currentCar.carInfo;
    //通過carInfo屬性獲得汽車的描述信息

    [self updateLabel:self.CarNumberLabel withBaseString:@"Car Number" count:displayedCarIndex +1];
}

- (IBAction)newCar:(id)sender {
    Car *newCar = [[Car alloc] init];//用默認值創建新的Car對象,並將其添加到數組中
    [arrayOfCars addObject:newCar];//添加
    [self updateLabel:self.totalCarsLabel withBaseString:@"Total Cars" count:[arrayOfCars count]];
}

今天的介紹就到這裏咯

我的另一個博客站點:Arnold-你們好啊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章