将变量结果从一个视图控制器传递到另一个非视图控制器swift文件

时间:2017-12-07 07:34:17

标签: ios swift

我正在尝试创建一个iOS应用程序,它从文本字段中获取用户名,将其转换为字符串并将其传递给另一个名为HomeModel.swift的文件。这个文件是一个ViewController,但我需要将该变量名添加到一个URL。

目前,我的应用程序设置了一个初始视图控制器,其中包含用户名和登录按钮的文本字段。当我单击登录按钮时,它将获取文本字段条目并将其转换为字符串,然后我将其用于在下一个ViewController上转换为标签。我的问题是将用户名变量(我以前变成标签)并将其传递给非ViewController swift文件,这样我就可以用它做一些“幕后”的东西。

任何帮助都会非常感激,因为我花了好几个小时试图找到一个答案,但却出现了短暂的问题。

这是我最初的ViewController

import UIKit

class Home: UIViewController, UITextFieldDelegate {

@IBOutlet var TextField: UITextField!
@IBOutlet var PasswordField: UITextField!
@IBOutlet var LoginBtn: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    self.TextField.delegate = self
    self.PasswordField.delegate = self

    func checkField(sender: Any?) {
        if (TextField.text?.isEmpty)! || (PasswordField.text?.isEmpty)!
        {
            LoginBtn.isEnabled = false

        }
        else
        {
            LoginBtn.isEnabled = true
        }
    }
}

//Hide keyboard when touched outisde keyboard
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    PasswordField.resignFirstResponder()
    return (true)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let DestViewController : ViewTwo = segue.destination as! ViewTwo

    DestViewController.PasswordText = PasswordField.text!
    DestViewController.LabelText = TextField.text!
}

}

这是HomeModel.swift文件

import Foundation

protocol HomeModelProtocol: class {
func itemsDownloaded(items: NSArray)
}

class HomeModel: NSObject, URLSessionDataDelegate {

//properties

weak var delegate: HomeModelProtocol!

func viewDidLoad() {

}

func downloadItems() {

    let myusername = //Variable from initial controller here

    let urlPath = "http://urlhere.com/index.php?username="+myusername //this is where the list of users are

    let url: URL = URL(string: urlPath)!
    let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
    let task = defaultSession.dataTask(with: url) { (data, response, error) in

        if error != nil {
            print("Failed to download data")
        }
        else {
            print("Contact List Data Downloaded")
            self.parseJSON(data!)
        }
    }
    task.resume()
}

func parseJSON(_ data:Data) {
    var jsonResult = NSArray()
    print (jsonResult)

    do {
        jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray

    }
    catch let error as NSError {
        print(error)
    }

    var jsonElement = NSDictionary()
    let locations = NSMutableArray()

    for i in 0 ..< jsonResult.count
    {
        jsonElement = jsonResult[i] as! NSDictionary

        let location = LocationModel()

        //the following insures none of the JsonElement values are nil through optional binding
        if let name = jsonElement["name"] as? String,
            let phone = jsonElement["phone"] as? String
        {
            location.name = name
            location.phone = phone
        }

        locations.add(location)
    }

    DispatchQueue.main.async(execute: { () -> Void in

        self.delegate.itemsDownloaded(items: locations)

    })
}
}

1 个答案:

答案 0 :(得分:1)

通常根据您的描述,这只是在您拥有的视图控制器之间传递对象。假设有:

class LoginData {
   var username: String?
}

现在你的第一个视图控制器似乎是你的入口点,所以它就是那个创建它的人,例如&#34; next&#34;按下按钮。然后应该将此对象传递给新的视图控制器:

@IBAction onNextPressed() {
    let loginData = LoginData() // Create object
    loginData.username = self.textField.text // Set data to it

    let nextController = UIStoryboard(...) as! NextViewController // Generate new view controller
    nextController.loginData = loginData // Assign login data
    navigationController.push(... nextController ...) // Show controller
}

那么下一个视图控制器应该使用这个对象:

class NextViewController: UIViewController {
    var loginData: LoginData?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.label.text = loginData?.username
    }

...

在某些情况下(看起来像你的),全局保存数据可能是有意义的。要做到这一点,您只需要一个静态变量。在您的情况下,我建议您创建一个新对象User

class User {
    static var current: User?

    var loginData: LoginData?
}

现在这里User只包含登录数据,但是还有一个占位符来添加当前用户的实例,可以在应用程序内部使用。

现在对于这种情况,第一个视图控制器不需要将数据传递给下一个视图控制器,而是设置当前用户:

@IBAction onNextPressed() {
    let loginData = LoginData() // Create object
    loginData.username = self.textField.text // Set data to it

    let newUser = User() // Create a new user
    newUser.loginData = loginData // Assign login data to it
    User.current = newUser // Set current user

    let nextController = UIStoryboard(...) // Generate new view controller
    navigationController.push(... nextController ...) // Show controller
}

新视图控制器不需要对登录数据的引用:

class NextViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.label.text = User.current?.loginData?.username
    }

...

当您需要在整个应用中使用这些数据时,这非常棒,因为您提到了一些网址,如果您实施,您现在可以在任何地方User.current?.serviceURL拨打电话:

extension User {
   var serviceURL: URL? {
      guard let username = username else {
         return nil
      }
      return URL(string: "https://some.pat/\(username)/resource_name")
   }
}

我希望这清除了一些关于在Swift中传递数据的事情。