Justin Hodges Justin Hodges - 1 year ago 81
Swift Question

Saving username information to a server instead of NSDefaults (iOS)

I have a server for storing username and password data in my application. When testing the app I had everything save to the device locally using NSDefaults, but now that the app is close to being fully launched, I am trying to save them to the server instead, as it is safer that way for the user's information.

When I had it save to NSDefaults, it was easy and short work. Now however, I am trying to POST the data to the server and keep getting build errors. What do I need to change for this to work? Am I not fully understanding how POST and GET works? Thanks. Using Swift 2 as of right now, not my choice, I prefer 3, but my boss isn't letting us update it yet.

The current error is coming from the POST USER DATA TO SERVER section, where xcode claims that userNmeTxt cannot be converted into NSData. Thank you in advance.

EDIT: Error is on line 87: "Cannot convert value of type UITextField! to expected argument type NSData!"

import UIKit

class UserNameViewController: AuthorizationViewController {

@IBOutlet weak var userNameTxt: UITextField!
@IBOutlet weak var continueBtn: UIButton!

var userModel: ProfileModel!

//MARK: - SYSTEMS METHODS

override func viewDidLoad() {
super.viewDidLoad()
userNameTxt.delegate = self
userNameTxt.autocapitalizationType = .Sentences
setEnabledButton()
}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBarHidden = false
self.navigationItem.leftBarButtonItem = getBackButton()
self.title = ""
}

override func viewWillDisappear(animated: Bool) {
self.navigationController?.navigationBarHidden = true
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

continueBtn.layer.cornerRadius = 10
}

override func popToRoot(sender:UIBarButtonItem){
self.navigationController!.popViewControllerAnimated(true)
}

//MARK: - CHECK FOR AVALABILITY

func setEnabledButton(){
if userNameTxt.text == "" {
continueBtn.backgroundColor = UIColor.lightGrayColor()
} else {
continueBtn.backgroundColor = UIColor(colorLiteralRed: 63.0/255.0, green: 220.0/255.0, blue: 236.0/255.0, alpha: 1.0)
}
continueBtn.userInteractionEnabled = userNameTxt.text != ""
}

//MARK: - POST USER DATA TO SERVER

func postData(url: String, params: Dictionary<String, String>, completionHandler: (data: NSData?, response: NSURLResponse?, error: NSError?) -> ()) {

// Indicate download
UIApplication.sharedApplication().networkActivityIndicatorVisible = true

let url = NSURL(string: "myPlaceholderURLgoesHere")!
// print("URL: \(url)")
let request = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

// Verify downloading data is allowed
do {
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
} catch let error as NSError {
print("Error in request post: \(error)")
request.HTTPBody = nil
} catch {
print("Catch all error: \(error)")
}

// Post the data
let task = session.dataTaskWithRequest(request) { data, response, error in
completionHandler(data: userNameTxt, response: userModel, error: error)

// Stop download indication
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
// Stop download indication

}

task.resume()

}

//MARK: - SEGUE

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toPassword"{
let controller = segue.destinationViewController as! PasswordViewController
controller.userModel = userModel
}
}

//MARK: - IB ACTIONS
@IBAction func continuePressed(sender: AnyObject) {
userModel.userNickName = userNameTxt.text!
performSegueWithIdentifier("toPassword", sender: self)
}
}

extension UserNameViewController: UITextFieldDelegate{
func textFieldDidEndEditing(textField: UITextField) {
self.setEnabledButton()
}
}

Answer Source

There are a couple of things you need to change.

userNameTxt is not the username, it's the UITextField containing the username. The text you need is userNameTxt.text?

If the function is expecting Data, you have to convert your text to Data first

let task = session.dataTaskWithRequest(request) { data, response, error in
    completionHandler(data: userNameTxt.text?.data(using: .utf8), response: userModel, error: error)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download