Sco*_*ton 4 iphone datasource objective-c tableview
我的浏览器恰好是一个tableViewController,它告诉我,它的属性是一个NSArray或一个NSDictionary,它保存了要加载到表中以供显示的数据.
好像我应该明确说出类似的话:
[self.tableView useData:self.MyArray];
Run Code Online (Sandbox Code Playgroud)
我想在tableViewController中有多个数组,并以编程方式在一个和另一个之间切换.
我注意到当tableViewController使用searchViewController时,你可以这样做:
if (tableView == self.searchDisplayController.searchResultsTableView) {
Run Code Online (Sandbox Code Playgroud)
我甚至能够做到这一点:
self.tableView = self.searchDisplayController.searchResultsTableView;
[self.tableView reloadData];
Run Code Online (Sandbox Code Playgroud)
但是我无处可以找到如何将self.tableView设置回主数据源!
Tec*_*Zen 41
好的,我了解您的挫折感,因为绝大多数iPhone教学材料都没有足够重视整体应用程序设计.它们直接用于眼睛糖果界面并且只为应用程序应该处理数据的方式付费,即使处理数据首先是应用程序的全部目的!
教学材料没有花足够的时间来解释整个iPhone/Cocoa API所基于的模型 - 视图 - 控制器设计模式.你很难理解任何事情,因为你错误地认为UI视图是程序的核心,因为你一直在努力将功能塞入错误的对象,因为教学材料让你相信.在这种误解下,没有任何意义,甚至不是Apple文档.
你需要退后一步重新思考.决定显示哪些数据以及何时显示数据不是视图的功能.表视图控制器的功能不是保存,管理或存储应用程序的数据.这些函数正确属于数据模型对象(您可能从未听说过.)您遇到了麻烦,因为您试图在视图中拆分数据模型任务,而视图控制器则不属于它们.
显然,您的应用程序甚至没有数据模型,因为您将表的数据作为tableview控制器的属性.虽然你经常在简单的教程示例中看到这一点,但它是一个糟糕的设计,在任何但最简单的应用程序的复杂性下都会崩溃.
相反,您的数据应存储在自己的自定义对象中并在其中进行管理.这是数据模型.在您的情况下,听起来您的数据分布在两个数组中,因此您将创建一个如下所示的数据模型对象:
@interface MyDataModel : NSObject {
@protected
NSArray *arrayOne;
NSArray *arrayTwo;
@public
NSArray *currentlyUsedArray;
}
@property(nonatomic, retain) NSArray *currentlyUsedArray;
-(void) switchToArrayOne;
-(void) switchToArrayTwo;
-(void) toggleUsedArray;
@end
#import "MyDataModel.h"
@interface MyDataModel ()
@property(nonatomic, retain) NSArray *arrayOne;
@property(nonatomic, retain) NSArray *arrayTwo;
@end
@implementation MyDataModel
- (id) init{
if (self=[super init]) {
self.arrayOne=//... initialize array from some source
self.arrayTwo=//... initialize array from some source
self.currentlyUsedArray=self.arrayOne; //whatever default you want
}
return self;
}
-(void) switchToArrayOne{
self.currentlyUsedArray=self.arrayOne;
}
-(void) switchToArrayTwo{
self.currentlyUsedArray=self.arrayTwo;
}
- (void) toggleUsedArray{
if (self.currentlyUsedArray==self.arrayOne) {
self.currentlyUsedArray=self.arrayTwo;
}else {
self.currentlyUsedArray=self.arrayOne;
}
}
Run Code Online (Sandbox Code Playgroud)
(请注意,实际数据是封装的,其他对象只能访问currentlyUsedArray
.数据模型根据数据的内部状态决定提供哪些数据.)
此数据模型对象应位于通用可访问的位置.最好的方法是使它成为单例,但快速而肮脏的方法是将其作为app委托的属性.
所以在你的tableview控制器中你会有一个属性:
MyDataModel *theDataModel;
@property (nonatomic, retain) MyDataModel *theDataModel;
Run Code Online (Sandbox Code Playgroud)
然后在实施中
@synthesize theDataModel;
-(MyDataModel *) theDataModel; {
if (theDataModel; !=nil) {
return theDataModel; ;
}
id appDelegate=[[UIApplication sharedApplication] delegate];
self.theDataModel=appDelegate.theDataModelProperty;
return theDataModel;
}
Run Code Online (Sandbox Code Playgroud)
然后在tableview数据源方法中:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
cell.textLabel.text=[self.theDataModel.currentlyUsedArray objectAtIndex:indexPath.row];
return cell;
}
Run Code Online (Sandbox Code Playgroud)
如果应用程序中任何位置的某个事件要求您切换数组,则只需从应用程序委托调用数据模型对象并向其发送相应的交换机阵列消息.
id appDelegate=[[UIApplication sharedApplication] delegate];
[appDelegate.theDataModelProperty toggleUsedArray];
Run Code Online (Sandbox Code Playgroud)
现在所有后续数据操作,无论是在特定的表视图还是其他完全不相关的视图中,都将使用数据形成正确的数组.
为什么要经历这一切?它使应用程序模块化.您可以轻松添加不同的视图,每个视图以不同的方式显示数据,而无需每次都重写数据管理.您可以使用数据模型来管理将在表格,Web视图或命令行中显示的数据.您甚至可以轻松地将数据模型移动到完全不同的应用程序.
这种模块化使大型复杂应用程序的管理变得更加容易.您只有一个操作和控制数据的对象.您不必担心某些很少使用的代码段中的一些小错误会丢弃整个应用程序.您可以轻松地插入视图或轻松删除它们而不会破坏应用程序.
这当然是一个微不足道的例子,但它显示了良好的做法.
但是,您可能会问,这如何解决tableview的问题,知道要加载哪些数据以及何时加载它?简单,它没有.知道要加载哪些数据或何时加载,不是tableview的工作.数据模型处理what-data和tableview控制器处理何时.(您甚至可以在更新数据模型时发出通知,例如对于网址.然后视图控制器可以注册通知并reloadData
在数据模型发生更改时进行调用.)
通过在MVC中无情地划分和封装功能,您可以从易于维护和调试的简单,可重用组件创建复杂的应用程序.
对大多数教学材料来说,这只是对这个完全关键的概念不屑一顾.