PreparingForSegue를 전달하는 방법 : 객체


357

지도보기 ( rightCalloutAccessory버튼 포함) 에 많은 주석이 있습니다. 버튼은 이것에서 a로 segue를 수행 mapview합니다 tableview. tableview클릭 한 콜 아웃 버튼에 따라 데이터를 보유하는 다른 객체 를 전달하고 싶습니다 .

예를 들면 : (완전히 구성)

  • annotation1 (오스틴)-> 데이터 obj 1 전달 (오스틴 관련)
  • annotation2 (달라스)-> 데이터 obj 2 전달 (댈러스 관련)
  • annotation3 (휴스턴)-> 데이터 obj 3 등을 전달합니다 ... (당신은 아이디어를 얻습니다)

클릭 한 문구 버튼을 감지 할 수 있습니다.

나는 prepareForSegue:를 사용 하여 데이터 obj를 대상에 전달합니다 ViewController. 이 호출이 필요한 데이터 obj에 대해 추가 인수를 취할 수 없기 때문에 동일한 효과 (동적 데이터 obj)를 얻는 우아한 방법은 무엇입니까?

모든 팁을 주시면 감사하겠습니다.


답변:


673

prepareForSegue:메소드 에서 대상 뷰 컨트롤러에 대한 참조를 가져와 필요한 오브젝트를 전달하십시오. 예를 들면 다음과 같습니다.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Make sure your segue name in storyboard is the same as this line
    if ([[segue identifier] isEqualToString:@"YOUR_SEGUE_NAME_HERE"])
    {
        // Get reference to the destination view controller
        YourViewController *vc = [segue destinationViewController];

        // Pass any objects to the view controller here, like...
        [vc setMyObjectHere:object];
    }
}

개정 : performSegueWithIdentifier:sender:방법을 사용 하여 선택 또는 버튼 누름을 기반으로 새 보기로의 전환을 활성화 할 수도 있습니다 .

예를 들어 두 개의 뷰 컨트롤러가 있다고 가정합니다. 첫 번째는 세 개의 버튼을 포함하고 두 번째는 전환 전에 어떤 버튼을 눌렀는지 알아야합니다. 다음 과 같은 방법 IBAction을 사용 performSegueWithIdentifier:하는 코드에 버튼을 연결할 수 있습니다 ...

// When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
    [self performSegueWithIdentifier:@"MySegue" sender:sender];
}

// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"MySegue"]) {

        // Get destination view
        SecondView *vc = [segue destinationViewController];

        // Get button tag number (or do whatever you need to do here, based on your object
        NSInteger tagIndex = [(UIButton *)sender tag];

        // Pass the information to your destination view
        [vc setSelectedButton:tagIndex];
    }
}

편집 : 내가 처음 첨부 한 데모 응용 프로그램은 이제 6 세이므로 혼란을 피하기 위해 제거했습니다.


고맙지 만 [vc setMyObjectHere:object];동적으로 설정하고 싶습니다 . 즉, button1의 경우 obj1, button2의 경우 obj2 문제는 인수를 전달할 수 없다는 것입니다.이 문제를 해결할 방법이 있습니까?
chizzle

2
내가 말하고있는 것에 대한 다운로드 가능한 예제로 게시물을 업데이트했습니다.
Simon

작동했습니다! 무리 감사. D : 보조 노트 prepareForSegue으로 (태그를 얻을, 따라서 수)있는 UIButton의 부모 클래스 인 UIControl 인수가
chizzle

스토리 보드 segue없이 내비게이션 컨트롤러로 푸시 할 때도 readyForSegue가 호출됩니까?
zakdances 2016 년

이것은 내가 본 것 중 가장 철저한 답변 중 하나입니다. 좋은 코드 샘플, 문제 해결, 다운로드 가능한 샘플 제공 ... 와우. 나는 감동!
lewiguez 2016 년

82

