Validate text fields swift 3 - ios

I am trying to make all of my text fields required to make sure that users does not leave it empty. I tried this but for some reason it's not working. I feel like my logic is correct, but it's an issue with swift's logic
Here is my code:
let title = txtTitle.text!
let location = txtWhere.text!
let when = txtWhen.text!
if title != nil && location != nil && when != nil {
var titleArray = [String]()
var whereArray = [String]()
var whenArray = [String]()
let titleObject = UserDefaults.standard.object(forKey: "saveTitle")
let whereObject = UserDefaults.standard.object(forKey: "saveLocation")
let whenObject = UserDefaults.standard.object(forKey: "saveWhen")
if let tempTitle = titleObject as? [String] {
titleArray = tempTitle
titleArray.append(txtTitle.text!)
print(titleArray)
}
else {
titleArray = [txtTitle.text!]
}
if let tempWhere = whereObject as? [String] {
whereArray = tempWhere
whereArray.append(txtWhere.text!)
//print(titleArray)
}
else {
whereArray = [txtWhere.text!]
}
if let tempWhen = whenObject as? [String] {
whenArray = tempWhen
whenArray.append(txtWhen.text!)
//print(titleArray)
}
else {
whenArray = [txtWhen.text!]
}
UserDefaults.standard.set(titleArray, forKey: "saveTitle")
UserDefaults.standard.set(whereArray, forKey: "saveLocation")
UserDefaults.standard.set(whenArray, forKey: "saveWhen")
txtTitle.text = ""
txtWhere.text = ""
txtWhen.text = ""
txtTime.text = ""
}
else
{
errMsg.isHidden = false
errMsg.text = "All fields are required"
}
}

