Tạo một segue theo chương trình


202

Tôi có một điểm chung UIViewControllerlà tất cả các phần UIViewsControllersmở rộng của tôi để sử dụng lại một số hoạt động chung.

Tôi muốn thiết lập một segue trên "Chung" này UIViewControllerđể tất cả các UIViewControllerskế thừa khác .

Tôi đang cố gắng tìm ra cách để tôi làm điều đó theo lập trình.

Tôi đoán rằng câu hỏi cũng có thể là làm thế nào để tôi đặt ra seguecho tất cả của mình UIViewControllersmà không cần vào bảng câu chuyện và làm chúng bằng tay.

Câu trả lời:


169

Theo định nghĩa, một segue thực sự không thể tồn tại độc lập với bảng phân cảnh. Nó thậm chí còn có trong tên của lớp : UIStoryboardSegue. Bạn không tạo ra sự khác biệt theo chương trình - đó là thời gian chạy bảng phân cảnh tạo ra chúng cho bạn. Bạn thường có thể gọi performSegueWithIdentifier:mã của trình điều khiển xem của mình, nhưng điều này phụ thuộc vào việc có một segue đã được thiết lập trong bảng phân cảnh để tham chiếu.

Điều tôi nghĩ bạn đang hỏi là làm thế nào bạn có thể tạo một phương thức trong trình điều khiển khung nhìn chung (lớp cơ sở) sẽ chuyển sang trình điều khiển khung nhìn mới và sẽ được kế thừa bởi tất cả các lớp dẫn xuất. Bạn có thể làm điều này bằng cách tạo một phương thức như thế này cho trình điều khiển khung nhìn lớp cơ sở của bạn:

- (IBAction)pushMyNewViewController
{
    MyNewViewController *myNewVC = [[MyNewViewController alloc] init];

    // do any setup you need for myNewVC

    [self presentModalViewController:myNewVC animated:YES];
}

và sau đó trong lớp dẫn xuất của bạn, gọi phương thức đó khi nhấp vào nút thích hợp hoặc hàng bảng được chọn hoặc bất cứ thứ gì.


4
Cảm ơn. Thật xấu hổ khi chúng ta không thể làm điều đó bằng lập trình. Nó thực sự sẽ tăng chất lượng mã nguồn (ít trùng lặp luôn luôn tốt). Tôi sẽ đi với đề nghị của bạn.
Tiago Veloso

2
@jonkroll có thể gọi / thực hiện segue từ câu lệnh switch tức là dựa trên chỉ số nào tôi có?
codejunkie

5
@codejunkie: Vâng, bạn có thể làm điều đó. Bạn sẽ sử dụng UIViewControllerphương pháp được đặt tên performSegueWithIdentifier:sender:cho việc này.
jonkroll

2
Tôi đã tạo và thực hiện segue theo chương trình (xem câu trả lời của tôi). Bất cứ điều gì sai với mã của tôi, sau đó, nếu câu trả lời của bạn là chính xác?
Jean-Philippe Pellet

13
Cập nhật dành cho iOS 6+: UIView's presentModalViewController:animated:bị phản đối. Từ các tài liệu - (Không dùng nữa trong iOS 6.0. Sử dụng PresentViewControll: hoạt hình: hoàn thành: thay vào đó.)
người dùng

346

Tôi nghĩ rằng tôi sẽ thêm một khả năng khác. Một trong những điều bạn có thể làm là bạn có thể kết nối hai cảnh trong bảng phân cảnh bằng cách sử dụng một segue không được gắn vào một hành động, và sau đó lập trình kích hoạt segue bên trong bộ điều khiển xem của bạn. Cách bạn thực hiện việc này là bạn phải kéo từ biểu tượng chủ sở hữu của tệp ở cuối cảnh phân cảnh là cảnh phân biệt và kéo sang phải vào cảnh đích. Tôi sẽ ném vào một hình ảnh để giúp giải thích.

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

Một cửa sổ bật lên sẽ hiển thị cho "Phân đoạn thủ công". Tôi chọn Push làm loại. Chạm vào hình vuông nhỏ và đảm bảo bạn đang ở trong trình kiểm tra thuộc tính. Cung cấp cho nó một định danh mà bạn sẽ sử dụng để tham chiếu đến nó trong mã.

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

Ok, tiếp theo tôi sẽ sử dụng một mục nút thanh lập trình. Trong viewDidLoad hoặc một nơi nào khác tôi sẽ tạo một mục nút trên thanh điều hướng với mã này:

UIBarButtonItem *buttonizeButton = [[UIBarButtonItem alloc] initWithTitle:@"Buttonize"
                                                                    style:UIBarButtonItemStyleDone
                                                                   target:self
                                                                   action:@selector(buttonizeButtonTap:)];