때로는 두 개의 뷰 컨트롤러간에 컴파일 타임 종속성을 생성하지 않는 것이 도움이됩니다. 대상 뷰 컨트롤러 유형에 신경 쓰지 않고 수행 할 수있는 방법은 다음과 같습니다.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {
        [segue.destinationViewController performSelector:@selector(setMyData:) 
                                              withObject:myData];
    } 
}

대상 뷰 컨트롤러가 공개 속성을 선언하는 한 다음과 같습니다.

@property (nonatomic, strong) MyData *myData;

위에서 설명한대로 이전 뷰 컨트롤러에서이 속성을 설정할 수 있습니다.


12
이것은 실제로 의견의 문제입니다. 나는 (아직) 뷰 컨트롤러를 '단단하게'제어하고 싶지 않은 상황에 처하지는 않았지만, 당신이 말하는 것을 고맙게 생각하고 올바른 상황에서 중요 할 수 있습니다.
Simon

2
@Simon : 예, 당신은 당신에게 가장 적합한 방법을 선택합니다. 예를 들어 현재 작업중 인 앱에서 동일한 데이터 객체가 필요한 뷰 컨트롤러를 계속 추가하기 때문에 접근 방식이 상당히 합리적입니다. 단지 segue로 그들을 연결할 수 있고 그들이 올바른 데이터를 얻을 수 있다는 것을 아는 것이 매우 편리합니다.
Macondo2Seattle

10
그것은 의견의 문제가 아니며, 단지 틀린 것입니다. "특정한 경우,이 작업을 수행해야합니다 ..."
Fattie

2
나는 Simon의 방법을 선호합니다. 컴파일 타임에 오류를 알려줍니다. 예를 들어, 대상 뷰 컨트롤러에서 myData 선언을 놓친 경우 즉시 알게됩니다. 그러나 시나리오의 경우 접근 방식이 좋습니다!
Abdurrahman Mubeen Ali

14
이 방법은 대상 뷰 컨트롤러에을 갖도록 요구하므로 절대적으로 종속성을 만듭니다 setMyData:. 그것은 의존성입니다. 컴파일 오류를 피하기 위해 선택기를 사용한다는 사실 은 이점이 아니라 접근 방식 의 약점 으로 취급해야합니다 . 런타임 오류보다 컴파일 타임 오류가 선호되어야한다는 개념을 잃어버린 개발자 수에 놀랐습니다.
Nate

21

Swift 4.2에서는 다음과 같은 작업을 수행합니다.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let yourVC = segue.destination as? YourViewController {
        yourVC.yourData = self.someData
    }
}

`super.prepare (for : segue, sender : sender)`로 전화해야합니까?
Andrew K

16

나는이 보낸 클래스를 다음과 같이

@class MyEntry;

@interface MySenderEntry : NSObject
@property (strong, nonatomic) MyEntry *entry;
@end

@implementation MySenderEntry
@end

발신자 클래스 를 사용하여 객체를 전달합니다.prepareForSeque:sender:

-(void)didSelectItemAtIndexPath:(NSIndexPath*)indexPath
{
    MySenderEntry *sender = [MySenderEntry new];
    sender.entry = [_entries objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:SEGUE_IDENTIFIER_SHOW_ENTRY sender:sender];
}

-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_SHOW_ENTRY]) {
        NSAssert([sender isKindOfClass:[MySenderEntry class]], @"MySenderEntry");
        MySenderEntry *senderEntry = (MySenderEntry*)sender;
        MyEntry *entry = senderEntry.entry;
        NSParameterAssert(entry);

        [segue destinationViewController].delegate = self;
        [segue destinationViewController].entry = entry;
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_HISTORY]) {
        // ...
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_FAVORITE]) {
        // ...
        return;
    }
}

우리는 사용 prepareForSegue 또는 우리는 구현 을하고, 가정은 우리가 즉 prepareForSegue 자체가 호출되는 것입니다 하지 않습니다 같은 것을 할 필요가[self prepareForSegue]

15