To check reliably if the text properties of the text fields are not nil and not empty use
if let title = txtTitle.text, !title.isEmpty,
let location = txtWhere.text, !location.isEmpty,
let when = txtWhen.text, !when.isEmpty { ...
If all conditions are passed the three variables are safely unwrapped.

a. You shouldn't force unwrap (txtTitle.text!): instead check the optional value
b. You may want to check for empty strings instead of just for nil
That said, you can test for validity like that:
let title = txtTitle.text
if title?.isEmpty == false {
...// title was filled
}
Or better (thank you Leo Dabus):
if let title = txtTitle.text, !title.isEmpty {
...// title was filled
}

TEXTFIELD VALIDATION
======================>
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
switch (textField.tag)
{
case 1:
password.becomeFirstResponder()
case 2 :
confirm_pass.becomeFirstResponder()
case 3 :
email.becomeFirstResponder()
case 4 :
phone.becomeFirstResponder()
case 5 :
phone.resignFirstResponder()
default: break
}
return true
}
func textFieldShouldClear(_ textField: UITextField) -> Bool
{
return true
}
func textFieldDidEndEditing(_ textField: UITextField)
{
if (textField == username)
{
let name_reg = "[A-Za-z0-9]{5,20}"
let name_test = NSPredicate(format: "SELF MATCHES %#", name_reg)
if name_test.evaluate(with: username.text) == false
{
let alert = UIAlertController(title: "Information", message: "Enter the name in correct format", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alert.addAction(ok)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
}
if (textField == password)
{
let name_reg = "[A-Z0-9a-z._%#+-]{6,10}"
let name_test = NSPredicate(format: "SELF MATCHES %#", name_reg)
if name_test.evaluate(with: password.text) == false
{
let alert = UIAlertController(title: "Information", message: "Enter the password in correct format", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alert.addAction(ok)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
}
if (textField == email)
{
let name_reg = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
let name_test = NSPredicate(format: "SELF MATCHES %#", name_reg)
if name_test.evaluate(with: email.text) == false
{
let alert = UIAlertController(title: "Information", message: "Enter the E-mail in correct format", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alert.addAction(ok)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
}
if (textField == phone)
{
let name_reg = "[0-9]{10}"
let name_test = NSPredicate(format: "SELF MATCHES %#", name_reg)
if name_test.evaluate(with: phone.text) == false
{
let alert = UIAlertController(title: "Information", message: "Enter your number in correct format", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alert.addAction(ok)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
}
}

Related

How can I get data from API in Swift?

How can I get location, time, lng, lat, mag and depth data from this API in Swift?
https://api.hknsoft.com/earthquake/v1/last24hours?limit=500
//API
let url = URL(string: "https://api.hknsoft.com/earthquake/v1/last24hours?limit=500")
let session = URLSession.shared
let task = session.dataTask(with: url!) { data, response, error in
if error != nil {
let alert = UIAlertController(title: "Error!", message: error?.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
} else {
if data != nil {
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String, Any>
DispatchQueue.main.async {
//print(jsonResponse)
if let result = jsonResponse["earthquakes"] as? [String : Any] {
if let location = result["location"] as? String {
print(location)
}
if let time = result["time"] as? String {
print(time)
}
if let mag = result["mag"] as? Double {
print(mag)
}
if let lat = result["lat"] as? Double {
print(lat)
}
if let lng = result["lng"] as? Double {
print(lng)
}
if let depth = result["depth"] as? Double {
print(depth)
}
}
}
} catch {
print("alert")
let alert = UIAlertController(title: "Error!", message: error.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
}
}
}
}
task.resume()

Swift UIRefresh Control Drag to refresh in UITableView causes app crash

I have a UIRefreshControll, inside my TableView. All works fine, but if i pull the tableview too fast, the app crashes.
Error: Fatal error: Index out of range
When i call the function refreshData from a Button, the crash doesnt appear. Is kind of weird because refreshControll doesnt do something different than calling a action.
I hope somebody can help me.
private let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(self.refreshData), for: .valueChanged)
if #available(iOS 10.0, *) {
self.tableView.refreshControl = self.refreshControl
} else {
self.tableView.addSubview(self.refreshControl)
}
#objc private func refreshData() {
if isRefreshing {
self.refreshControl.endRefreshing()
return
}
isRefreshing = true
print("refresh")
guard let url = URL(string: taskURL) else {
return
}
let request = URLRequest(url: url)
urlSessionBackground.dataTask(with: request) { (dataOpt, response, error) in
if error != nil {
DispatchQueue.main.async {
let alert = UIAlertController(title: "Loading Error", message: "No Internet Connection. Please try again later.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {(action: UIAlertAction!) in
self.refreshControl.endRefreshing()
}))
self.present(alert, animated: true)
}
return
}else {
self.data.removeAll()
self.userImage.removeAll()
self.currentData.removeAll()
self.taskDetails.removeAll()
}
guard let dataNew = dataOpt else {
return
}
let appdata = try? JSONDecoder().decode(TaskList.self, from: dataNew)
for data in appdata!{
self.data.append(CellData.init(image: UIImage(named: "Profile"), message: data.name, checkImage: data.status))
self.userImage.append("")
self.taskDetails.append(TaskDetails.init(status: data.status, assigned: data.assigneUid, time: data.duedateTsUTC, priority: data.priority, desc: data.desc, uid: data.uid))
}
self.currentData = self.data
DispatchQueue.main.async {
self.tableView.reloadData()
self.searchBar.text = ""
self.isRefreshing = false
self.refreshControl.endRefreshing()
}
}.resume()
}
Fixed it: Used temporary variables to save data and use afterwards. Deleting the data was the problem.
Try this
if error != nil {
DispatchQueue.main.async {
let alert = UIAlertController(title: "Loading Error", message: "No Internet Connection. Please try again later.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {(action: UIAlertAction!) in
self.refreshControl.endRefreshing()
}))
self.present(alert, animated: true)
}
return
}else {
if self.data != nil{
self.data.removeAll()
}
if self.userImage != nil{
self.userImage.removeAll()
}
if self.currentData != nil{
self.currentData.removeAll()
}
if self.taskDetails != nil{
self.taskDetails.removeAll()
}
}
Just try this
var dataTask: URLSessionDataTask?
let defaultSession = URLSession(configuration: .background)
#objc private func refreshData() {
if isRefreshing {
self.refreshControl.endRefreshing()
return
}
isRefreshing = true
print("refresh")
guard let url = URL(string: taskURL) else {
return
}
dataTask?.cancel()
let request = URLRequest(url: url)
dataTask =
defaultSession.dataTask(with: url) { [weak self](dataOpt, response, error) in
defer {
self?.dataTask = nil
}
if let error = error {
DispatchQueue.main.async {
let alert = UIAlertController(title: "Loading Error", message: "No Internet Connection. Please try again later.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {(action: UIAlertAction!) in
self.refreshControl.endRefreshing()
}))
self.present(alert, animated: true)
}
return
} else if
let data = dataOpt,
let response = response as? HTTPURLResponse,
response.statusCode == 200 {
self.data.removeAll()
self.userImage.removeAll()
self.currentData.removeAll()
self.taskDetails.removeAll()
let appdata = try? JSONDecoder().decode(TaskList.self, from: data)
for data in appdata!{
self.data.append(CellData.init(image: UIImage(named: "Profile"), message: data.name, checkImage: data.status))
self.userImage.append("")
self.taskDetails.append(TaskDetails.init(status: data.status, assigned: data.assigneUid, time: data.duedateTsUTC, priority: data.priority, desc: data.desc, uid: data.uid))
}
self.currentData = self.data
DispatchQueue.main.async {
self.tableView.reloadData()
self.searchBar.text = ""
self.isRefreshing = false
self.refreshControl.endRefreshing()
}
}
}
dataTask?.resume()
}