self.navigationItem.rightBarButtonItems = @[buttonizeButton];

Ok, lưu ý rằng bộ chọn là buttonizeButtonTap :. Vì vậy, hãy viết một phương thức void cho nút đó và trong phương thức đó, bạn sẽ gọi segue như thế này:

-(void)buttonizeButtonTap:(id)sender{
    [self performSegueWithIdentifier:@"Associate" sender:sender];
    }

Tham số người gửi được yêu cầu để xác định nút khi gọi Chuẩn bị được gọi. readyForSegue là phương thức khung trong đó bạn sẽ khởi tạo cảnh của mình và chuyển cho nó bất kỳ giá trị nào nó sẽ cần để thực hiện công việc của nó. Đây là phương thức của tôi.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"Associate"])
    {
        TranslationQuizAssociateVC *translationQuizAssociateVC = [segue destinationViewController];
        translationQuizAssociateVC.nodeID = self.nodeID; //--pass nodeID from ViewNodeViewController
        translationQuizAssociateVC.contentID = self.contentID;
        translationQuizAssociateVC.index = self.index;
        translationQuizAssociateVC.content = self.content;
    }
}

Ok, chỉ cần thử nghiệm nó và nó hoạt động. Hy vọng nó sẽ giúp bạn.


@MichaelRowe làm thế nào để loại bỏ sự cần thiết phải phân biệt? Như tôi thấy, bạn vẫn phải kéo và thả trên Storyboard vào bộ điều khiển đích ..
aherrick

@MichaelRowe điều này không loại bỏ sự cần thiết phải phân biệt. Điều này làm là cho phép bạn phân biệt giữa các bộ điều khiển xem được xây dựng theo mã thay vì trong trình tạo giao diện.
Matthew

@ Tôi thực sự chỉ cần tôi suy nghĩ lại về cách tôi thiết lập ứng dụng của mình ... Sau khi viết lại hoàn toàn tất cả giao diện người dùng, tôi không còn sử dụng bất kỳ phân biệt nào nữa ..
Michael Rowe

@cocoanut Tôi nhận được lỗi là "Ứng dụng đã cố gắng trình bày một bộ điều khiển hoạt động" bất kỳ trợ giúp nào về vấn đề này ..
Bala

1
Phân đoạn thủ công "Đẩy" không được dùng nữa, sử dụng "Hiển thị". Câu trả lời này có nhiều chi tiết hơn. @smileBot vui lòng cập nhật câu trả lời.
NAbbas

81

Tôi đã sử dụng mã này để khởi tạo lớp con segue tùy chỉnh của mình và chạy nó theo chương trình. Nó dường như làm việc. Bất cứ điều gì sai với điều này? Tôi bối rối, đọc tất cả các câu trả lời khác nói rằng nó không thể được thực hiện.

UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"OtherViewControllerId"];
MyCustomSegue *segue = [[MyCustomSegue alloc] initWithIdentifier:@"" source:self destination:toViewController];
[self prepareForSegue:segue sender:sender];
[segue perform];

4
Có gì trong MyCustomSegue?
Victor Engel

3
Nó là một lớp con tùy chỉnh của UIStoryboardSegue.
Jean-Philippe Pellet

7
@MarkAmery Rất nhiều người (bao gồm cả tôi) tránh sử dụng bảng phân cảnh. Chúng khó hợp nhất và không có kiểm tra thời gian biên dịch rằng ID tôi chuyển đến performSegueWithIdentifier:thực sự được xác định trong bảng phân cảnh. Tôi tránh tất cả các vấn đề nếu tôi tự tạo ra segue.
Jean-Philippe Pellet

3
Tôi đồng ý với Jean-Philippe. Quản lý bảng phân cảnh là một nỗi đau ở mông. Tất nhiên, thật dễ dàng để nhấp theo cách của bạn thông qua một vài khung nhìn và thêm một dấu tách ở đây và một dấu tách ở đó, nhưng việc quản lý 6 khung nhìn với 16 phân biệt được xác định trong XML, khi bạn có ba nhà phát triển đấu tranh với nó là rất tệ. Dù sao, vấn đề là: mã cho phép bạn kiểm soát, xml được tạo bởi xcode thì không.
Kirtian

3
Tôi thấy một sự cố trong [segue Performance] trong iOS7, không biết có ai khác đang gặp phải điều này không.
Eric Chen

45

Đoán điều này đã được trả lời và chấp nhận, nhưng tôi chỉ muốn thêm một vài chi tiết cho nó.

