[英]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
擁有我希望調用的方法。 mapView
是tabBar
上的第二個選項,因此索引為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。
一種解決方案是將一個引用傳遞tabBarController
到vc3
從vc2
按本圖。
[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.