Bảng phân cảnh - tham khảo ViewController trong AppDelegate


122

hãy xem xét tình huống sau: Tôi có một ứng dụng dựa trên bảng phân cảnh. Tôi thêm một đối tượng ViewController vào bảng phân cảnh, thêm các tệp lớp cho ViewController này vào dự án và chỉ định tên của lớp mới trong trình kiểm tra danh tính IB. Bây giờ tôi sẽ tham khảo ViewController này theo cách lập trình từ AppDelegate như thế nào? Tôi đã tạo một biến với lớp có liên quan và biến nó thành thuộc tính IBOutlet, nhưng tôi không thấy bất kỳ cách nào có thể tham chiếu đến ViewController mới trong mã - mọi nỗ lực ctrl-kéo kết nối đều không hoạt động .

tức là trong AppDelegate, tôi có thể truy cập ViewController cơ sở như thế này

(MyViewController*) self.window.rootViewController

nhưng làm thế nào về bất kỳ ViewController nào khác có trong bảng phân cảnh?


Kiểm tra câu trả lời này . Nó nhanh chóng, nhưng các ngôn ngữ tương tự nhau.
Borzh

Câu trả lời:


165

Hãy xem các tài liệu cho -[UIStoryboard instantiateViewControllerWithIdentifier:]. Điều này cho phép bạn khởi tạo bộ điều khiển chế độ xem từ bảng phân cảnh của mình bằng cách sử dụng số nhận dạng mà bạn đã đặt trong Trình kiểm tra thuộc tính IB:

nhập mô tả hình ảnh ở đây

ĐÃ CHỈNH SỬA để thêm mã mẫu:

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                         bundle: nil];

MyViewController *controller = (MyViewController*)[mainStoryboard 
                    instantiateViewControllerWithIdentifier: @"<Controller ID>"];

Chào Robin, cảm ơn vì điều đó! Tôi đã xem tài liệu này nhưng các từ khởi tạo và khởi tạo lẫn lộn ... điều này giúp chúng tôi đến đó (sau khi làm theo hướng dẫn của bạn :) (chết tiệt vì thiếu định dạng mã trong các câu trả lời ...) UIStoryboard * mainStoryboard = [UIStoryboard storyboardWithName: @ Gói "MainStoryboard": nil]; MyViewController * thisController = (MyViewController *) [mainStoryboard InstantiateViewControllerWithIdentifier: @ "myvc"];
Matthias D

Tôi đã thêm mã ví dụ của bạn vào câu trả lời với định dạng cho bất kỳ ai đang xem nó.
Robin Summerhill

24
nếu bạn đang tạo một ứng dụng toàn cầu, hãy đảm bảo sử dụng MainStoryboard_iPhone / MainStoryboard_iPad nếu không bạn sẽ gặp sự cố.
roocell

16
Từ bên trong ủy quyền, bạn có thể truy cập phiên bản bảng phân cảnh được tải bởi info.plist của bạn như sau: [[[self window] rootViewController] storyboard] Theo tài liệu, điều này sẽ trả về "bảng phân cảnh mà bộ điều khiển chế độ xem bắt nguồn từ đó." (hoặc không nếu nó không đến từ bảng phân cảnh). Từ UIStoryboard * đó, bạn có thể sử dụng các lệnh gọi khởi tạo mà @RobinSummerhill đã đề cập. Lưu ý rằng Bảng phân cảnh khởi tạo các phiên bản mới của viewControllers ( cảnh ) khi chúng cần thiết và không sử dụng lại những phiên bản đã được xem trước đó.
Tad Bumcrot

6
Tôi tin rằng OP muốn biết LÀM THẾ NÀO ĐỂ CÓ ĐƯỢC HIỆN TẠI CHẠY vc. Không phải làm thế nào để tải một. Chính xác như anh ấy giải thích, bạn đã từng có thể nói điều này self.window.rootViewController và bây giờ bạn không thể nói nữa.
Fattie,

41

Nếu bạn sử dụng XCode5, bạn nên làm theo một cách khác.

  • Chọn của bạn UIViewControllertrongUIStoryboard
  • Đi tới Identity Inspectorngăn trên cùng bên phải
  • Đánh dấu vào Use Storyboard IDhộp kiểm
  • Viết một id duy nhất vào Storyboard IDtrường

