如果从不同的视图控制器按下返回,则重新加载而不重新加载。迅速

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 添加类

使用子视图中的数据重新加载 tableview

当收到新消息而不重新加载视图时,如何将来自 stomp 客户端的消息显示到视图中

在UITableViewCell上设置编辑样式而不重新加载单元格

重新渲染视图而不重新加载/刷新 AngularJS 应用程序