IOS開發入門(4)

承接上節
在本節中,我們將聯繫應用程序開發中的另一項核心功能:佈局和給場景寫代碼,然後構建新場景與現有界面之間的關聯。對於編輯場景的部分,需要在故事面板中添加新的場景,增加用於顯示與編輯汽車的視圖,並創建該場景中的自定義控制器。接下來,實現到達和離開View/Edit場景的轉場動畫。

如果使用該應用程序的泊車員只停某一類型的車,那麼現有功能已經做夠了。然而,汽車有不同的品牌、類型和年份,因此該應用程序還需要幫助泊車員用這些標準辨別汽車。

所以,我們需要添加一個用來編輯汽車的場景:

添加新場景的過程如下:

  1. 創建一個管理新場景的對象,這裏採用的是IOS系統內置的視圖控制器的一個子類
  2. 往故事板中加入一個同樣的系統內置類型的IOS視圖控制器
  3. 將這個視圖新控制器的類名設置爲步驟1中的控制器名
  4. 往故事板的新場景內添加可視化元素
  5. 創建場景所需要的action或outlet
  6. 編寫代碼,使其能夠工作,並確保工作正常

在這個過程中,有時還需要添加一些所需要的過渡動畫。

好了,書上的說明嗶嗶完了,進入實踐模式
首先添加新的場景:

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

創建完之後,類似於之前,也就是上圖左側的那個面板

這裏寫圖片描述

然後我們要把測試的故事面板換一下
把下圖的箭頭用鼠標拖過去

這裏寫圖片描述
這裏寫圖片描述

Car Number字體設置成Headline
Make:那些是Label,後面跟着的是Text Field

元素 屬性名稱
Car Number carNumberLabel
Make文本框 makeField
Model文本框 modelField
Year文本框 yearField
Fuel文本框 fuelField

將這些添加到CarEditViewController.h中,忘了的話可以看前面的章節

結果如圖:
這裏寫圖片描述

然後現在添加公共屬性

#import <UIKit/UIKit.h>

@class Car;//添加代碼

@interface CarEditViewController : UIViewController

@property (nonatomic) NSInteger carNumber;//添加代碼 @class表明向前引用 
@property (strong,nonatomic) Car *currentCar;//添加代碼 控制器使用strong內存限定符,因爲需要確保被編輯的汽車對象不會從內存中移除
@property (weak, nonatomic) IBOutlet UILabel *carNumberLabel;
@property (weak, nonatomic) IBOutlet UITextField *makeField;
@property (weak, nonatomic) IBOutlet UITextField *modelField;
@property (weak, nonatomic) IBOutlet UITextField *yearField;
@property (weak, nonatomic) IBOutlet UITextField *fuelField;

@end

修改CarEditViewController.m文件中的viewDidLoad:方法,這個方法會在每次顯示車輛信息的時候調用

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSString *carNumberText;
    carNumberText = [NSString stringWithFormat:@"Car Number:%d",self.carNumber];
    self.carNumberLabel.text = carNumberText;
    self.makeField.text = self.currentCar.make;
    self.modelField.text = self.currentCar.model;
    self.yearField.text = [NSString stringWithFormat:@"%d",self.currentCar.year];
    self.fuelField.text = [NSString stringWithFormat:@"%0.2f",self.currentCar.fuelAmount];

}

下面的viewWillDIsppear:方法會在每次視圖消失的時候用,因爲我們可能會修改原來的數據,所以該方法會在切換的時候將當前界面顯示的東西覆蓋到原來的數據(如果沒變動話,原來數據被舊數據覆蓋;變動的話,原來數據被新數據覆蓋)

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];

    self.currentCar.make = self.makeField.text;
    self.currentCar.model = self.modelField.text;
    self.currentCar.year = [self.yearField.text integerValue];
    self.currentCar.fuelAmount = [self.fuelField.text floatValue];
}

運行結果如圖

這裏寫圖片描述

講道理,這裏的Year和Fuel的輸入框應該是數字纔對,這裏竟然是字符

這是我們的Keyboard設置的不對
如下修改:
對year
將Keyboard Type改爲Number Pad
這裏寫圖片描述
對fuel
將Keyboard Type改爲Decimal Pad

Number Pad與Decimal Pad的不同之處在於,一個的左下角有小數點,另一個沒有
再次運行

