2014-12-13 2 views
6

나는 스위프트를 배우려고 노력 중이며 유명한 노트 응용 프로그램을 개발하려고합니다.prepareForSegue는 뷰 컨트롤러간에 값을 전달하는 올바른 방법입니다.

테이블 뷰에 바인딩 된 배열과 메모를 추가하는 뷰가 있습니다. 두 번째보기에서 textfieldshouldreturn 이벤트가 segue를 트리거하고 tableview로 돌아갑니다.

나는 이것이 올바른지 배우고 싶다. 이 방법으로 다른 뷰 컨트롤러에서 변수를 조작하고 있기 때문입니다. 나는 MVC 마스터가 아니지만 잘못된 것처럼 느꼈다. 내 코드 스 니펫은 다음과 같습니다.

func textFieldShouldReturn(textField: UITextField) -> Bool { 

    self.performSegueWithIdentifier("backSegue", sender: self) 
    return true 
} 

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
    if(segue.identifier == "backSegue"){ 
     let navController = segue.destinationViewController as UINavigationController; 
     let myController = navController.topViewController as NotesTableViewController; 
     if(self.ourTextField?.text != nil || self.ourTextField?.text != ""){ 
      myController.notes.append(self.ourTextField?.text ?? ""); 
     } 

    } 
} 

고맙습니다.

+0

* 왜 잘못 생각합니까? 그것은 올바른 방법입니다. 컨트롤러는 데이터와 이러한 데이터의 뷰를 관리하는 데 사용되므로 다른 뷰 컨트롤러를 밀어 넣으면 소스와 대상 사이에 일부 데이터를 전달하는 것이 합리적입니다. –

+0