Sau đó viết mã của bạn.

// Override point for customization after application launch.

if (<your implementation>) {
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" 
                                                             bundle: nil];
    YourViewController *yourController = (YourViewController *)[mainStoryboard 
      instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
    self.window.rootViewController = yourController;
}

return YES;

4
Theo như tôi biết và đã có thể chơi thử, đây là câu trả lời được cập nhật.
gnclmorais

Tên của bảng phân cảnh là tên tệp của nó không có phần mở rộng nên nó cũng có thể là "Main_iPhone" hoặc "Main_iPad" nếu bạn đã thiết lập dự án của mình theo cách đó.
Brian White,

và sau đó làm cách nào để chúng ta chuyển trở lại rootViewController ban đầu sau khi đăng nhập. Ít nhất theo hiểu biết của tôi về iOS 7 và Xcode 5.0.2 - việc thay đổi bộ điều khiển chế độ xem gốc trở lại sẽ ngay lập tức và không có hoạt ảnh chuyển hệ thống phân cấp chế độ xem. Nhóm UX đã giết người lập trình với giá thấp hơn.
lol

Tôi sẽ làm điều đó bằng Swift như thế nào?
Leo Dabus

8

Nói chung, hệ thống phải xử lý việc khởi tạo bộ điều khiển chế độ xem bằng bảng phân cảnh. Những gì bạn muốn là duyệt qua hệ thống phân cấp viewController bằng cách lấy tham chiếu đến tham chiếu self.window.rootViewControllertrái ngược với việc khởi tạo các bộ điều khiển chế độ xem, vốn đã được khởi tạo chính xác nếu bạn thiết lập bảng phân cảnh của mình đúng cách.

Vì vậy, giả sử của bạn rootViewControllerlà một UINavigationController và sau đó bạn muốn gửi một cái gì đó đến bộ điều khiển chế độ xem hàng đầu của nó, bạn sẽ làm như thế này trong AppDelegate's didFinishLaunchingWithOptions:

UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;

Trong Swift nếu sẽ rất giống:

let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data

Bạn thực sự không nên khởi tạo bộ điều khiển chế độ xem bằng id bảng phân cảnh từ đại biểu ứng dụng trừ khi bạn muốn bỏ qua cách tải bảng phân cảnh thông thường và tự tải toàn bộ bảng phân cảnh. Nếu bạn đang phải khởi tạo các cảnh từ AppDelegate, rất có thể bạn đang làm sai. Ý tôi là hãy tưởng tượng bạn, vì một lý do nào đó, muốn gửi dữ liệu đến một bộ điều khiển chế độ xem theo cách xuống ngăn xếp, AppDelegate không nên đi vào ngăn bộ điều khiển chế độ xem để thiết lập dữ liệu. Đó không phải là việc của nó. Doanh nghiệp của nó là rootViewController. Hãy để rootViewController xử lý các phần tử con của chính nó! Vì vậy, nếu tôi bỏ qua quy trình tải bảng phân cảnh bình thường của hệ thống bằng cách xóa các tham chiếu đến nó trong tệp info.plist, thì tôi sẽ khởi tạo tối đa rootViewController bằng cách sử dụnginstantiateViewControllerWithIdentifier:và có thể là gốc của nó nếu nó là một vùng chứa, như UINavigationController. Những gì bạn muốn tránh là khởi tạo bộ điều khiển chế độ xem đã được bảng phân cảnh khởi tạo. Đây là một vấn đề tôi thấy rất nhiều. Tóm lại, tôi không đồng ý với câu trả lời được chấp nhận. Nó không chính xác trừ khi các áp phích có nghĩa là xóa tải bảng phân cảnh khỏi info.plist vì bạn sẽ tải 2 bảng phân cảnh nếu không, điều này không có ý nghĩa gì. Nó có thể không phải là rò rỉ bộ nhớ bởi vì hệ thống đã khởi tạo cảnh gốc và gán nó cho cửa sổ, nhưng sau đó bạn đến và khởi tạo nó một lần nữa và gán lại. Ứng dụng của bạn đã có một khởi đầu khá tệ!


0
    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
    self.window.rootViewController = [storyboard instantiateInitialViewController];
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.