I am currently trying to use Eureka forms for my app. I need to display a user profile, and then update it using AlamoFire from my website. I want to be able to update profile information. Using Eureka forms is extremely difficult, since I am relatively new to Swift programming, but it proves to be the most intuitive platform right now for quick development..
When I log into my website I can see my user profile picture, its stored as a path in my MySQL database. My goal is to have my app do the same thing, view the picture and then change the picture with a picture from my phone and update the database. I can take care of the PHP, but the code is where I am stuck.
As I mentioned, Eureka is extremely complex and I cannot figure out how to directly use AlamoFire to retrieve my information, so I was able to save it to NSDefaults, including the URL, but cannot figure out how to get it to display. It keeps giving me a string error. Here is the code:
UserDataVC.swift
import UIKit
import Alamofire
import SwiftyJSON
import Eureka
import ImageRow
class UserDataVC: FormViewController {
let defaultValues = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
let parameters: Parameters=["id": UserDefaults.standard.string(forKey:
"id_user")! ]
let URL_USER_LOGIN = "https://www.mywebsite.com/userinfo.php"
_ = Alamofire.request(URL_USER_LOGIN, method: .get, parameters:
parameters).responseJSON
{response in
print("Result: \(response.result)") //
response serialization result
do {
let json = try JSONSerialization.jsonObject(with:
response.data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let resultValue = parseJSON["errorcode"] as? String
print("result: \(String(describing: resultValue))")
var isUserInfoOk:Bool = false;
if(resultValue=="none"){ isUserInfoOk = true;}
var messageToDisplay = parseJSON["message"] as! String!;
if(!isUserInfoOk)
{
messageToDisplay = parseJSON["message"] as! String!;
}
DispatchQueue.main.async {
if isUserInfoOk == true{
//Display alert message with confirmation
if let result = response.result.value {
let jsonData = result as! NSDictionary
//if there is no error
if(!(jsonData.value(forKey: "error") as!
Bool)){
//getting the user from response
let user = jsonData.value(forKey:
"user") as! NSDictionary
print(user)
//getting user values
let idUser = user.value(forKey:
"id_user") as? Int
let userFirstName = user.value(forKey:
"first_name") as? String
let userLastName = user.value(forKey:
"last_name") as? String
let userEmail = user.value(forKey:
"email") as? String
let userMobile = user.value(forKey:
"mobile_number") as? String
let userPicture = user.value(forKey:
"profile_image_url") as? URL
//saving user values to defaults
self.defaultValues.set(idUser, forKey:
"id_user")
self.defaultValues.set(userFirstName,
forKey: "first_name")
self.defaultValues.set(userLastName,
forKey: "last_name")
self.defaultValues.set(userEmail,
forKey: "email")
self.defaultValues.set(userMobile,
forKey: "mobile_number")
self.defaultValues.set(userPicture,
forKey: "profile_image_url")
UserDefaults.standard.synchronize()
}
}
} else {
print("Error with user data")
// let myAlert =
UIAlertController(title:"Error", message:messageToDisplay, preferredStyle:
UIAlertControllerStyle.alert);
// let okAction = UIAlertAction(title:"Ok",
style:UIAlertActionStyle.default) { action in
// self.dismiss(animated: false,
completion:nil);
// }
// myAlert.addAction(okAction);
// self.present(myAlert, animated:false,
completion:nil);
}
};
}
} catch let error {
print("error occured \(error)")
}
}
form +++ Section("Your Profile")
<<< UserInfoRow { row in
row.value = User()
row.reload()
}
form +++ Section("Edit Profile")
<<< ImageRow() {
$0.title = "Profile picture"
$0.sourceTypes = [.PhotoLibrary, .SavedPhotosAlbum, .Camera]
$0.clearAction = .no
}
.cellUpdate { cell, row in
cell.accessoryView?.layer.cornerRadius = 17
cell.accessoryView?.frame = CGRect(x: 0, y: 0, width: 34,
height: 34)
}
form +++ Section()
<<< NameRow(){ row in
row.title = "First name"
row.placeholder = "Enter your First Name"
}
<<< NameRow(){ row in
row.title = "Last name"
row.placeholder = "Enter your last name"
}
<<< PhoneRow(){
$0.title = "Mobile Number"
$0.placeholder = "Enter your mobile number"
}
<<< EmailRow(){ row in
row.title = "Email"
row.placeholder = "Enter your email address"
}
<<< PasswordRow(){ row in
row.title = "Password"
row.placeholder = "Change your password"
}
form +++ Section()
<<< ButtonRow() {row in
row.title = "UPDATE PROFILE"
}
// let row: UserInfoRow? = form.rowBy(tag: "Your Profile")
let valuesDictionary = form.values()
}
}
and here is the next file
UserInfoCell.swift
import Foundation
import Alamofire
import AlamofireImage
import SwiftyJSON
import Eureka
final class UserInfoRow: Row<UserInfoCell>, RowType {
required init(tag: String?) {
super.init(tag: tag)
cellProvider = CellProvider<UserInfoCell>(nibName: "UserInfoCell")
}
}
final class UserInfoCell: Cell<User>, CellType {
@IBOutlet weak var userImageView: UIImageView!
@IBOutlet weak var firstnameLabel: UILabel!
@IBOutlet weak var lastnameLabel: UILabel!
@IBOutlet weak var emailLabel: UILabel!
@IBOutlet weak var mobileLabel: UILabel!
required init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func setup() {
super.setup()
UserDefaults.standard.synchronize()
// we do not want our cell to be selected in this case. If you use such
a cell in a list then you might want to change this.
selectionStyle = .none
// configure our profile picture imageView
userImageView.contentMode = .scaleAspectFill
userImageView.clipsToBounds = true
// define fonts for our labels
firstnameLabel.font = .systemFont(ofSize: 18)
lastnameLabel.font = .systemFont(ofSize: 18)
emailLabel.font = .systemFont(ofSize: 13.3)
mobileLabel.font = .systemFont(ofSize: 13.3)
// set the textColor for our labels
for label in [mobileLabel, emailLabel, lastnameLabel, firstnameLabel] {
label?.textColor = .gray
}
// specify the desired height for our cell
height = { return 106 }
// set a light background color for our cell
backgroundColor = UIColor(red:0.984, green:0.988, blue:0.976,
alpha:1.00)
}
override func update() {
super.update()
// we do not want to show the default UITableViewCell's textLabel
textLabel?.text = nil
// get the value from our row
guard let user = row.value else { return }
// set the image to the userImageView. You might want to do this with
AlamofireImage or another similar framework in a real project
if let url = user.pictureUrl, let data = try? Data(contentsOf: url) {
userImageView.image = UIImage(data: data)
} else {
userImageView.image = UIImage(named: "MainImage")
}
// set the texts to the labels
firstnameLabel.text = user.firstname
lastnameLabel.text = user.lastname
emailLabel.text = user.email
mobileLabel.text = user.mobile
}
}
let defaultValues = UserDefaults.standard
// Alamofire Code to updating struct
struct User: Equatable {
var firstname = UserDefaults.standard.string(forKey: "first_name")
//var firstname: String
var lastname = UserDefaults.standard.string(forKey: "last_name")
var email = UserDefaults.standard.string(forKey: "email")
var mobile = UserDefaults.standard.string(forKey: "mobile_number")
// var pictureUrl = UserDefaults.standard.string(forKey:
"profile_image_url")
var pictureUrl: URL?
}
func ==(lhs: User, rhs: User) -> Bool {
return lhs.email == rhs.email
}