IOS开发入门(5)
来源:互联网 发布:上海圣剑网络怎么样 编辑:程序博客网 时间:2024/05/20 21:18
承接上节
在本节中,将对之前的故事版进行改进
改进故事版I
先大致介绍一下协议
在大多数应用程序中,都会存在一些需要与其他对象中的触发行为者进行交换的数据,这导致互相关联、不独立的代码难以维护和复用。相应的解决办法,就是使用协议(protocol)。
协议增加了代码的可维护性、复用性和灵活性。可以认为协议是请求者和供应者之间的合同。供应者常被叫做代理(delegate),统一实现一些方法,从而请求者可以调用。每个方法通常用于如下三个目的之一
- 从代理请求数据,如Car对象
- 在改变时通知代理,以允许存储、取消或再次显示数据
- 指向特定的行为,如呼叫某人前来取车
协议的主要优点在于复用性,并且每个实现了所规定的方法的类,都可以成为代理。相似的是,任何类都可以使用协议方法,请求信息或发起行为。
要了解更多关于协议的信息,查看Programming in Objective-C 2.0,第二版,Stephen G Kochan著,有Addison We是可以出版,翻看该书中第231页关于协议的内容。也可以阅读苹果公司Objective-C文档中关于协议的章节。
使用协议交换数据
协议的常见用法是交换数据。编辑者或请求者需要信息,由代理提供并且或许由代理更新。
在这种情况下,汽车编辑者需要知道汽车对象和拍照。Add/View场景或代理,在汽车对象有改变时需要被通知到,从而可以更新显示内容。这要求协议有三个方法:
- carToEdit返回汽车对象以进行编辑
- carNumber返回被编辑汽车的拍照(不是索引数)
- editedCarUpdated告诉代理,编辑操作已经完成
现在创建新的Objective-C协议,命名为CarEditViewControllerProtocol,并将它添加到项目中。
需要注意的是,需要选择Objective-C File中,File Type 选择protocol
代码如下:
#import <Foundation/Foundation.h>//在协议中个导入用到的类的所有头文件。Foundation.h定义了许多Cocoa类型,包括NSInteger类型@class Car;@protocol CarEditViewControllerProtocol <NSObject>//@protocol是声明协议的指令。接下来的部分是协议的名称,接着是协议要包含的内容。在这种情况下,CarEditViewControllerProtocol有权限访问任何在NSObject协议中声明的方法,如self、class和description等- (Car*)carToEdit;//指定方法声明的方式如同公共类方法- (NSInteger)carNumber;- (void)editedCarUpdated;@end
在定义好协议后,改变要使用该协议的请求者。在CarValet应用中,从改变导入文件开始,进行修改。在CarEditViewController.h文件中,移除carNumber属性,然后按下列代码进行更改
#import <UIKit/UIKit.h>#import "CarEditViewControllerProtocol.h"//修改@class Car;@interface CarEditViewController : UIViewController//@property (nonatomic) NSInteger carNumber;//修改@property (weak, nonatomic) id <CarEditViewControllerProtocol> delegate;//修改@property (strong,nonatomic) Car *currentCar;@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
最后一个修改是协议中十分重要的一部分。id是占位符,能代表任意类的对象。这意味着任意类,包含哪些我们还没有想到过的类,都可以成为该协议的代理。虽然Edit场景要求Car对象拥有某些特定属性,但我们依然拥有设置该代理的灵活性。可以在其他的项目中重用到Edit场景。另一处要注意的地方是,在声明id变量类型时并不适用星号。id变量的声明应该是delegate
而非*delegate
。
在类型之后,用尖括号括起的CarEditViewControllerProtocol,这表明无论delegate所属的类是什么,他都必须遵从协议。也就是说,它必须实现协议要求的所有方法。
现在更新CarEditViewController.m中的viewDidLoad方法,代码如下
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSString *carNumberText; carNumberText = [NSString stringWithFormat:@"Car Number:%d",[self.delegate carNumber]];//修改 启辰的拍照,现在从代理返回 self.carNumberLabel.text = carNumberText; self.currentCar = [self.delegate carToEdit];//修改 因已编辑过Car对象,故而通知代理。 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];
最后一处修改是通知Add/View场景进行自我更新。在viewWillDisappear:的结尾处添加对[self.delegate editedCarUpdated]
的调用
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. [self.delegate editedCarUpdated];}
现在已经完成请求者部分,是时候更新代理部分了。
修改ViewController.h文件顶部的代码
#import <UIKit/UIKit.h>#import "CarEditViewControllerProtocol.h"//修改@interface ViewController : UIViewController<CarEditViewControllerProtocol>//修改@property (weak, nonatomic) IBOutlet UILabel *totalCarsLabel;@property (weak, nonatomic) IBOutlet UILabel *CarNumberLabel;@property (weak, nonatomic) IBOutlet UILabel *CarInfoLabel;- (IBAction)newCar:(id)sender;- (IBAction)previousCar:(id)sender;- (IBAction)nextCar:(id)sender;@end
<CarEditViewControllerProtocol>
的意思是ViewController支持——也即是说,遵从——我们的协议。当然,我们还未实现任何支持。此处,Xcode展现了它帮助你检查代码完整的方法之一。查看工具栏中间部分的状态栏,可以看到右边有黄色警告三角形。表明在编译代码时已导致警告。单击警告可以找到更多细节。因为协议的方法部分不存在,该警告表明存在不完整的实现。
在newCar:方法的上方添加协议方法:
- (Car*)carToEdit { return arrayOfCars[displayedCarIndex];}- (NSInteger)carNumber { return displayedCarIndex + 1;}- (void)editedCarUpdated { [self displayCurrentCarInfo];}
最后还有一个错误提示需要解决
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if([segue.identifier isEqualToString:@"EditSegue"]){ CarEditViewController *nextCOntroller; nextCOntroller = segue.destinationViewController; nextCOntroller.delegate = self;//修改 Car *currentCar = arrayOfCars[displayedCarIndex]; nextCOntroller.currentCar = currentCar; }}
然后就是成功运行了。
改进故事版2
IOS 6 引入了一种更好的方法来将数据返回到激发segue的视图控制器:简单地将一个特殊类型的IBAction添加到视图控制器中即可。同城,动作方法有个看似为(id)sender的参数,或者根本没有参数。通过将参数修改为(UIStoryboard*)segue,可以创建特殊类型的动作——一种能接受segue对象的动作。
仅当一个场景激发另一个场景的切换时才会发送prepareForSegue:sender:。它是向前segue。在IOS 6中,存在另一种类型的segue,其动作是相反的:在一个changing想要返回到之前的场景时发送prepareForSeguesender:。它会回退(unwinds)首次打开场景的segue,并且在打开之前的场景时不会创建新场景。
要查看这个回退动作,修改如下代码:
在ViewController.m底部添加
- (IBAction)editingDone:(UIStoryboardSegue*)segue { [self displayCurrentCarInfo];}
现在需要激发这个回退动作,方法如同Edit的修改
添加按钮(这里换了个样式)
Ctrl将Done拉到下图位置,选择editingDone
在CarEditViewController.m中修改如下方法
- (IBAction)editingDone:(UIStoryboardSegue*)segue { NSLog(@"\neditedCarUpdated called!\n"); [self displayCurrentCarInfo];}
每次Done之后,会在控制台看到
运行的时候发现,还是没能立即刷新,然而你对同一个再次编辑,再次返回,会发现他保存的是上一个的变化。
讲道理,我们要的应该是点返回只有立即更新才对,那么做如下修改
在CarEditViewController.m中添加方法,这个跟之前跳转到类似,我就不多解释了
添加segue标签
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if([segue.identifier isEqualToString:@"EditDoneSegue"]){ 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]; }}
现在运行之后,一旦更更久能立即显示啦
今天的介绍就到这里咯
我的另一个博客站点:Arnold-你们好啊
- IOS开发入门(5)
- IOS开发入门(1)
- IOS开发入门(2)
- IOS开发入门(3)
- IOS开发入门(4)
- ios开发(二十)入门图表
- iOS开发入门(好东西)
- IOS开发入门(10)-滚动
- iOS 8开发入门--序言(1)
- iOS 8开发入门--序言(2)
- iOS 8开发入门--序言(2)
- iOS 8开发入门--序言(2)
- ios 开发入门资料
- IOS开发入门
- 【iOS开发】---- ARC 入门
- ios 入门开发三
- 第一章 ios开发入门
- iOS开发~OPenCV入门
- goto
- Composer笔记(三):composer.json文件配置
- Tutorial: 463. Island Perimeter
- 闪回查询和闪回版本查询实验
- jquery关闭当前页面,后台刷新父页面
- IOS开发入门(5)
- $.trim(),$.each()方法详解
- 用JSP做计算器(二)
- Android的Switch语句case expressions must be constant expressions错误的解决方法
- 插入排序
- 写线程的感悟
- 数论【Sdoi2010】 古代猪文
- 湖南省大学生程序设计竞赛系统设计
- Java事件处理机制(自定义事件)