한 View Controller에서 다른 View Controller로 데이터를 전달하는 방법을 배우려고 할 때이 질문을 보았습니다. 그래도 배울 수 있도록 시각적 인 것이 필요 하므로이 답변은 이미 여기에있는 다른 사람들을 보완합니다. 원래 질문보다 조금 더 일반적이지만 작동하도록 조정할 수 있습니다.

이 기본 예제는 다음과 같이 작동합니다.

여기에 이미지 설명을 입력하십시오

아이디어는 문자열을 첫 번째보기 컨트롤러의 텍스트 필드에서 두 번째보기 컨트롤러의 레이블로 전달하는 것입니다.

퍼스트 뷰 컨트롤러

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // get a reference to the second view controller
        let secondViewController = segue.destinationViewController as! SecondViewController

        // set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    }

}

두 번째 뷰 컨트롤러

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    }

}

기억해

  • control버튼 을 클릭하고 세컨드 뷰 컨트롤러로 끌어서 segue를 만듭니다 .
  • UITextField및 의 콘센트를 연결 합니다 UILabel.
  • 첫 번째 및 두 번째 View Controller를 IB에서 적절한 Swift 파일로 설정하십시오.

출처

segue를 통해 데이터를 전송하는 방법 (빠른) (YouTube 자습서)

또한보십시오

View Controllers : 데이터 전달 및 데이터 전달 (완전한 답변)


5

들어 스위프트는 이를 사용,

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var segueID = segue.identifier

    if(segueID! == "yourSegueName"){

        var yourVC:YourViewController = segue.destinationViewController as YourViewController

        yourVC.objectOnYourVC = setObjectValueHere!

    }
}

4

UIViewController 에이 작업을 단순화하는 범주가있는 라이브러리를 구현했습니다. 기본적으로 segue를 수행하는 UI 항목과 연관된 NSDictionary에서 전달하려는 매개 변수를 설정합니다. 수동 segue 와도 작동합니다.

예를 들어, 할 수 있습니다

[self performSegueWithIdentifier:@"yourIdentifier" parameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

수동 segue 또는 segue와 함께 버튼을 만들고 사용

[button setSegueParameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

대상 뷰 컨트롤러가 키에 대해 키-값 코딩을 준수하지 않으면 아무 일도 일어나지 않습니다. 키 값과도 작동합니다 (풀기 해제에 유용). 여기에서 확인하십시오 https://github.com/stefanomondino/SMQuickSegue


2

내 솔루션은 비슷합니다.

// In destination class: 
var AddressString:String = String()

// In segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
   if (segue.identifier == "seguetobiddetailpagefromleadbidder")
    {
        let secondViewController = segue.destinationViewController as! BidDetailPage
        secondViewController.AddressString = pr.address as String
    }
}

1

이 기능을 사용하십시오.

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let index = CategorytableView.indexPathForSelectedRow
    let indexNumber = index?.row
    let VC = segue.destination as! DestinationViewController
   VC.value = self.data

}

0

이 솔루션을 사용하여 segue와 데이터 통신의 호출을 동일한 기능 내에서 유지할 수있었습니다.

private var segueCompletion : ((UIStoryboardSegue, Any?) -> Void)?

func performSegue(withIdentifier identifier: String, sender: Any?, completion: @escaping (UIStoryboardSegue, Any?) -> Void) {
    self.segueCompletion = completion;
    self.performSegue(withIdentifier: identifier, sender: sender);
    self.segueCompletion = nil
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    self.segueCompletion?(segue, sender)
}

유스 케이스는 다음과 같습니다.

func showData(id : Int){
    someService.loadSomeData(id: id) {
        data in
        self.performSegue(withIdentifier: "showData", sender: self) {
            storyboard, sender in
            let dataView = storyboard.destination as! DataView
            dataView.data = data
        }
    }
}

이것은 나를 위해 작동하는 것 같지만 수행 및 준비 기능이 항상 동일한 스레드에서 실행된다는 것을 100 % 확신하지 못합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.