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

时间:2016-01-24 04:38:35

标签: ios swift back-button viewdidload viewdidappear

前三个答案可以解决我的问题。很难选择哪一个是最好的。所以,我只选择那个第一个回答我问题的人。对不起业余爱好者和iOSEnthusiatic。谢谢您的帮助。我很感激。

enter image description here

ViewController 1有一个表视图。

我的问题是,只有当我从视图控制器2中单击后退时才重新加载表视图,如果我从视图控制器3单击后退,则不重新加载表视图。

现在,我的后退代码是

@IBAction func backButtonTapped(sender: AnyObject) {
    self.dismissViewControllerAnimated(true, completion: nil)
}

在视图控制器1中。我知道表视图将从视图控制器2或3重新加载

override func viewDidAppear(animated: Bool) {
    loadTable()
}

我试图在viewDidLoad中放入loadTable()并尝试在视图控制器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

3 个答案:

答案 0 :(得分:3)

这是我几天前回答的问题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)
}

答案 1 :(得分:2)

如果vc1执行显示vc2并且始终确保使vc1中的数据无效,则可以执行以下操作:

  • needsReload布尔实例变量添加到vc1
  • 每当您显示vc2时(以及如果来自故事板,在awakeFromNib中实例化vc1时)将其设置为true。
  • 如果needsReload为true,则
  • 仅执行loadTable的内容(可能将此逻辑重构为loadTableIfNeeded
  • 不要忘记在needsReload
  • 的末尾将loadTableIfNeeded设置为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

答案 2 :(得分:1)

您可以轻松使用通知方法。

在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时,分别从第2和第3个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)])