[self.tableView reloadData]如何知道要重载的数据? [英] How does [self.tableView reloadData] know what data to reload?

查看:95
本文介绍了[self.tableView reloadData]如何知道要重载的数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我错误地告诉我,我的viewcontroller恰好是一个tableViewController,它不知道它的属性是NSArray还是NSDictionary,它保存了要加载到表中以供显示的数据。



似乎我应该明确说出类似的内容:

  [self.tableView useData :self.MyArray]; 

我希望在tableViewController中有多个数组,并以编程方式在一个和另一个之间切换。 / p>

我注意到当tableViewController使用searchViewController时,你可以这样做:

  if(tableView == self.searchDisplayController.searchResultsTableView){

我甚至曾经能够做到这一点:

  self.tableView = self.searchDisplayController.searchResultsTableView; 
[self.tableView reloadData];

但我无处可找到如何将self.tableView设置回主数据源!

解决方案

好的,我理解你的挫败感,因为绝大多数iPhone教学材料都没有足够重视整体应用程序设计。它们直接用于眼睛糖果界面并且只为应用程序应该处理数据的方式付费,即使处理数据首先是应用程序的全部目的!



教学材料没有花足够的时间来解释整个iPhone / Cocoa API所基于的模型 - 视图 - 控制器设计模式。你很难理解任何事情,因为你错误地认为UI视图是程序的核心,因为你一直在试图将功能塞入错误的对象,因为教学材料让你相信。在这种误解下,没有任何意义,甚至没有Apple文档。



你需要退后一步并重新思考。决定显示哪些数据以及何时显示数据不是视图的功能。表视图控制器的功能不是保存,管理或存储应用程序的数据。这些函数正确属于数据模型对象(您可能从未听说过。)您遇到了麻烦,因为您试图在视图中拆分数据模型任务,而视图控制器则不属于它们。



显然,您的应用程序甚至没有数据模型,因为您将表的数据作为tableview控制器的属性。虽然您经常在简单的教程示例中看到这一点,但它是糟糕的设计,在任何但最简单的应用程序的复杂性下都会崩溃。



相反,您的数据应存储在自己的自定义对象中并在其中进行管理。这是数据模型。在你的情况下,听起来你的数据分布在两个数组中,所以你要创建一个这样的数据模型对象:

  @interface MyDataModel:NSObject {
@protected
NSArray * arrayOne;
NSArray * arrayTwo;
@public
NSArray * CurrentlyUsedArray;

}
@property(非原子,保留)NSArray * CurrentlyUsedArray;

- (void)switchToArrayOne;
- (void)switchToArrayTwo;
- (void)toggleUsedArray;

@end

#importMyDataModel.h

@interface MyDataModel()
@property(nonatomic,retain)NSArray * arrayOne;
@property(非原子,保留)NSArray * arrayTwo;

@end


@implementation MyDataModel

- (id)init {
if(self = [super init] ]){
self.arrayOne = // ...从某些源初始化数组
self.arrayTwo = // ...从某些源初始化数组
self.currentlyUsedArray = self.arrayOne ; //你想要什么默认值
}
返回自我;
}

- (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;
}
}

(请注意实际数据是封装的,而其他数据是封装的对象只能访问 currentUsedArray 。数据模型根据数据的内部状态决定提供哪些数据。)



此数据模型对象应位于普遍可访问的位置。最好的方法是使它成为单例,但快速而肮脏的方法是将其作为app委托的属性驻留。



所以在你的tableview控制器中你会有一个属性:

  MyDataModel * theDataModel; 
@property(nonatomic,retain)MyDataModel * theDataModel;

然后在实施中

  @synthesize theDataModel; 

- (MyDataModel *)theDataModel; {
if(theDataModel;!= nil){
返回theDataModel; ;
}
id appDelegate = [[UIApplication sharedApplication] delegate];
self.theDataModel = appDelegate.theDataModelProperty;
返回theDataModel;
}

然后在你的tableview数据源方法中:

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
cell.textLabel。 text = [self.theDataModel.currentlyUsedArray objectAtIndex:indexPath.row];
返回单元格;
}

如果某个活动 在应用中的任何位置 要求您切换数组,只需从应用程序委托调用数据模型对象并向其发送相应的开关阵列消息。

  id appDelegate = [[UIApplication sharedApplication] delegate]; 
[appDelegate.theDataModelProperty toggleUsedArray];

现在所有后续数据操作,无论是在特定的表视图还是其他完全不相关的视图中,都将使用数据形成正确的数组。



为什么要经历所有这些麻烦?它使应用程序模块化。您可以轻松添加不同的视图,每个视图都以不同的方式显示数据,而无需每次都重写数据管理。您可以使用数据模型来管理将在表格,Web视图或命令行中显示的数据。您甚至可以轻松地将数据模型移动到完全不同的应用程序。



这种模块化使大型复杂应用程序的管理变得更加容易。您只有一个操作和控制数据的对象。您不必担心某些很少使用的代码段中的一些小错误会丢弃整个应用程序。您可以轻松地插入视图或轻松删除它们而不会破坏应用程序。