Update information user profile Swift 4

Hello i just implements the method to modify and update the user profile on swift 4 and i have a problem updating the user information (firstname and lastname) in token
//Get token
let token = HPWSLoginManager.shared().saveSuccessResponse.token
// Bearer token to update information
let url = URL(string: "http://51.38.36.76:40/api/v1/updateProfile")
var request = URLRequest(url: url!)
request.httpMethod = "PUT"
request.addValue("Bearer \(token!)", forHTTPHeaderField: "Authorization")
//serialization token
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: AnyObject]
let sub = json["sub"] as? [String: AnyObject]
DispatchQueue.main.async {
//Get current user
let myUser = PFUser.current()
// check if firstName, lastName are not empty
if(self.firstNameTextfield.text!.isEmpty || self.lastNameTextfield.text!.isEmpty )
{
let myAlert = UIAlertController(title: "Alert", message: "First name and Last name are required fields", preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil);
return
}
// set new values user
let userFirstName = self.firstNameTextfield.text
let userLastName = self.lastNameTextfield.text
// update information
myUser?.setObject(userFirstName, forKey: "\(sub?["firstname"])")
myUser?.setObject(userLastName, forKey: "\(sub?["lastname"])")
//display activity indicator
let loadingNotification = MBProgressHUD.showAdded(to: self.view, animated: true)
loadingNotification.labelText = "sauvegarde des informations"
myUser?.saveInBackground(block: { (success:Bool, error:NSError?) -> Void in
// Hide activity indicator
loadingNotification.hide(animated: true)
if(error != nil)
{
let myAlert = UIAlertController(title: "Alert", message: error!.localizedDescription, preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil);
return
}
if(success)
{
let userMessage = "votre profil a été mis a jour"
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {(action:UIAlertAction!) -> Void in
self.dismiss(animated: true, completion: {() -> Void in
// self.opener.loadUserDetails()
})
})
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil);
}
} as! PFBooleanResultBlock)
}
} catch {
print("error")
}
}.resume()
I do not know if it's the right way to update the information, and he recovers userFirstName, userLastName when I seize but myUser?.setObject(userFirstName, forKey: "\(sub?["firstname"])") displays nil on the console. I really need your help thank you in advance :)
Try Replacing these lines in the above code -
var myUser = PFUser.current()
myUser?["\(sub?["firstname"])"] = userFirstName
myUser?["\(sub?["lastname"])"] = userLastName

Alert when Parse Query doesn't return results

