Khởi tạo và trình bày một viewContoder trong Swift


300

Vấn đề

Tôi bắt đầu tham gia một cái nhìn mới Swiftvề Xcode 6, và tôi đã cố gắng một số dự án trình diễn và hướng dẫn. Bây giờ tôi bị mắc kẹt tại:

Khởi tạo và sau đó trình bày viewControllertừ một bảng phân cảnh cụ thể

Giải pháp khách quan-C

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"myStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"myVCID"];
[self presentViewController:vc animated:YES completion:nil];

Làm thế nào để đạt được điều này trên Swift?

Câu trả lời:


648

Câu trả lời này đã được sửa đổi lần cuối cho Swift 5.2 và iOS 13.4 SDK.


Tất cả chỉ là vấn đề về cú pháp mới và các API được sửa đổi một chút. Các chức năng cơ bản của UIKit đã không thay đổi. Điều này đúng với phần lớn các khung SDK iOS.

let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "myVCID")
self.present(vc, animated: true)

Nếu bạn gặp vấn đề với init(coder:), vui lòng tham khảo câu trả lời của EridB .


3
Bạn thậm chí có thể bỏ qua ;! ;) Bạn có muốn giải thích chi tiết về as UIViewController? Tại sao điều đó là cần thiết?
Sebastian Wramba

5
astừ khóa được sử dụng để đánh máy. Nó giống như (UIViewController *)anObjecttrong mục tiêu c
Garoal

1
Vâng tôi biết tôi có thể bỏ qua chúng nhưng đó là một phần của tiếng cười dài. : D Như instantiateViewControllerWithIdentifierlợi nhuận AnyObject( idtương đương trong Swift) và tôi tuyên bố vcnhư UIViewController, tôi phải định kiểu AnyObjectđể UIViewController.
akashivskyy

Xin chào các bạn, tôi đang gặp một số vấn đề khác, Mã này chạy trên trình giả lập không có trên ipad2 của tôi có iOS v7.1.2. Nếu bạn không phiền hãy giúp tôi giải quyết vấn đề này.
Indra

3
@akashivskyy Chắc chắn nhất, với bạn. Nhưng có lẽ không phải với một số.
mmc

43

Đối với những người sử dụng câu trả lời của @ akashivskyy để khởi tạo UIViewControllervà đang có ngoại lệ:

lỗi nghiêm trọng: sử dụng trình khởi tạo chưa được thực hiện 'init (coder :)' cho lớp

Mẹo nhanh:

Thực hiện thủ công required init?(coder aDecoder: NSCoder)tại điểm đến của bạn UIViewControllermà bạn đang cố gắng khởi tạo

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

Nếu bạn cần thêm mô tả xin vui lòng tham khảo câu trả lời của tôi ở đây


Nếu bạn muốn sử dụng bộ khởi tạo tùy chỉnh, bạn có thể chỉ cần gọi super bằng super.init (nibName: nil, bundle: nil) và whew sẽ tải tốt hoặc gọi nó bằng tên của tệp NIB.
dùng1700737

4
@ user1700737 Tôi đang khởi tạo viewContoder đề cập đến bảng phân cảnh, thực thi initWithCoder, không phải initWithNib. Tham khảo câu hỏi này stackoverflow.com/questions/24036393/ Cách
E-Riddie

Xin chào các bạn, tôi đang gặp một số vấn đề khác, Mã này chạy trên trình giả lập không có trên ipad2 của tôi có iOS v7.1.2. Nếu bạn không phiền hãy giúp tôi giải quyết vấn đề này.
Indra

@ Ấn Độ bạn cần đặt một câu hỏi khác trên stack, hãy cho tôi đường dẫn Ill rất vui lòng giúp bạn!
E-Riddie

Trên Swift 1.2, bạn phải thực hiện init(coder aDecoder: NSCoder!)"bắt buộc". Vì vậy, bây giờ bạn phải viết như sau:required init(coder aDecoder: NSCoder!)
Eduardo Viegas

18

Liên kết này có cả việc triển khai:

Nhanh:

let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
self.presentViewController(viewController, animated: false, completion: nil)

Mục tiêu C

UIViewController *viewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"];

Liên kết này có mã để khởi tạo trình điều khiển khung nhìn trong cùng một bảng phân cảnh

/*
 Helper to Switch the View based on StoryBoard
 @param StoryBoard ID  as String
*/
func switchToViewController(identifier: String) {
    let viewController = self.storyboard?.instantiateViewControllerWithIdentifier(identifier) as! UIViewController
    self.navigationController?.setViewControllers([viewController], animated: false)

}

15

câu trả lời của akashivsky chỉ hoạt động tốt! Nhưng, trong trường hợp bạn gặp một số khó khăn khi quay lại từ trình điều khiển xem được trình bày, sự thay thế này có thể hữu ích. Nó làm việc cho tôi!