이것은 뷰 컨트롤러간에 데이터를 전달하는 매우 일반적인 방법이므로 사용하는 것에 대해 걱정할 필요가 없습니다. 많은 [존경받는 개발자] (http://oleb.net/blog/2012/02/passing-data-between-view-controllers/)가 그렇게합니다. 다른 하나의 옵션이 있습니다. 내가 아는 한, Swift는이 점에서 테이블에 특별한 것을 가져 오지 않으므로 [기존 Objective C 질문] (http://stackoverflow.com/questions/5210535/passing-data-between)을 확인해야합니다. -view-controllers)도 있습니다. –

답변

7

귀하의 질문은 실제로는 prepareForSegue에 관한 것이 아니라보기 컨트롤러 간의 관계입니다. 당신의 디자인이 "잘못 느껴지는"이유는 그것이 그 것이다. 문제는 메모 작성보기 컨트롤러가 호출보기 컨트롤러에서 직접 변수를 조작하기 때문에을 사용하는보기 컨트롤러에 대해 너무 많이 알고 있다는 것입니다. 변수를 직접 조작하려면 호출자의 클래스를 알아야합니다.

왜 이것이 문제입니까? 그것은 귀하의 노트 작성보기 컨트롤러를 덜 재사용 할 수 있습니다. 메모 작성보기 컨트롤러를 올바르게 작성하면 다른 앱에서도 재사용 할 수 있습니다. 재사용이 가능하도록하려면 호출자로부터 노트 작성보기 컨트롤러를 분리해야합니다. 정확히 누가 호출하고 있는지 알 필요가 없습니다.

그럼 누가 전화했는지 모르는 경우 데이터를 발신자에게 다시 전달하려면 어떻게해야합니까? 대답은 대표단입니다.

대표단은 다음과 같이 작동합니다

  1. 당신은 방법 또는 프로토콜의 구현이 구현할 방법을 설명하는 프로토콜을 만들 수 있습니다. 귀하의 경우 takeNote(note: String)을 구현하는 NoteWriterDelegate과 같은 프로토콜을 사용할 수 있습니다.

    protocol NoteWriterDelegate { 
        func takeNote(note: String) 
    } 
    

    노트 작성보기 컨트롤러와 함께 파일에 정의하십시오.

  2. 대리자에 대한 옵션 포인터를해야합니다 귀하의 노트 작가 :

    weak var delegate: NoteWriterDelegate? 
    
  3. 당신은 NoteWriterDelegate로 첫 번째보기 컨트롤러를 선언 할 필요가
  4. :

    class ViewController: UITableViewController, NoteWriterDelegate 
    
  5. 을 그리고 필요한 구현 첫 번째보기 컨트롤러의 메소드 :

    func takeNote(note: String) { 
        notes.append(note) 
    } 
    
  6. 당신이 돌려 보내는 메모가있을 때, 메모 쓰기 뷰 컨트롤러에서

    destinationViewController.delegate = self 
    
  7. : 당신은 뷰 컨트롤러를 작성 노트에 이동에 대비 prepareForSegue를 호출 할 때

  8. , 당신은 대리인으로 자신을 전달합니다 발신자에게, 당신은 위임에 takeNote 전화 :

    delegate?.takeNote(self.ourTextField?.text ?? "") 
    
  9. 이 방법으로 그 일을함으로써

이, 메모 작가는이 이야기 것을 알고있다 NoteWriterDelegate에 나중에 이것을 재사용하려면 노트 작성자 클래스를 다른 프로젝트에 드롭하고, 델리게이트를 구현하면 메모 작성자 클래스의 코드를 건드리지 않아도 작동합니다.

2

대부분의 경우 prepareForSegue를 통해 데이터를 전달하는 것이 좋습니다. 설정하고 이해하기 쉽습니다.

그러나 대상보기에서 UI 요소 (레이블, 텍스트 필드 등)를 직접 업데이트하지 않는 것이 좋습니다. 제 의견으로는, 이것은 많은 문제를 야기하는 불량 커플 링입니다.

대신 대상 호출 컨트롤러에서 데이터를 전달하기 위해 호출자가 prepareForSegue에서 설정할 수있는 속성이나 속성을 만듭니다. 이들은 데이터 전달에만 사용되는 특수 목적의 속성이어야합니다. 대상보기 컨트롤러는이 속성의 데이터를 사용하여 UI 또는 내부 상태를 업데이트합니다.

위임은 유효한 접근 방법이지만, 대부분의 상황에서 과도하게 사용됩니다. 더 많은 설정이 필요하며 더 추상적입니다. 이 추상화는 많은 뷰 컨트롤러 관계에서 필요하지 않습니다. 뷰 컨트롤러를 재사용해야한다는 것을 알게되면 언제든지 나중에 위임을 리 팩터로 사용할 수 있습니다.

2

prepareSegue가보기 컨트롤러간에 데이터를 전달하는 이상적인 방법이라고 생각하지 않습니다. 적어도 직접적으로는 아닙니다.

prepareForSegue을 사용하여보기 컨트롤러간에 값을 전달하는 것에 대한 우려를 공유합니다. 소스 뷰 컨트롤러는 대상 뷰 컨트롤러 (및 그 반대의 경우)와 관련하여 아무 것도 알지 못한다. 이상적으로 보기 컨트롤러는 서로 가시성이없는 별도의 섬이어야합니다.

스토리 보드가 권장하는 커플 링을 해결하기 위해 종종 뷰 컨트롤러간에 데이터를 전달하기 위해 mediator pattern 양식을 사용했습니다. 다음은 스토리 보드에서이 패턴의 버전을 구현하는 방법에 대한 블로그 게시물입니다 : http://coding.tabasoft.it/ios/mediator-pattern-in-swift/. 언제나 그렇듯이,이 패턴은 모든 상황에 가장 적합하지 않을 수 있지만, 나는 과거의 많은 프로젝트에서 좋은 해결책이라고 생각합니다.

기본적으로 스토리 보드 패러다임에서 조정자 패턴이 작동하는 방법은 각보기 컨트롤러의 prepareForSegue 메소드에서 segue 객체가 조정자 객체로 전달된다는 것입니다. 뷰 컨트롤러는 내부의 정보 나 내비게이션의 위치를 ​​신경 쓰지 않습니다. 그냥 보이지 않게 될 것입니다. segue 객체 (소스 및 대상보기 컨트롤러 포함)를 통과 한 조정자는 소스 및 대상보기 컨트롤러간에 데이터를 전달합니다.

이 패턴을 사용하면 각보기 컨트롤러는 다른보기 컨트롤러가 다른 하나의 존재를 멋지게 인식하지 못합니다. 한편, 조정자 클래스는 탐색 경로에서보기 제어기 (및보기 제어기의 인터페이스) 간의 관계를 알아야합니다. 분명히 네비게이션이 변경되거나 뷰 컨트롤러 자체가 변경되면 조정자 클래스가 조정해야합니다. 그러나 각보기 컨트롤러는 서로 의존 할 필요가 없으므로 탐색 경로의 변경 사항이나 해당 탐색 경로의 다른보기 컨트롤러에 대한 변경 사항을 수용하기 위해 업데이트 할 필요가 없습니다.

0

'올바른 방법은 아니지만 올바른 방법입니다. 특히 스토리 보드 응용 프로그램에서.

여기에 값을 전달하고보기를 호출하는 다른 방법이 있습니다.

var myNewVC = NewViewController() 
myNewVC.data = self 
navigationController?.presentViewController(myNewVC, animated: true, completion: nil) 
관련 문제