basically I am running a tinder like app, which gives you a new person everytime you are swiping.
At some point my Query doesn't give back anymore users, since all are already rejected or accepted. Any ideas how to set an alert, when my Query doesn't return users anymore?
query?.whereKey("objectId", notContainedIn: ignoredUsers)
// Immer nur ein Resultat pro Zeit.
query?.limit = 1
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error != nil {
//Alert raushauen für einen Error:
let userMessage = error!.localizedDescription
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
return
// Muss nicht mehr auf PFObject gecastet werden (von AnyObject?)
} else if let objects = objects {
for object in objects {
displayedUserId = object.objectId!
// Name, Alter und Hashtags müssen gedownloaded werden.
// first_name sollte es ja immer geben.
var profilText = object["first_name"] as! String
self.ContainerVC.nameAgeLabel.text = profilText
if let geburtstag = object["birthday"] as? String {
profilText += ", " + geburtstag
self.ContainerVC.nameAgeLabel.text = profilText
}
if let hashtags = object["hashtags"] as? String {
self.ContainerVC.hashtagTextField.text = hashtags
}
let imageFile = object["firstImage"] as! PFFile
// Image muss ja erstmal gedownloaded werden.
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error != nil {
let userMessage = error!.localizedDescription
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
return
} else {
if let data = imageData {
self.ContainerVC.profilePicture.image = UIImage(data: data)
self.ContainerVC.miniImage.image = UIImage(data: data)
}
}
}
}
}
})
}
}
The following may work.
...} else if let objects = objects {
if objects.length() == 0 {
let myAlert = UIAlertController(title: "Alert", message: "No Users", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
} else {
for object in objects {
displayedUserId = object.objectId!
// Name, Alter und Hashtags müssen gedownloaded werden.
// first_name sollte es ja immer geben.
var profilText = object["first_name"] as! String
self.ContainerVC.nameAgeLabel.text = profilText
if let geburtstag = object["birthday"] as? String {
profilText += ", " + geburtstag
self.ContainerVC.nameAgeLabel.text = profilText
}
if let hashtags = object["hashtags"] as? String {
self.ContainerVC.hashtagTextField.text = hashtags
}
let imageFile = object["firstImage"] as! PFFile
// Image muss ja erstmal gedownloaded werden.
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error != nil {
let userMessage = error!.localizedDescription
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
return
} else {
if let data = imageData {
self.ContainerVC.profilePicture.image = UIImage(data: data)
self.ContainerVC.miniImage.image = UIImage(data: data)
}
}
}
}
}
}
Just a disclaimer... your approach on querying one user every swipe is not the most effective. You could get a collection of users and then use it as a buffer for every swipe.

App crashes once Restart Game clicked

App crashes when either player presses the Restart button. I tried adding an alert that shows up once Player2 accepts game reset and a new alert message that sends to Player1 in the OKAction line.
func handleReceivedDataWithNotification(notification:NSNotification){
let userInfo = notification.userInfo! as Dictionary
let receivedData:NSData = userInfo["data"] as! NSData
let message = NSJSONSerialization.JSONObjectWithData(receivedData, options: NSJSONReadingOptions.AllowFragments, error: nil) as! NSDictionary
let senderPeerId:MCPeerID = userInfo["peerID"] as! MCPeerID
let senderDisplayName = senderPeerId.displayName
if message.objectForKey("string")?.isEqualToString("New Game") == true{
let alert = UIAlertController(title: "Game Restart Request", message: "\(senderDisplayName) has requested to restart the game", preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "No", style: .Cancel) { (acttion) in
}
alert.addAction(cancelAction)
let OKAction = UIAlertAction(title: "Yes", style: .Default) { (action) in
self.resetField()
let messageDicts = ["string":"RestartNow"]
}
alert.addAction(OKAction)
self.presentViewController(alert, animated: true) {
}
}else{
var field:Int? = message.objectForKey("field")?.integerValue
var player:String? = message.objectForKey("player") as? String
if field != nil && player != nil{
fields[field!].playerr = player
fields[field!].setPlayer(player!)
if player == "x"{
currentPlayer = "o"
}else{
currentPlayer = "x"
}
checkResults()
}
}
}
Here is where the alert is sent to when Player2 presses Accept/Yes:
#IBAction func newGame(sender: AnyObject, notification:NSNotification) {
let alertWait = UIAlertController(title: "Request Sent", message: "Waiting for other player to accept this request", preferredStyle: UIAlertControllerStyle.Alert)
self.presentViewController(alertWait, animated: true) {
}
let messageDict = ["string":"New Game"]
let messageData = NSJSONSerialization.dataWithJSONObject(messageDict, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
var error:NSError?
let userInfo = notification.userInfo! as Dictionary
let receivedData:NSData = userInfo["data"] as! NSData
let message = NSJSONSerialization.JSONObjectWithData(receivedData, options: NSJSONReadingOptions.AllowFragments, error: nil) as! NSDictionary
let senderPeerId:MCPeerID = userInfo["peerID"] as! MCPeerID
let senderDisplayName = senderPeerId.displayName
if message.objectForKey("string")?.isEqualToString("RestartNow") == true{
let alertOK = UIAlertController(title: "Game Is Restarting", message: "\(senderDisplayName) has accapted game request", preferredStyle: UIAlertControllerStyle.Alert)
let OkayAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
self.resetField()
})
self.presentViewController(alertOK, animated: true, completion: nil)
}
appDelegate.mpcHandler.session.sendData(messageData, toPeers: appDelegate.mpcHandler.session.connectedPeers, withMode: MCSessionSendDataMode.Reliable, error: &error)
if error != nil{
println("error: \(error?.localizedDescription)")
}
}

Resources