My goal is to notify a UITableView to refresh itself every time some configurations have changed. The problem is that the configuration view is "not" on the same view that produces the signal. (Yes, I used Tabbed Application.)
我的目标是每次更改某些配置时通知UITableView刷新自己。问题是配置视图在产生信号的同一视图上“不”。 (是的,我使用了Tabbed应用程序。)
Currently I use a sort of global variable in AppDelegate for detecting the change in one view, and do the check in another view. This is fine but the code is not readable as it is so tightly coupling. Is there an elegant method for doing this? Do I miss something in this programming framework?
目前,我在AppDelegate中使用一种全局变量来检测一个视图中的更改,并在另一个视图中执行检查。这很好,但代码不可读,因为它是如此紧密耦合。这样做有一种优雅的方法吗?我在这个编程框架中是否遗漏了什么?
If there were such an elegant way, I suppose the refreshing process of UITableView should happen as soon as the notification occurs. In this case, I would like to know whether it's possible to delay UITableView from refreshing itself until viewDidAppear occurs.
如果有这么优雅的方式,我想UITableView的刷新过程应该在通知发生时立即发生。在这种情况下,我想知道是否有可能延迟UITableView刷新自己,直到发生viewDidAppear。
4 个解决方案
#1
2
I would use KVO (Key Value Observing) to keep track of when it changes:
我会使用KVO(键值观察)来跟踪它何时发生变化:
- (void)viewDidLoad {
[super viewDidLoad];
// Note that you can use the options to get the new value passed when it
// changes if you want to update immediately.
[configurationObject addObserver:self forKeyPath:@"configurationItem" options:0 context:nil];
}
- (void)viewDidUnload {
[super viewDidUnload];
[configurationObject removeObserver:self forKeyPath:@"configurationItem"];
}
// Note that I would refresh in viewWillAppear instead of viewDidAppear
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.needToRefreshData == YES) {
[self.tableView refreshData];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (keyPath isEqualToString:@"configurationItem") {
[self.needToRefreshData = YES];
}
}
#2
2
Use Delegation Design Pattern to pass data from one View Controller to the Other.
使用委托设计模式将数据从一个View Controller传递到另一个。
For example, let's say one Tab shows a list of cars in a UITableViewController and you have another view that let's a user add a new car to the list. You can let the UITableViewController
例如,假设一个选项卡显示UITableViewController中的汽车列表,并且您有另一个视图,让用户将新汽车添加到列表中。你可以让UITableViewController
- Adopt AddCarViewController's protocol
- Set itself as a Delegate for AddCarViewController's protocol
- Implement its protocol method
- Execute the protocol method when informed
采用AddCarViewController的协议
将自己设置为AddCarViewController协议的委托
实现其协议方法
通知后执行协议方法
You can then let the AddCarViewController
然后你可以让AddCarViewController
- Create a Protocol
- Declare object reference Delegate with getter and setter methods
- Define a method under that protocol
- Inform the Delegate when the Save action is performed
创建协议
使用getter和setter方法声明对象引用Delegate
根据该协议定义方法
执行保存操作时通知代理
Take a look at the following sample code for your UITableViewController
查看UITableViewController的以下示例代码
@interface ViewController : UITableViewController <AddCarViewControllerDelegate>
:
:
// The addCar: method is invoked when the user taps the Add button created at run time.
- (void)addCar:(id)sender
{
// Perform the segue named ShowAddCar
[self performSegueWithIdentifier:@"ShowAddCar" sender:self];
}
:
:
// This method is called by the system whenever you invoke the method performSegueWithIdentifier:sender:
// You never call this method. It is invoked by the system.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString *segueIdentifier = [segue identifier];
if ([segueIdentifier isEqualToString:@"ShowAddCar"]) {
// Obtain the object reference of the destination view controller
AddCarViewController *addCarViewController = [segue destinationViewController];
// Under the Delegation Design Pattern, set the addCarViewController's delegate to be self
addCarViewController.delegate = self;
// Instantiate a Save button to invoke the save: method when tapped
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:addCarViewController action:@selector(save:)];
// Set up the Save custom button on the right of the navigation bar
addCarViewController.navigationItem.rightBarButtonItem = saveButton;
}
}
:
:
- (void)addCarViewController:(AddCarViewController *)controller didFinishWithSave: (BOOL)save {
:
:
}
Sample code for the AddCarViewController is here
AddCarViewController的示例代码在这里
@protocol AddCarViewControllerDelegate;
@interface AddCarViewController : UIViewController
@property (nonatomic, strong) IBOutlet UITextField *carMake;
@property (nonatomic, strong) IBOutlet UITextField *CarName;
@property (nonatomic, assign) id <AddCarViewControllerDelegate> delegate;
// The keyboardDone: method is invoked when the user taps Done on the keyboard
- (IBAction)keyboardDone:(id)sender;
// The save: method is invoked when the user taps the Save button created at run time.
- (void)save:(id)sender;
@end
/*
The Protocol must be specified after the Interface specification is ended.
Guidelines:
- Create a protocol name as ClassNameDelegate as we did above.
- Create a protocol method name starting with the name of the class defining the protocol.
- Make the first method parameter to be the object reference of the caller as we did below.
*/
@protocol AddCarViewControllerDelegate
- (void)addCarViewController:(AddCarViewController *)controller didFinishWithSave:(BOOL)save;
@end
#3
1
Well, one approach would be to have some common class (singleton perhaps which app delegate kind of is) that keeps track of your model, when the settings viewController detects a change it can mark the model as changed, then when the view in question comes in to view, ie, viewDidAppear gets called, it can query the model to see if the changed flag has been set, if it has then you know to reload the table view, otherwise you dont...
好吧,一种方法是使用一些公共类(单例或类似于app委托类型)来跟踪你的模型,当设置viewController检测到变化时它可以将模型标记为已更改,然后当有问题的视图出现时在查看中,即viewDidAppear被调用,它可以查询模型以查看是否已设置更改的标志,如果已经知道重新加载表视图,否则你不...
Another way could be to use notification center for it, if your view is loaded it can sign up for the notifications of the model change, in which at point it sets a flag that it needs to reload the table view next time it comes on screen..
另一种方法是使用通知中心,如果您的视图已加载,它可以注册模型更改的通知,在此点它设置一个标志,它需要在下次屏幕上重新加载表视图..
hope this helps
希望这可以帮助
#4
1
You could store the configuration in core data and use an NSFetchedResultsController with the dependant view controller set as a delegate. This way your view controller will get a callback whenever the data is changed.
您可以将配置存储在核心数据中,并使用NSFetchedResultsController并将从属视图控制器设置为委托。这样,只要数据发生更改,视图控制器就会收到回调。
Apple has some boilerplate code to handle the updates as well
Apple也有一些样板代码来处理更新
#1
2
I would use KVO (Key Value Observing) to keep track of when it changes:
我会使用KVO(键值观察)来跟踪它何时发生变化:
- (void)viewDidLoad {
[super viewDidLoad];
// Note that you can use the options to get the new value passed when it
// changes if you want to update immediately.
[configurationObject addObserver:self forKeyPath:@"configurationItem" options:0 context:nil];
}
- (void)viewDidUnload {
[super viewDidUnload];
[configurationObject removeObserver:self forKeyPath:@"configurationItem"];
}
// Note that I would refresh in viewWillAppear instead of viewDidAppear
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.needToRefreshData == YES) {
[self.tableView refreshData];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (keyPath isEqualToString:@"configurationItem") {
[self.needToRefreshData = YES];
}
}
#2
2
Use Delegation Design Pattern to pass data from one View Controller to the Other.
使用委托设计模式将数据从一个View Controller传递到另一个。
For example, let's say one Tab shows a list of cars in a UITableViewController and you have another view that let's a user add a new car to the list. You can let the UITableViewController
例如,假设一个选项卡显示UITableViewController中的汽车列表,并且您有另一个视图,让用户将新汽车添加到列表中。你可以让UITableViewController
- Adopt AddCarViewController's protocol
- Set itself as a Delegate for AddCarViewController's protocol
- Implement its protocol method
- Execute the protocol method when informed
采用AddCarViewController的协议
将自己设置为AddCarViewController协议的委托
实现其协议方法
通知后执行协议方法
You can then let the AddCarViewController
然后你可以让AddCarViewController
- Create a Protocol
- Declare object reference Delegate with getter and setter methods
- Define a method under that protocol
- Inform the Delegate when the Save action is performed
创建协议
使用getter和setter方法声明对象引用Delegate
根据该协议定义方法
执行保存操作时通知代理
Take a look at the following sample code for your UITableViewController
查看UITableViewController的以下示例代码
@interface ViewController : UITableViewController <AddCarViewControllerDelegate>
:
:
// The addCar: method is invoked when the user taps the Add button created at run time.
- (void)addCar:(id)sender
{
// Perform the segue named ShowAddCar
[self performSegueWithIdentifier:@"ShowAddCar" sender:self];
}
:
:
// This method is called by the system whenever you invoke the method performSegueWithIdentifier:sender:
// You never call this method. It is invoked by the system.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString *segueIdentifier = [segue identifier];
if ([segueIdentifier isEqualToString:@"ShowAddCar"]) {
// Obtain the object reference of the destination view controller
AddCarViewController *addCarViewController = [segue destinationViewController];
// Under the Delegation Design Pattern, set the addCarViewController's delegate to be self
addCarViewController.delegate = self;
// Instantiate a Save button to invoke the save: method when tapped
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:addCarViewController action:@selector(save:)];
// Set up the Save custom button on the right of the navigation bar
addCarViewController.navigationItem.rightBarButtonItem = saveButton;
}
}
:
:
- (void)addCarViewController:(AddCarViewController *)controller didFinishWithSave: (BOOL)save {
:
:
}
Sample code for the AddCarViewController is here
AddCarViewController的示例代码在这里
@protocol AddCarViewControllerDelegate;
@interface AddCarViewController : UIViewController
@property (nonatomic, strong) IBOutlet UITextField *carMake;
@property (nonatomic, strong) IBOutlet UITextField *CarName;
@property (nonatomic, assign) id <AddCarViewControllerDelegate> delegate;
// The keyboardDone: method is invoked when the user taps Done on the keyboard
- (IBAction)keyboardDone:(id)sender;
// The save: method is invoked when the user taps the Save button created at run time.
- (void)save:(id)sender;
@end
/*
The Protocol must be specified after the Interface specification is ended.
Guidelines:
- Create a protocol name as ClassNameDelegate as we did above.
- Create a protocol method name starting with the name of the class defining the protocol.
- Make the first method parameter to be the object reference of the caller as we did below.
*/
@protocol AddCarViewControllerDelegate
- (void)addCarViewController:(AddCarViewController *)controller didFinishWithSave:(BOOL)save;
@end
#3
1
Well, one approach would be to have some common class (singleton perhaps which app delegate kind of is) that keeps track of your model, when the settings viewController detects a change it can mark the model as changed, then when the view in question comes in to view, ie, viewDidAppear gets called, it can query the model to see if the changed flag has been set, if it has then you know to reload the table view, otherwise you dont...
好吧,一种方法是使用一些公共类(单例或类似于app委托类型)来跟踪你的模型,当设置viewController检测到变化时它可以将模型标记为已更改,然后当有问题的视图出现时在查看中,即viewDidAppear被调用,它可以查询模型以查看是否已设置更改的标志,如果已经知道重新加载表视图,否则你不...
Another way could be to use notification center for it, if your view is loaded it can sign up for the notifications of the model change, in which at point it sets a flag that it needs to reload the table view next time it comes on screen..
另一种方法是使用通知中心,如果您的视图已加载,它可以注册模型更改的通知,在此点它设置一个标志,它需要在下次屏幕上重新加载表视图..
hope this helps
希望这可以帮助
#4
1
You could store the configuration in core data and use an NSFetchedResultsController with the dependant view controller set as a delegate. This way your view controller will get a callback whenever the data is changed.
您可以将配置存储在核心数据中,并使用NSFetchedResultsController并将从属视图控制器设置为委托。这样,只要数据发生更改,视图控制器就会收到回调。
Apple has some boilerplate code to handle the updates as well
Apple也有一些样板代码来处理更新