这当然是一个微不足道的例子,但它显示了良好的做法。



但是,你可能会问,这是如何解决tableview知道要加载什么数据以及何时加载它的问题?很简单,它没有。知道要加载什么数据或何时加载,不是tableview的工作。数据模型处理what-data和tableview控制器处理何时。 (您甚至可以在更新数据模型时发出通知,例如对于网址。然后视图控制器可以注册通知并在数据模型更改时调用 reloadData 。 )



通过在MVC中无情地划分和封装功能,您可以从易于维护和调试的简单,可重用组件创建复杂的应用程序。



对于大多数教学材料而言,实际上只是为这个完全关键的概念付出代价。


It bugs me to death that my viewcontroller, which happens to be a tableViewController, knows without being told that its property that is an NSArray or an NSDictionary holds the data that is to be loaded into the table for display.

Seems like I should explicitly say something like:

[self.tableView useData:self.MyArray];

I want to have more than one array inside my tableViewController and switch between one and the other programmatically.

I notice that when a tableViewController makes use of a searchViewController, you can do this:

if (tableView == self.searchDisplayController.searchResultsTableView) {

I have even been able to do this:

self.tableView =  self.searchDisplayController.searchResultsTableView;
[self.tableView reloadData];

But nowhere can I find how to set self.tableView back to the main datasource!

解决方案

Okay, I understand your frustrations because the vast majority of iPhone instructional material do not pay sufficient attention to overall app design. They make a beeline for the eye candy interface and pay only lip service to way that the app should handle the data even though handling data is the entire purpose of the app in the first place!

The instructional materials do not spend enough time explaining the Model-View-Controller design pattern on which the entire iPhone/Cocoa API is based. You're having a hard time understanding anything because you keep trying to cram functionality into the wrong objects under the mistaken belief that the UI view is the core of the program as the instructional materials have led you to believe. Under this misapprehension, nothing makes sense, not even the Apple Documentation.

You need to step back and rethink. It is not the function of a view to decide what data to display and when to display it. It is not the function of the table view controller to hold, manage or store the app's data. Those functions properly belong to the data model object (which you've possibly never heard of.) You're having trouble because you are trying to split the data model task across the view and the view controller were they do not belong.

Apparently, your app doesn't even have a data model because you are holding the table's data as properties of the tableview controller. Although you often see this in simplistic tutorial examples, it is bad design which will collapse under the complexity of any but the most trivial apps.

Instead, your data should be stored in and managed in its own custom object. This is the data model. In your case, it sounds like you have data spread across two arrays so you would create a data model object something like this:

@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;
    }
}

(Notice that the actual data is encapsulated and that other objects can only access the currentlyUsedArray. The data model decides which data to provide based on the internal state of the data.)

This data model object should be in a universally accessible location. The best method is to make it a singleton but the quick and dirty method is to park it as an attribute of the app delegate.

So in you tableview controller you would have a property:

MyDataModel *theDataModel;
@property (nonatomic, retain) MyDataModel *theDataModel;

then in the implementation

@synthesize theDataModel;

-(MyDataModel *) theDataModel; {
    if (theDataModel; !=nil) {
        return theDataModel; ;
    }
    id appDelegate=[[UIApplication sharedApplication] delegate];
    self.theDataModel=appDelegate.theDataModelProperty;
    return theDataModel;
}

Then in your tableview datasource method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    ...
    cell.textLabel.text=[self.theDataModel.currentlyUsedArray objectAtIndex:indexPath.row];
    return cell;
}

If some event anywhere in the app requires you to switch arrays, you just call up the data model object from the app delegate and send it the appropriate switch array message.

id appDelegate=[[UIApplication sharedApplication] delegate];
[appDelegate.theDataModelProperty toggleUsedArray];

Now all subsequent data operations, whether in that particular table view or some other completely unrelated view, will use the data form the proper array.

Why go through all this trouble? It makes the application modular. You can easily add on different views each of which display the data in a different manner without having to rewrite your data management every single time. You can use the data model to manage data that will be displayed in a table, in a webview or on the command line. You can even easily move the data model to an entirely different app.

This modularity makes the management of large complex apps so much easier. You have only one object that manipulates and controls the data. You don't have to worry that some minor error in some rarely used code segment will trash the entire app. You can plugin views easily or remove them easily without breaking the app.

This is of course a trivial example but it shows good practice.

However, you may ask, how does this solve the problem of the tableview knowing what data to load and when to load it? Simple, it doesn't. It is not the job of the tableview to know what data to load or when to load. The data model handles the what-data and tableview controller handles the when. (You can even have the data model issue notifications when it is updated e.g. for a url. then the view controller can register for the notification and call reloadData whenever the data model changes.)

By ruthlessly compartmentalizing and encapsulating functionality in MVC, you create complex apps from simple, reusable components that are easy to maintain and debug.

It's really to bad most instructional materials only pay lip service to this utterly critical concept.

这篇关于[self.tableView reloadData]如何知道要重载的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