如何获取对已经实例化的 ViewController 的引用?
Posted
技术标签:
【中文标题】如何获取对已经实例化的 ViewController 的引用?【英文标题】:How to get reference to already instantiated ViewController? 【发布时间】:2015-11-14 12:43:28 【问题描述】:这里是新手。我试图让我的简单核心位置应用程序在通过locationManager
获取坐标后自动检索数据。
我已经实现了单独的类,不让我的主视图控制器负责太多的任务,这里看起来像这样:
import Foundation
import CoreLocation
class CoreLocationController : NSObject, CLLocationManagerDelegate
var locationManager = CLLocationManager()
var lastCoordinates: (lat: Double, lon: Double)?
override init()
super.init()
self.locationManager.delegate = self
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.distanceFilter = 3000
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
let location = locations.last! as CLLocation
self.lastCoordinates = (location.coordinate.latitude, location.coordinate.longitude)
print("didUpdateLocations: \(location.coordinate.latitude), \(location.coordinate.longitude)")
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus)
print("didChangeAuthorizationStatus")
switch status
case .NotDetermined:
print(".NotDetermined")
break
case .AuthorizedWhenInUse:
print(".AuthorizedWhenInUse")
self.locationManager.startUpdatingLocation()
break
case .Denied:
print(".Denied")
break
default:
print("Unhandled authorization status")
break
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
当然我已经在 AppDelegate.swift 中初始化了
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
var window: UIWindow?
var coreLocationController: CoreLocationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
self.coreLocationController = CoreLocationController()
return true
现在我的主要ViewController
在单击按钮后正在执行retrieveWeatherForecast
,并将appDelegate
传递给它以获取对CoreLocationController.lastCoordinates
属性的引用。我得出的结论是,为了在启动后立即获取坐标后执行retrieveWeatherForecast
,最好的方法是在locationManager
func(带有didUpdateLocations
参数的那个)中运行此方法。为了做到这一点,我需要参考 ViewController
运行实例来执行类似的操作:
runningViewControlerinstance.retrieveWeatherForecast(runningViewControlerinstance.appDel)
主ViewController
代码:
import UIKit
class ViewController: UIViewController
@IBOutlet weak var currentTemperatureLabel: UILabel?
@IBOutlet weak var currentHumidityLabel: UILabel?
@IBOutlet weak var currentPrecipitationLabel: UILabel?
@IBOutlet weak var currentWeatherIcon: UIImageView?
@IBOutlet weak var currentWeatherSummary: UILabel?
@IBOutlet weak var refreshButton: UIButton?
@IBOutlet weak var activityIndicator: UIActivityIndicatorView?
let appDel = UIApplication.sharedApplication().delegate! as! AppDelegate
private var forecastAPIKey: String?
override func viewDidLoad()
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("APIkeys", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
self.forecastAPIKey = dict!.objectForKey("forecastAPIKey") as? String
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
func retrieveWeatherForecast(appDel: AppDelegate )
let currentCoordinates :(lat: Double, lon: Double) = (appDel.coreLocationController?.lastCoordinates)!
let forecastService = ForecastService(APIKey: forecastAPIKey!)
forecastService.getForecast(currentCoordinates.lat, lon: currentCoordinates.lon)
(let currently) in
if let currentWeather = currently
dispatch_async(dispatch_get_main_queue())
if let temperature = currentWeather.temperature
self.currentTemperatureLabel?.text = "\(temperature)º"
if let humidity = currentWeather.humidity
self.currentHumidityLabel?.text = "\(humidity)%"
if let precipitation = currentWeather.precipProbability
self.currentPrecipitationLabel?.text = "\(precipitation)%"
if let icon = currentWeather.icon
self.currentWeatherIcon?.image = icon
if let summary = currentWeather.summary
self.currentWeatherSummary?.text = summary
self.toggleRefreshAnimation(false)
@IBAction func refreshWeather()
toggleRefreshAnimation(true)
retrieveWeatherForecast(appDel)
func toggleRefreshAnimation(on: Bool)
refreshButton?.hidden = on
if on
activityIndicator?.startAnimating()
else
activityIndicator?.stopAnimating()
我将非常感谢您 swift 社区的任何帮助、cmets 和建议,谢谢!
【问题讨论】:
【参考方案1】:如果您有一个单独的类来处理位置服务(这是一个很好的设计模式)或应用程序委托,那么通知任何活动视图控制器的最佳方式是通过NSNotification
。
通过viewDidAppear
中的NSNotificationCenter
在视图控制器中注册,并在viewWillDisappear
中将自己移除为观察者。有很多文档可以解释细节。
控制器与异步进程的这种松散耦合比保留对 UI 对象的引用要安全得多。
【讨论】:
【参考方案2】:“当然我已经在 AppDelegate.swift 中初始化了” 为什么?没有理由在那里初始化它,是吗?在您打算使用它的地方初始化它。您的 viewController 需要访问您的 CoreLocationController 才能使用、显示或编辑位置。所以初始化并在那里使用它,你不必将你的视图控制器传递给你的位置管理器。
【讨论】:
这可能会导致多个核心位置控制器。在这里,单例模式显然更可取。 好的。由于它是 swift ,所以在 CoreLocationController 中声明一个静态变量(这也是一个惰性变量)也是可能的。以上是关于如何获取对已经实例化的 ViewController 的引用?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 QML 中的 GridView 或 ListView 获取实例化的委托组件
从 SceneDelegate 获取 viewController 实例化的错误
在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型
如何从QML中的GridView或ListView获取实例化的委托组件