2017-01-20 1 views
2

두 개의 빠른 클래스가 있으며 하나는 다른 신속 클래스의 메소드를 참조해야합니다. 각각의 뷰 컨트롤러 모두가 tabBarController에 부착, 그래서는 같은 인스턴스를 만들려고하고 있습니다 : MapVC 내가 전화 할 방법을 보유하고다른 Swift 클래스에서 메소드 호출 시도 중

let mapVC : MapVC = self.tabBarController!.viewControllers![1] as! MapVC 
mapVC.loadViewIfNeeded() 
mapVC.add(newLocation:location_one) // .add is the method I want to call 

. 그리고 mapViewtabBar의 두 번째 옵션이므로 인덱스는 1입니다. 그러나 mapVC 개체를 캐스팅하면 [fatal error: unexpectedly found nil while unwrapping an Optional value] 오류가 발생합니다. 문제가 인스턴스 mapVC을 만드는 것과 관련이 있다고 생각합니다. 올바르게 설정하지 않았다고 생각하지만 문제를 해결하는 방법을 모르겠습니다.

필자의 문제를 어떻게 표현할 지 잘 모르겠다. 아직도 혼란 스러우면, 나는 의견에 더 많은 정보를 제공 할 수있다.

답변

3

일반적으로 각 탭의 위임자로 사용자 정의 tabBarController을 사용하여이 작업을 수행하지만 스택의 viewControllers에 액세스하는 방법이 좋습니다. 버전에 무엇이 문제인지 알아 봅시다.

이 뭐죠 코드 최대 우리가 디버깅하는 데 도움이 될이

if let tC = self.tabBarController { 
    if let vcs = tC.viewControllers { 
     if let map = vcs[1] as? MapVC { 
      print("map vc found in stack") 
      map.loadViewIfNeeded() 
      map.add(newLocation:location_one) 
     } else { 
      print("no map vc found at index 1") 
     } 
    } else { 
     print("no stack found") 
    } 
} else { 
    print("no tab bar found") 
} 

처럼 실행 해보십시오, 당신은 nil를 반환하는 mapVC 확실하다?


편집 : 당신이 의견에 설명 된대로 떨어져 tabBarController에서 segueing 경우은 다음 새로 발표의 ViewController의 tabBarController 속성이 Apple Docs에 따라 전무 할 것이다.

보기 컨트롤러가 탭 표시 줄 컨트롤러 안에 포함되어 있지 않으면이 속성은 nil입니다.

하나의 해결책이도 당 vc2에서 vc3tabBarController로의 참조를 전달하는 것이다.

[tabBarController] 
    |  | 
    [vc1] [vc2] - both have a reference to tabBarController 
      | 
      [vc3] - no reference yet 

설정 vc3는 한 tabBar 참조 를 개최합니다 - 그것은 기존의 tabBarController 속성을 사용하는 대신 이에 대한 새로운 VAR를 만들 아마 가장 좋습니다.

class vc3:UIViewController { 

    var tabBarReference:UITabBarController? 

    func addALocation(location:CLLocationCoordinate2D) { 
     if let tbc = self.tabBarReference { 
      if let map = tbc.viewControllers[1] as? MapVC { 
       map.loadViewIfNeeded() 
       map.add(newLocation:location) 
      } 
     } 
    } 

} 

이어서 vc2 내부 vc3 액세스하고 제시하기 전에 그것을 기준을 수득 SEGUE 방법 준비 용도.

class vc2:UIViewController { 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if let vc3 = segue.destinationViewController as? vc3 
      vc3.tabBarReference = self.tabBarController 
     } 
    } 

    func goToVC3() { 
     self.performSegueWithIdentifier("goToVC3", sender: nil) 
    } 

} 

이 코드를 테스트하지 않은,하지만 나에게 당신이 얼마나 알려 이론적으로 작동합니다.

+0

이 코드를 내 코드에 구현하고 "탭 표시 줄을 찾을 수 없음"을 반환했습니다. 어느 것이 내가 문제라고 생각했지만,보기 컨트롤러가 tabBarController로 구성되어 있기 때문에 다소 이상합니다. 무슨 일이 일어나고 있는지 아십니까? – Kevin