Nhanh:

let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController
// Alternative way to present the new view controller
self.navigationController?.showViewController(vc, sender: nil)

Obj-C:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"someViewController"];
[self.navigationController showViewController:vc sender:nil];

12

Mã cập nhật Swift 4.2 là

let storyboard = UIStoryboard(name: "StoryboardNameHere", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerNameHere")
self.present(controller, animated: true, completion: nil)

7
// "Main" is name of .storybord file "
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// "MiniGameView" is the ID given to the ViewController in the interfacebuilder
// MiniGameViewController is the CLASS name of the ViewController.swift file acosiated to the ViewController
var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MiniGameView") as MiniGameViewController
var rootViewController = self.window!.rootViewController
rootViewController?.presentViewController(setViewController, animated: false, completion: nil)

Điều này làm việc tốt với tôi khi tôi đặt nó trong AppDelegate


7

Nếu bạn muốn trình bày nó một cách vừa phải, bạn nên có một cái gì đó như dưới đây:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewControllerID")
self.showDetailViewController(vc as! YourViewControllerClassName, sender: self)

5

Tôi muốn đề xuất một cách sạch sẽ hơn nhiều. Điều này sẽ hữu ích khi chúng ta có nhiều bảng phân cảnh

1. Tạo cấu trúc với tất cả các bảng phân cảnh của bạn

struct Storyboard {
      static let main = "Main"
      static let login = "login"
      static let profile = "profile" 
      static let home = "home"
    }

2. Tạo tiện ích mở rộng UIStoryboard như thế này

extension UIStoryboard {
  @nonobjc class var main: UIStoryboard {
    return UIStoryboard(name: Storyboard.main, bundle: nil)
  }
  @nonobjc class var journey: UIStoryboard {
    return UIStoryboard(name: Storyboard.login, bundle: nil)
  }
  @nonobjc class var quiz: UIStoryboard {
    return UIStoryboard(name: Storyboard.profile, bundle: nil)
  }
  @nonobjc class var home: UIStoryboard {
    return UIStoryboard(name: Storyboard.home, bundle: nil)
  }
}

Đặt định danh bảng phân cảnh làm tên lớp và sử dụng mã dưới đây để khởi tạo

let loginVc = UIStoryboard.login.instantiateViewController(withIdentifier: "\(LoginViewController.self)") as! LoginViewController

@Gonobjc để làm gì?
StackRunner

1
@StackRunner điều này sẽ không có sẵn cho mục tiêu c
XcodeNOOB

3

Swift 4:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let yourVC: YourVC = storyboard.instantiateViewController(withIdentifier: "YourVC") as! YourVC

2

Nếu bạn có một Trình điều khiển không sử dụng bất kỳ bảng phân cảnh / Xib nào, bạn có thể đẩy tới VC cụ thể này như cuộc gọi dưới đây:

 let vcInstance : UIViewController   = yourViewController()
 self.present(vcInstance, animated: true, completion: nil)

Tôi hiểu điều này: "không thể được xây dựng bởi vì nó không có bộ khởi tạo có thể truy cập được".
Paul Bénéteau

các cửa hàng và các mối quan hệ khác được tạo bởi bảng phân cảnh bị mất
jose920405

2

Swift 3 Bảng phân cảnh

let settingStoryboard : UIStoryboard = UIStoryboard(name: "SettingViewController", bundle: nil)
let settingVC = settingStoryboard.instantiateViewController(withIdentifier: "SettingViewController") as! SettingViewController
self.present(settingVC, animated: true, completion: {

})

1

Tôi biết đó là một luồng cũ, nhưng tôi nghĩ rằng giải pháp hiện tại (sử dụng mã định danh chuỗi được mã hóa cứng cho trình điều khiển xem đã cho) rất dễ bị lỗi.

Tôi đã tạo một tập lệnh thời gian xây dựng (mà bạn có thể truy cập ở đây ), nó sẽ tạo ra một trình biên dịch an toàn để truy cập và khởi tạo các bộ điều khiển xem từ tất cả các bảng phân cảnh trong dự án đã cho.

Ví dụ: trình điều khiển xem có tên vc1 trong Main.storyboard sẽ được khởi tạo như vậy:

let vc: UIViewController = R.storyboard.Main.vc1^  // where the '^' character initialize the controller

1

Bất kể tôi đã thử gì, nó cũng không hoạt động với tôi - không có lỗi, nhưng cũng không có bộ điều khiển xem mới trên màn hình của tôi. Không biết tại sao, nhưng gói nó trong chức năng hết thời gian cuối cùng đã làm cho nó hoạt động:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.0) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "TabletViewController")
    self.present(controller, animated: true, completion: nil)
}

1

Swift 5

let vc = self.storyboard!.instantiateViewController(withIdentifier: "CVIdentifier")
self.present(vc, animated: true, completion: nil)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.