Tôi đã làm gì để giải quyết vấn đề trong đó tôi sẽ hiển thị chế độ xem đăng nhập dưới dạng màn hình đầu tiên và sau đó muốn tách biệt với ứng dụng nếu đăng nhập đúng. Tôi đã tạo segue từ bộ điều khiển xem đăng nhập đến bộ điều khiển xem gốc và đặt cho nó một mã định danh như "myidentifier".

Sau đó, sau khi kiểm tra tất cả mã đăng nhập nếu đăng nhập đúng, tôi gọi

[self performSegueWithIdentifier: @"myidentifier" sender: self];

Sự hiểu lầm lớn nhất của tôi là tôi đã cố gắng đặt segue vào một nút và loại ngắt dòng này sau khi nó được tìm thấy.


4
Như tôi đã viết như một bình luận khác: Tôi đã tạo và thực hiện các phân biệt tùy chỉnh theo chương trình (xem câu trả lời của tôi).
Jean-Philippe Pellet

32

Bạn phải liên kết mã của bạn với mã UIStoryboardmà bạn đang sử dụng. Hãy chắc chắn rằng bạn đi vào YourViewControll của bạn UIStoryboard, nhấp vào đường viền xung quanh nó, sau đó đặt identifiertrường của nó thành một mã NSStringmà bạn gọi trong mã của mình.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" 
                                                     bundle:nil];
YourViewController *yourViewController = 
 (YourViewController *)
  [storyboard instantiateViewControllerWithIdentifier:@"yourViewControllerID"];
[self.navigationController pushViewController:yourViewController animated:YES];

1
Tôi nhận được điều này, nhưng điều gì sẽ xảy ra nếu viewContoder mà tôi muốn trình bày được nhúng trong NavigationContoder trong bảng phân cảnh? Từ những gì tôi có thể tìm thấy, tôi có thể khởi tạo NavigationContoder để nhúng nó vào trong bảng phân cảnh, tôi đã thiết lập các phân đoạn đẩy cho chế độ xem cần được trình bày.
jhilgert00

1
bạn có thể xây dựng trên này? Tôi nghĩ rằng đây là vấn đề tôi đang gặp phải, nhưng dường như không thể tìm ra cách / nơi để làm điều này ...
jesses.co.tt

1
Ngay cả giải pháp này là một giải pháp chính xác, Đó là về việc tránh bất kỳ sai sót nào, nhưng câu hỏi là về segue. Bằng cách này, bạn có thể kết nối hoặc thực hiện chuyển đổi giữa hai cảnh KHÔNG CÓ sự khác biệt trong bảng phân cảnh.
BootMaker

16

Đối với bộ điều khiển có trong bảng phân cảnh.

jhilgert00 đây có phải là những gì bạn đang tìm kiếm?

-(IBAction)nav_goHome:(id)sender {
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:@"HomeController"];
[self.navigationController pushViewController: myController animated:YES];

}

HOẶC LÀ...

[self performSegueWithIdentifier:@"loginMainSegue" sender:self];


3

Tôi muốn thêm một sự làm rõ ...

Một sự hiểu lầm phổ biến, trong thực tế mà tôi đã có một thời gian, đó là một phân đoạn bảng phân cảnh được kích hoạt bởi prepareForSegue:sender:phương thức. Không phải vậy. Một segue bảng phân cảnh sẽ thực hiện, bất kể bạn đã thực hiện một prepareForSegue:sender:phương thức cho bộ điều khiển xem (khởi hành từ) đó chưa.

Tôi đã học được điều này từ các bài giảng iTunesU tuyệt vời của Paul Hegarty . Tôi xin lỗi nhưng tiếc là không thể nhớ bài giảng nào.

Nếu bạn kết nối một segue giữa hai bộ điều khiển khung nhìn trong bảng phân cảnh, nhưng không thực hiện một prepareForSegue:sender:phương thức, thì segue vẫn sẽ tách biệt với bộ điều khiển khung nhìn đích. Tuy nhiên, nó sẽ tách biệt với bộ điều khiển xem không chuẩn bị.

Hi vọng điêu nay co ich.


3

Phân đoạn Storyboard không được tạo bên ngoài bảng phân cảnh. Bạn sẽ cần phải dây nó lên, mặc dù những hạn chế.

UIStoryboardSegue Reference ghi rõ:

Bạn không tạo các đối tượng segue trực tiếp. Thay vào đó, thời gian chạy bảng phân cảnh tạo ra chúng khi nó phải thực hiện một khoảng cách giữa hai bộ điều khiển khung nhìn. Bạn vẫn có thể khởi tạo một segue theo chương trình bằng cách sử dụng phương thức biểu diễnSegueWithIdentifier: sender: của UIViewContoder nếu bạn muốn. Bạn có thể làm như vậy để bắt đầu một segue từ một nguồn được thêm vào theo chương trình và do đó không có sẵn trong Trình tạo giao diện.