(PS,這是Number Pad)
這裏寫圖片描述

(PS,這是Decimal Pad)
這裏寫圖片描述

好了,這時候我們第二個故事面板搞定了。我們還要做的事就是將之前那個面板跟現在這個面板聯繫起來

將箭頭移回第一個面板
並添加一個Button叫Edit放到圖中位置(當然你也可以隨便放)
這裏寫圖片描述

然後就跟着圖做(先不用知道爲什麼,之後會再說的)
這裏寫圖片描述

這裏寫圖片描述

發生了什麼變化呢?

  • Xcode移動首個場景的箭頭到插入的導航控制器中(圖上沒有截到,就是上面我們移動的那個箭頭,移動到第二個故事面板之後又移回去的那個)
  • 加入的關係鏈位於控制器和Add/View場景之間
  • 導航控制器在場景中添加了一個標題欄(後面兩個故事面板上面那灰色的區域)

雙擊畫圈圈的地方,做修改:將Title改成CarValet

這裏寫圖片描述

運行:
這裏寫圖片描述

發現Total Car被蓋掉了
這時候要把它拉下來
如下圖(我這裏就不再截圖了)

這裏寫圖片描述

好了,該鏈接兩個故事面板了。按住ctrl,將Edit按鈕拖向第二個故事面板,會出現下圖的菜單
這裏寫圖片描述

選中push,結果如下圖

這裏寫圖片描述

這時候運行程序,點擊Edit,會發現成功的切換故事面板

在ViewController.m文件中
首先導入CarEditViewController.h文件

import "CarEditViewController.h"

然後添加如下方法,注意看註釋

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"EditSegue"]){//設置Edit場景,除非這是edit segue
        CarEditViewController *nextCOntroller;

        nextCOntroller = segue.destinationViewController;//衝這個segue獲得Edit場景的視圖控制器。segue擁有源控制器屬性和目的控制器屬性,也就是當前屏幕上顯示的控制器(源控制器)與將要顯示的控制器(目的控制器)
        nextCOntroller.carNumber = displayedCarIndex + 1;//設置car Number屬性,機制索引是基於0的

        Car *currentCar = arrayOfCars[displayedCarIndex];//使用Objective-C的索引而非objectAtIndex方法
        nextCOntroller.currentCar = currentCar;//找到並設置好正確的Car對象
    }
}

從一個場景轉換到另一個場景時,通常需要傳遞某些類型的信息。用戶去某個其他的定做某事或瀏覽某物。
上述的方法目的就是,在segue啓動之後,而且是在新的場景要調用viewDidLoad:方法之前,將獲得的信息傳到新的場景。也就是如果我們的車有信息的話,就能把他傳到Edit場景中。

這時候還沒結束(如果你運行的話,會發現year還是0)
我們需要設置segue的名稱,修改如下圖

這裏寫圖片描述

這時候再次運行
發現並做下圖修改

這裏寫圖片描述

返回之後發現並沒有變化,然而其實他已經變化了,要查看這一點,你可點擊Next到下一輛車再Previous到上輛車,你就會發現變化了

這裏寫圖片描述

這裏寫圖片描述

你可能會疑惑,爲什麼我們不用segue返回?

通知Add/View場景更新,你可能的第一想法是使用segue實現返回。遺憾的是,這點行不通。segue並不能返回那個在Edit場景打開的、與之前相同的Add/View視圖控制器實例。要知道,每個segue會創建新的視圖控制器,因而它會跳到一個全新的、只有一輛汽車的視圖控制器。更糟的是,原來的Edit場景可能已被釋放,而隨着每個Edit/返回循環將會創建兩個或更多的控制器,他們會將系統的內存佔完。

至少有三種方法可以用來更新Add/View場景:

  • 添加一個名爲currentCarUpdated的方法到ViewController中,並將之關聯到CarEditViewController中的ViewController對象。在Edit場景消失時,調用更新方法。
  • 使用協議讓ViewController實現更新
  • 使用IOS6中初次出現的unwind segue機制

第一種方法能實現功能,但會極大降低代碼的複用性和模式化。每個視圖控制器對象需要知道彼此太多信息,因此它們無法分割。使用協議可以消除這個耦合性問題,這點將在接下來的小節中講到,在這裏就不嗶嗶了。

今天的介紹就到這裏咯

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

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