簡體   English   中英

嘗試從其他Swift類調用方法

[英]Trying to Call Method From Different Swift Class

我有兩個swift類,其中一個需要在另一個swift類中引用一個方法。 各自的視圖控制器都連接到tabBarController ,因此我嘗試創建一個類似這樣的實例:

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

MapVC擁有我希望調用的方法。 mapViewtabBar上的第二個選項,因此索引為1。但是,當我mapVC對象mapVC時,出現了錯誤[fatal error: unexpectedly found nil while unwrapping an Optional value][fatal error: unexpectedly found nil while unwrapping an Optional value] 我認為問題與創建實例mapVC ,並且我認為可能未正確設置它,但是我不確定如何解決它。

我不太確定如何表達我的問題,因此,如果您仍然感到困惑,我可以在評論中提供更多信息。

我通常使用一個自定義的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")
}

這可能有助於我們調試您的代碼,您確定是mapVC返回nil嗎?


編輯:您在注釋中描述,如果你是從segueing客場tabBarController那么新提出的viewController的tabBarController屬性將是零按照蘋果公司的文檔

如果視圖控制器未嵌入在選項卡欄控制器中,則此屬性為nil。

一種解決方案是將一個引用傳遞tabBarControllervc3vc2按本圖。

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

設置vc3以保存tabBar引用 -最好為此創建一個新的變量 ,而不是使用現有的tabBarController屬性。

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 ,並給它的基准被呈現之前。

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)
    }

}

我沒有測試過此代碼,但是它應該在理論上起作用,請告訴我您的情況。

我會首先將此安全數組擴展添加到您的項目中...

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中進行調用作為最后的選擇。

實現此類目標的兩種方法是通過委托或通知。 就您而言,我認為您應該調查通知,然后在通知時調用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()

您可以使用NotificationCenter進行此操作。 您將需要在要接收通知並采取措施的類中注冊通知偵聽器。 然后,您需要發布其他課程的通知。 您可以這樣:

 // Define identifier
let notificationName = Notification.Name("MyNotification")

// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(methodToCallWhenReceivingNotification), name: notificationName, object: nil)

// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)

同樣,通常,您應該在要接收它的類的viewDidLoad()中注冊通知。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM