如果从不同的视图控制器按下返回,则重新加载而不重新加载。迅速
Posted
技术标签:
【中文标题】如果从不同的视图控制器按下返回,则重新加载而不重新加载。迅速【英文标题】:Reload and not reload if press back from different view controllers. Swift 【发布时间】:2016-01-24 04:38:34 【问题描述】:前三个答案可以解决我的问题。很难选择哪一个是最好的。所以,我只选择第一个回答我问题的人。对不起业余爱好者和 ios 爱好者。感谢您的帮助。我很感激。
ViewController 1 有一个表格视图。
我的问题是如何仅在我从视图控制器 2 中单击返回时重新加载表视图,如果我从视图控制器 3 中单击返回则不重新加载表视图。
现在,我的后退按钮代码是
@IBAction func backButtonTapped(sender: AnyObject)
self.dismissViewControllerAnimated(true, completion: nil)
在视图控制器 1 中。我知道表格视图将从视图控制器 2 或 3 重新加载
override func viewDidAppear(animated: Bool)
loadTable()
我尝试将 loadTable() 放入 viewDidLoad 并尝试为视图控制器 2 中的后退按钮编写以下代码。但是,它不起作用。
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("UserHomePageViewController") as! UserHomePageViewController
controller.viewDidLoad()
有什么建议吗?感谢您的帮助。
编辑:
我认为这是一种更简单的方法,但它仍然无法像我想象的那样工作。我猜是因为 viewDidAppear 是在调用 reloadTableBool 之前执行的。正确的?有什么办法可以解决吗?谢谢你。您的帮助将不胜感激。
class 2ViewController
@IBAction func backButtonTapped(sender: AnyObject)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("1ViewController") as! 1ViewController
print("viewcontroller2 before call: \(controller.reloadTableBool)")
controller.reloadTableBool = false
print("viewcontroller2 after call: \(controller.reloadTableBool)")
self.dismissViewControllerAnimated(true, completion: nil)
class 1ViewController
var reloadTableBool = true
override func viewDidAppear(animated: Bool)
print("viewcontroller1: \(reloadTableBool)")
if reloadTableBool == true
loadTable()
当我返回视图控制器 2 时,它会打印
viewcontroller2 before call: true
viewcontroller2 after call: false
viewcontroller1: true
【问题讨论】:
您是使用从导航控制器获得的后退按钮,还是创建了一个并手动添加? 我将一个 Bar Button Item 拖到导航栏并为该按钮创建一个函数作为“返回”。我想我是手动创建的。 在您的屏幕截图中,它显示您正在使用导航控制器。为什么不使用内置返回按钮? 嗯。不知道如何使用内置。哈哈 嗯,这有点自动 :p 不管怎样,我已经更新了我的答案。 【参考方案1】:这是我几天前回答的问题的link。使用导航控制器委托来处理后退按钮。在您的第二个视图控制器中,将委托设置为 self 并在您按下后退按钮时重新加载 tableview。
override func viewDidLoad()
super.viewDidLoad()
navigationController?.delegate = self
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool)
if let controller = viewController as? FirstViewController
controller.tableView.reloadData()
注意: 我假设你在这里使用导航控制器的后退按钮。
编辑:使用手动添加的后退按钮的另一个示例:
@IBAction func backButtonTapped(sender: AnyObject)
if let viewControllers = app.window?.rootViewController?.childViewControllers
viewControllers.forEach ($0 as? FirstViewController)?.tableView.reloadData()
self.dismissViewControllerAnimated(true, completion: nil)
当您使用导航控制器时:
@IBAction func backButtonTapped(sender: AnyObject)
navigationController?.viewControllers.forEach ($0 as? FirstViewController)?.tableView.reloadData()
self.dismissViewControllerAnimated(true, completion: nil)
【讨论】:
嗨。你介意看看我的编辑吗?我认为这样做更简单,因为我可以只使用 Bool,但似乎 viewDidAppear 是在调用 reloadTableBool 之前执行的? 实际上,与每次导航回第一个视图时必须记住发送Bool
相比,我的方法应该是最简单且可以说是最干净的方法。我的任何建议有效吗?我现在看看你的编辑。
Bool
不起作用的原因是因为您正在创建 UserHomePageViewController
的新实例并仅为该实例更改内容。您想要的是更改现有UserHomePageViewController
实例中的Bool
。使用我的示例,如果您坚持使用 Bool
,则将 table view reload 替换为 Bool
。
奥普斯。 UserHomePageViewController 是 1 类视图控制器。我忘记改了。我只是想让我的代码更容易阅读。哈哈。我现在正在查看您的代码。【参考方案2】:
如果显示 vc2 是 vc1 执行的,并且总是确保 vc1 中的数据无效,您可以执行以下操作:
将needsReload
布尔实例变量添加到vc1
在显示 vc2 时将其设置为 true(以及在实例化 vc1 时,例如,如果来自故事板,则在 awakeFromNib
中)
只有在 needsReload 为真时才执行loadTable
的内容(也许将此逻辑重构为loadTableIfNeeded
)
不要忘记在loadTableIfNeeded
末尾设置needsReload
为false
这种失效模式在整个 UIKit 中都可以找到,例如 UIView setNeedsLayout
/layoutIfNeeded
。这样做的好处是,即使有几个事件导致数据失效,它也只会在您需要时才会真正刷新。
在您的情况下,它具有将逻辑包含在 vc1 中的额外优势,并且不会在您的 VC 之间创建不必要的耦合,这总是好的。
---更新:示例实现(ObjC,但你会明白的)
你只需要在 VC1 中处理这个,忘记 VC2 中的所有后退按钮。此实现将在 VC2 出现后立即将 VC1 标记为重新加载,但实际上只会在 viewWillAppear 上重新加载,此时 VC2 被关闭。
---更新 2:添加了基于委托回调的条件重新加载
请注意,_needsReload
现在是在委托回调中设置的,而不是在首次呈现 VC2 时设置的。相反,我们将 VC1 设置为 VC2 的委托。 (_needsReload
这个方法其实不需要逻辑,留作参考)
//VC2: add a delegate to the interface
@class VC2;
@protocol VC2Delegate
- (void) viewController:(VC2*)myVC2 didFinishEditingWithChanges:(BOOL)hasChanges;
@end
@interface VC2
@property (nonatomic, weak) id<VC2Delegate> delegate
@end
@implementation VC2
- (IBAction) finishWithChanges
[self.delegate viewController:self didFinishEditingWithChanges:YES];
- (IBAction) finishWithoutChanges
[self.delegate viewController:self didFinishEditingWithChanges:NO];
@end
//VC1: implement the VC2Delegate protocol
@interface VC1 () <VC2Delegate>
@end
@implementation VC1
BOOL _needsReload
- (void) awakeFromNib
//adding this for completeness but the way you did it in Swift (at init) is correct
[super awakeFromNib];
_needsReload = YES;
- (void) viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
[self reloadTableIfNeeded];
- (IBAction) displayVC2
VC2* myVC2 = ... //instanciate your VC2 here
myVC2.delegate = self; //set as the delegate of VC2
[self presentViewController:myVC2 animated:YES completion:nil];
- (void) viewController:(VC2*)myVC2 didFinishEditingWithChanges:(BOOL)hasChanges
_needsReload = hasChanges;
[self reloadTableIfNeeded];
- (void) reloadTableIfNeeded
if (_needsReload)
[self.tableView reloadData];
_needsReload = NO;
@end
【讨论】:
我也这样做了,但似乎 viewDidAppear 是在调用 reloadTableBool 之前执行的。你介意看看我的更新吗? 我明白了。工作。谢谢你的帮助:) 好消息。如果您接受了我的回答,那将是更好的消息,但仍然:-) 还有一个问题。如果我想从 display2 分配一个值以告诉 display1 是否应该像我在 EDIT 中尝试编码的那样重新加载表格视图,这可能吗? 是的,例如使用委托模式是可能的。看我的更新。希望你在 Swift 上不会遇到太多麻烦。【参考方案3】:您可以轻松地为此使用通知方法。
在 viewDidLoad 方法的第一个 ViewController 中添加观察者。
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reloadTable:", name: "reloadTable", object: nil)
func reloadTable(notification : NSNotification)
let isReload : NSNumber = notification.userInfo!["isReload"] as! NSNumber
if (isReload.boolValue)
self.tableView.reloadData()
然后当你调用dismissViewController时,分别从你的第二个和第三个ViewController发布这样的通知。
// From 2nd viewcontroller
NSNotificationCenter.defaultCenter().postNotificationName("reloadTable", object: nil, userInfo: ["isReload" : NSNumber(bool: false)])
// From 3rd viewcontroller
NSNotificationCenter.defaultCenter().postNotificationName("reloadTable", object: nil, userInfo: ["isReload" : NSNumber(bool: true)])
【讨论】:
不!您应该使用这种方法来达到预期的效果。 嗯。对不起。我不太了解目标 C 对不起,它的 reloadData()。请立即检查答案。谢谢 我有两个错误。 1. 无法识别的选择器发送到实例 0x7fb61283a000 2. 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-以上是关于如果从不同的视图控制器按下返回,则重新加载而不重新加载。迅速的主要内容,如果未能解决你的问题,请参考以下文章
如果 localStorage 值存在而不重新加载页面,则 Javascript 添加类
当收到新消息而不重新加载视图时,如何将来自 stomp 客户端的消息显示到视图中