+0

@Kevin 어떻게 tabroll에 viewController를 추가하고 있습니까? – Wez

+0

내 tabBar를 설정하는 방법은 원래 기본 (2 탭)을 사용하는 것입니다. 그런 다음 세 번째보기 컨트롤러에 연결되는 하단에 tabBarItem을 추가했습니다. 이 질문에 대한 대답이 있습니까? 더 많은 정보가 필요하시면 제공 해줘서 기쁩니다! – Kevin

0

위와 같은 기능을 구현하는 두 가지 방법은 대리인이나 알림을 사용하는 것입니다. 귀하의 경우 통지를 조사한 후 add(newLocation:)에 전화를 걸어 통보해야한다고 생각합니다.

다음은 다른 클래스에서 함수를 호출하는 클래스의 빠른 예입니다. 놀이터에 던져서 어떻게 작동하는지 볼 수 있습니다.

보기 컨트롤러의 경우 일반적으로 viewDidLoad의 이벤트를 관찰하기 시작하지만 클래스를 어떻게 구성했는지에 따라 다른 장소가 더 적합 할 수 있습니다.

class MapVC { 

    init() { 
     print("Adding self as observer now...") 
     NotificationCenter.default.addObserver(self, selector: #selector(add), name: NSNotification.Name.init("addNewLocation"), object: nil) 
    } 

    @objc func add(notification: Notification) { 
     guard let location = notification.object as? CLLocation else { 
      return print("Did not recieve a CLLocation object in notification") 
     } 
     print("Got location with lat: \(location.coordinate.latitude), and lon:\(location.coordinate.longitude)") 
     // your code for handling the addition of a new location 
    } 
} 

class OtherVC { 
    func add() { // however you're calling this function... you might be passing in a location here, but for demonstration, just creating a new one 
     let location = CLLocation(latitude: 100, longitude: 100) 
     NotificationCenter.default.post(name:  NSNotification.Name.init("addNewLocation"), object: location) 
    } 
} 


let mapVC = MapVC() 
let otherVC = OtherVC() 

otherVC.add() 
+0

알림은 무엇이며 어떻게 구현할 수 있습니까? – Kevin

+0

@Kevin 놀이터에 던져서 테스트해볼 수있는 예를 들어 답장했습니다. –

+0

나는 통보를 통해 정보를 전달한다는 개념을 좋아합니다. 귀하의 코드는 놀이터에서 작동하지만, 이것을 내 파일에 구현하려고하면 오류가 많이 생깁니다 (UIViewController의 하위 클래스에서 필요한 초기화 프로그램 init (코더)를 제공해야합니다). 구현은 놀이터에 비해 다른가요? – Kevin

0

NotificationCenter를 사용하여이를 수행 할 수 있습니다. 알림을 받고 조치를 취할 클래스에 알림 수신기를 등록해야합니다. 그런 다음 다른 클래스의 알림을 게시해야합니다. 다음과 같이 할 수 있습니다.

일반적으로 수신하려는 클래스의 viewDidLoad()에 알림을 등록해야합니다.

1

나는 ...보기 컨트롤러가 같이 존재하는 경우 내가 확인 것 ... 그리고

extension Collection where Indices.Iterator.Element == Index { 

    /// Returns the element at the specified index iff it is within bounds, otherwise nil. 
    subscript (safe index: Index) -> Generator.Element? { 
     return indices.contains(index) ? self[index] : nil 
    } 
} 

... 첫 번째 프로젝트에

guard let mapVC : MapVC = self.tabBarController?.viewControllers?[safe: 1] as? MapVC else { 
    print("could not find mapVC") 
    return 
} 
mapVC.loadViewIfNeeded() 
mapVC.add(newLocation:location_one) 

기회를이 안전 배열 확장을 추가 아마도이 방법을 너무 빨리 호출 할 것입니다. 탭 막대 또는 컨트롤러와 같은 소리가로드되지 않습니다. 최후의 수단으로 viewWillAppear 또는 viewDidAppear을 호출 해보십시오.

관련 문제