Bạn vẫn có thể lập trình cho bảng phân cảnh lập trình trình điều khiển chế độ xem bằng cách sử dụng segue bằng cách sử dụng presentModalViewController:hoặc pushViewController:animated:gọi, nhưng bạn sẽ cần một phiên bản bảng phân cảnh.

Bạn có thể gọi UIStoryboardphương thức lớp s để có được bảng phân cảnh có tên với gói nil cho gói chính.

storyboardWithName:bundle:


2

Trước tiên, giả sử bạn có hai chế độ xem khác nhau trong bảng phân cảnh và bạn muốn điều hướng từ màn hình này sang màn hình khác, vì vậy hãy làm theo các bước sau:

1). Xác định tất cả các chế độ xem của bạn với tệp lớp và id bảng phân cảnh trong trình kiểm tra danh tính.

2). Đảm bảo bạn thêm bộ điều khiển điều hướng vào chế độ xem đầu tiên. Chọn nó trong Bảng phân cảnh rồi chọn Trình chỉnh sửa> Nhúng vào> Trình điều khiển điều hướng

3). Trong lớp đầu tiên của bạn, nhập "secondClass.h"

#import "ViewController.h
#import "secondController.h"

4). Thêm lệnh này trong IBAction phải thực hiện segue

secondController *next=[self.storyboard instantiateViewControllerWithIdentifier:@"second"];
[self.navigationController pushViewController:next animated:YES];

5). @"second"là lớp điều khiển thứ hai, id bảng phân cảnh.


self.storyboardnên là:UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
masipcat

@masipcat và tên bảng Story có thể phụ thuộc vào cách bạn thiết lập dự án Xcode của mình, trong đó tôi là "Main.storyboard" nên tôi đã sử dụngstoryboardWithName:@"Main"
ammianus

@ sanket-chauhan nếu bộ điều khiển đầu tiên của bạn không được nhúng trong Bộ điều khiển điều hướng, bạn cũng có thể hiển thị chế độ xem tiếp theo bằng cách sử dụng [self showDetailViewController:next sender:self];hoặc[self showViewController:next sender:self];
ammianus

1

Tôi đã thiết kế ngược và thực hiện (tái) mã nguồn mở cho các phân biệt của UIStoryboard: https://github.com/acoomans/Segway

Với thư viện đó, bạn có thể xác định các phân biệt theo chương trình (không có bất kỳ bảng phân cảnh nào).

Hy vọng nó có thể giúp.


0

Một vài vấn đề, thực sự:

Đầu tiên, trong dự án mà bạn đã tải lên cho chúng tôi, segue không mang định danh "segue1":

không có định danh

Bạn nên điền vào định danh đó nếu bạn chưa có.

Thứ hai, khi bạn đang đẩy từ chế độ xem bảng sang chế độ xem bảng, bạn đang gọi initWithNibName để tạo bộ điều khiển xem. Bạn thực sự muốn sử dụng InstantiateViewControllWithIdentifier.


0

Đây là mẫu mã cho Creating a segue programmatically:

class ViewController: UIViewController {
    ...
    // 1. Define the Segue
    private var commonSegue: UIStoryboardSegue!
    ...
    override func viewDidLoad() {
        ...
        // 2. Initialize the Segue
        self.commonSegue = UIStoryboardSegue(identifier: "CommonSegue", source: ..., destination: ...) {
            self.commonSegue.source.showDetailViewController(self.commonSegue.destination, sender: self)
        }
        ...
    }
    ...
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // 4. Prepare to perform the Segue
        if self.commonSegue == segue {
            ...
        }
        ...
    }
    ...
    func actionFunction() {
        // 3. Perform the Segue
        self.prepare(for: self.commonSegue, sender: self)
        self.commonSegue.perform()
    }
    ...
}

Bạn đang gọi self.prepare(for: self.commonSegue, sender: self)từ phương pháp hành động của bạn. Vậy thì điểm so sánh if self.commonSegue == segue {...}trong prepare(for:sender)phương pháp là gì?
nayem

@nayem: Trong prepare(for:sender:), bạn có thể định cấu hình bộ điều khiển xem đích trước khi nó được hiển thị. Tất nhiên bạn cũng có thể làm điều đó trong actionFunction.
jqgsninimo

@nayem: Lý do tôi làm điều này là để cố gắng phù hợp với việc xử lý các phân biệt khác.
jqgsninimo
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.