如何从现有的View Controller类调用函数?

时间:2015-08-03 06:11:52

标签: ios swift class oop uiviewcontroller

我仍然是Swift开发人员的早期阶段。我正在尝试创建一个功能,我点击屏幕上的按钮,然后我得到iPhone的提示以允许位置,当我点击允许时,我会自动导航到另一个屏幕。

到目前为止,我已经做了以下事情:

  • 创建了一个单独的类(“User”),其中处理了所有位置函数
  • 在第一个视图控制器上设置一个按钮,以及从“用户”调用位置提示功能的适当IBAction
  • 为第一个和第二个视图控制器添加了故事板ID
  • 在第一个视图控制器类中创建了一个函数(“changeScreen”),用于执行到另一个视图的导航
  • 在“用户”类中设置一个监听器,用于用户点击允许位置,然后调用“changeScreen”功能

我认为还有另一种方法可以做到这一点(称之为某种完成处理程序),我玩弄了1-2个小时,没有任何效果。到目前为止,这个解决方案几乎完全有效,但我得到以下错误:

  

警告:尝试在_____上显示____,其视图不在窗口层次结构中!

这是我的“用户”类中的代码

class User: NSObject, CLLocationManagerDelegate {

func getLocation(){

    // For use in foreground
    locationManager.requestWhenInUseAuthorization()

    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    //locationManager.startUpdatingLocation()

    println("hello location")


}

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status:CLAuthorizationStatus){

        if status == .AuthorizedWhenInUse {

            locationManager.startUpdatingLocation()

            firstView!.showSecondScreen() // this is where I call the other      class's function

        }
    }
  }

这是我的First View控制器类中的代码

var firstView: FirstView? = nil

class FirstView: UIViewController {

var newUser = User()

override func viewDidAppear(animated: Bool) {

    firstView = self.storyboard!.instantiateViewControllerWithIdentifier("firstView") as? FirstView

// here i take the first view controller class and store it into a public variable

}

@IBAction func allowLocationBtn(sender: AnyObject) {

    newUser.getLocation()  // this is the first button clicked

}

func showSecondScreen(){

    let secondScreen = self.storyboard!.instantiateViewControllerWithIdentifier("SecondScreen") as! SecondScreen

    self.presentViewController(secondScreen, animated: true, completion:   nil  )

}

聚苯乙烯。我知道我可以将所有代码组合成一个类,它可以像这样工作。但我想以“正确”的方式做到这一点,在不同的类别中有不同的功能。

2 个答案:

答案 0 :(得分:1)

  • 尝试设置first = self,不要实例化新的视图控制器
  • 如果使用故事板,最好使用segues来显示另一个屏幕

虽然这里的正确之处是拥有UserDelegate协议

protocol UserDelegate { func displayOtherScreen( ) }

然后在User添加var delegate: UserDelegate? 并在locationManager函数中而不是调用 firstView!.showSecondScreen致电 delegate?.displayOtherScreen( )

然后让FirstView采用UserDelegate协议

class FirstView: UIViewController, UserDelegate {
var newUser = User()

override func viewDidAppear(animated: Bool) {
    newUser.delegate = self
    ...
    }
    ...
    ...
func displayOtherScreen( ) {
    showSecondSceen( ) 
    }

现在不需要第一个变量..

答案 1 :(得分:0)

理想情况下,您尝试处理多个MVC的情况。您的第二个屏幕本身应该是一个不同的视图,并且应该有自己的模型视图控制器。这样你就不会破坏MVC架构的规则。您的ShowSecondScreen()功能应由SecondViewController控制。

一旦定义了多个MVC,您就可以将它们连接起来。 有一些方法可以做到这一点 - UISplitViewController, UITabViewController, UINavigationViewController。在您的情况下,UINavigationViewController似乎是最佳选择。您可以使用Editor -> Embed上的class FirstView添加导航控制器以连接MVC。那会使FirstView controller成为你的rootViewController。

然后将FirstView上的按钮中的segue添加到控制器以进行SecondScreen,SecondViewController

class FirstView: UIViewController {
    override func prepareForSegue(..) {
        if let secondControllerObject = segue.destinationViewController as? SecondViewController {
            if let identifier = segue.identifier {
                 switch identifier {
                       case "<your_buttons_identifier_string" : secondControllerObject .callToSecondScreen() 
/* Now will move the Second View to the top of the MVC stack and you 
will be also able to go back to first view as you have a 
Navigation Controller hooked up.*/
/* callToSecondScreen - should be a controller object displaying the
 controlling and displaying contents in the second screen's view. 
Data for second screen's view will come from its Model */

        }