使用Swift编程以编程方式返回到上一个ViewController

261

当用户点击按钮时,我会将用户发送到一个页面。这个页面是一个UITableViewController

现在,如果用户点击单元格,我希望将其推回到上一个页面。

我考虑过像self.performSegue("back")....这样的方法,但这似乎是个坏主意。

正确的做法是什么?


15
self.navigationController?.popViewControllerAnimated(true)翻译:使用该代码可以让当前视图控制器返回上一个视图控制器。 - Kalpesh
16个回答

628

Swift 3:

如果您想返回到上一个视图控制器

_ = navigationController?.popViewController(animated: true)

如果您想返回到根视图控制器

_ = navigationController?.popToRootViewController(animated: true)

如果您没有使用导航控制器,请使用以下代码。

self.dismiss(animated: true, completion: nil)

动画值可以根据您的要求进行设置。


1
当单元格被点击时,如果我们使用navigationController?.popViewControllerAnimated(true),那么如何将数据发送回previousController? - JDDelgado
4
这是您如何将数据与用户一起发送回去的方法,https://dev59.com/SGcs5IYBdhLWcg3w0HIa - Mohamad Kaakati
36
对于Swift 3来说,它是.popViewController(animated: true) - Sasho
10
为了消除任何警告:_ = self.navigationController?.popToRootViewController(animated: true)。翻译说明: 这是一行 Swift 代码,它的作用是将当前视图控制器导航到其根视图控制器。该代码中的问号表示 navigationController 属性可能为空,popToRootViewController 是导航控制器的一个方法,通过传递 animated: true 参数来启用动画效果。在这里,下划线 _ 表示我们不需要使用这个方法返回的任何值。 - Andrew K
1
我们正在忽略返回值;在Swift中,_ = 是惯例。 - Andrew K
显示剩余5条评论

62

Swift 3Swift 4

if movetoroot { 
    navigationController?.popToRootViewController(animated: true)
} else {
    navigationController?.popViewController(animated: true)
}

navigationController是可选的,因为可能不存在。


@Vyacheslva 我遇到了一个错误:“在闭包中隐式使用了 'seft',请使用 'self' 来明确捕获语义”。 - Sandip Subedi
@SandipSubedi 使用[weak self]self?.navigationController?. - Vyacheslav
这很有用,但我想在导航时发送一些变量,但现在我不能 - 我使用了 { if let vc = segue.destination as?``` 但当我使用它时,我不能使用那个。 - Saeed Rahmatolahi
如何添加 navigationController 呢? - user25
@user25添加?你是什么意思? - Vyacheslav
@user25,“navigationController”隐式地引用了“self.navigationController”,因此您需要实现“UINavigationControllerDelegate”才能使用它。 - MK Yung

41

Swift 5及以上版本

案例1:与导航控制器一起使用

返回到上一个视图控制器
self.navigationController?.popViewController(animated: true)
返回到根视图控制器
self.navigationController?.popToRootViewController(animated: true)
案例2:与当前视图控制器一起使用
self.dismiss(animated: true, completion: nil)

40

Swift 3

我可能回答晚了,但对于Swift 3,您可以按照以下方法操作:

override func viewDidLoad() {
    super.viewDidLoad()

    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "< Back", style: .plain, target: self, action: #selector(backAction))

    // Do any additional setup if required.
}

func backAction(){
    //print("Back Button Clicked")
    dismiss(animated: true, completion: nil)
}

3
这并不是“完全正确”的。如果你推出一个包含自己导航的视图控制器,并在推出另一个视图控制器后使用dismiss:方法,它不仅会关闭当前的视图控制器,还会关闭根视图控制器,这并不是被要求的结果。 - Ernesto Fernandez
2
问题没有询问用户是否拥有导航控制器。这是没有导航控制器的最简单和最佳答案。这确实应该成为被接受的答案。 - Droid Chris
谢谢Droid - 嗨ernestofndz,你说rootVC也会被解散可能是对的,但这在我这里并没有发生,它只解散了当前的VC,我是通过编程方式添加和删除项目的,这可能与在storyboard上正常添加元素的方法不同...如果我理解有误,请纠正我的理解...对于tableView,如果用户需要将详细信息传递给另一个视图,则这是另一种情况,与我发布的内容没有关联,我完全同意你的看法..。我理解的是,在这种情况下需要一个返回按钮 :) - Fullpower
或许您可以加一点介绍...因为存在dismiss和navigationController?.popViewController? - marlonpya
旋转后dismiss(animated: true, completion: nil)无法工作! - user924
如果您没有使用序列,而是通过引用故事板和其中的视图控制器来进行操作,那么它的效果非常好。 - DragonFire

38

Swift 4

有两种方法返回到前一个ViewController:

  1. 第一种情况:如果你使用了:self.navigationController?.pushViewController(yourViewController, animated: true),在这种情况下,你需要使用self.navigationController?.popViewController(animated: true)
  2. 第二种情况:如果你使用了:self.present(yourViewController, animated: true, completion: nil),在这种情况下,你需要使用self.dismiss(animated: true, completion: nil)

在第一种情况下,请确保在你的storyboard中将ViewController嵌入到navigationController中


24

如果您在一个UIViewController中呈现了另一个UIViewController,也就是说...

// Main View Controller
self.present(otherViewController, animated: true)

只需调用 dismiss 函数:

// Other View Controller
self.dismiss(animated: true)

self.dismiss(animated: true) - 旋转后无法工作 - user924

11
如果 Segue 是“Show”或“Push”的类型,则可以在 UINavigationController 实例上调用“popViewController(animated: Bool)”方法。如果 segue 是“present”的类型,则使用 UIViewController 的实例调用“dismiss(animated: Bool, completion: (() -> Void)?)”方法。请保留所有 html 标签和格式。

7

对于Swift 3,您只需要编写以下代码行:

_ = navigationController?.popViewController(animated: true)

4

这个对我有效(Swift UI)

struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

  var body: some View {
      VStack {
        Text("This is the detail view")
        Button(action: {
          self.presentationMode.wrappedValue.dismiss()
        }) {
          Text("Back")
        }
      }
    }
}

3
尝试这样做: 对于先前的视图,请使用以下内容:
navigationController?.popViewController(animated: true)  

使用以下代码返回到根视图:

navigationController?.popToRootViewController(animated: true) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接