How to pass API image from Table View into another View Controller using didselectrowat - swift

I am a newbie in Swift and I am trying to build an app in which I retrieve plant images and information from this api "https://rapidapi.com/mnai01/api/house-plants2".
I managed to implement a table view in which I display the name and image of each plant in the api, and when I click on any cell in the table view I displayed that certain plant's information in a new view controller.
My problem is that no matter what I tried I couldn't also display the image of that plant in that view controller and I don't know what to do to make it work.
It is also worth to mention that the links for the images are of this format:
img: "http://www.tropicopia.com/house-plant/thumbnails/5556.jpg"
This is the class of the view controller where the image and information should be displayed:
import UIKit
import SDWebImage
class PlantDetailsViewController: UIViewController {
// image view for the plant
#IBOutlet weak var plantImage: UIImageView!
// labels for the plant information
#IBOutlet weak var commonNameLabel: UILabel!
#IBOutlet weak var latinNameLabel: UILabel!
#IBOutlet weak var otherNamesLabel: UILabel!
#IBOutlet weak var categoryLabel: UILabel!
#IBOutlet weak var useLabel: UILabel!
#IBOutlet weak var styleLabel: UILabel!
#IBOutlet weak var familyLabel: UILabel!
#IBOutlet weak var bloomSeasonLabel: UILabel!
#IBOutlet weak var wateringLabel: UILabel!
#IBOutlet weak var idealLightLabel: UILabel!
#IBOutlet weak var growthLabel: UILabel!
#IBOutlet weak var climatLabel: UILabel!
#IBOutlet weak var diseaseLabel: UILabel!
#IBOutlet weak var insectsLabel: UILabel!
#IBOutlet weak var leafColourLabel: UILabel!
#IBOutlet weak var bloomsColourLabel: UILabel!
#IBOutlet weak var availabilityLabel: UILabel!
#IBOutlet weak var bearingLabel: UILabel!
#IBOutlet weak var appealLabel: UILabel!
var plants: Plant?
var strCommonName = ""
var strLatinName = ""
var strOtherNames = ""
var strCategory = ""
var strUse = ""
var strStyle = ""
var strFamily = ""
var strBloomSeason = ""
var strWatering = ""
var strIdealLight = ""
var strGrowth = ""
var strClimat = ""
var strDisease = ""
var strInsects = ""
var strLeafColour = ""
var strBloomsColour = ""
var strAvailability = ""
var strBearing = ""
var strAppeal = ""
override func viewDidLoad() {
super.viewDidLoad()
commonNameLabel.text = strCommonName
latinNameLabel.text = strLatinName
otherNamesLabel.text = strOtherNames
categoryLabel.text = strCategory
useLabel.text = strUse
styleLabel.text = strStyle
familyLabel.text = strFamily
bloomSeasonLabel.text = strBloomSeason
wateringLabel.text = strWatering
idealLightLabel.text = strIdealLight
growthLabel.text = strGrowth
climatLabel.text = strClimat
diseaseLabel.text = strDisease
insectsLabel.text = strInsects
leafColourLabel.text = strLeafColour
bloomsColourLabel.text = strBloomsColour
availabilityLabel.text = strAvailability
bearingLabel.text = strBearing
appealLabel.text = strAppeal
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
This is is the didSelectRowAt function for the table view:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detail:PlantDetailsViewController = self.storyboard?.instantiateViewController(withIdentifier: "showDetails") as! PlantDetailsViewController
detail.strCommonName = plants[indexPath.row].common_name?.first ?? "N/A"
detail.strLatinName = plants[indexPath.row].latin_name ?? "N/A"
detail.strOtherNames = plants[indexPath.row].other_names ?? "N/A"
detail.strCategory = plants[indexPath.row].categories ?? "N/A"
detail.strUse = plants[indexPath.row].use?.first ?? "N/A"
detail.strStyle = plants[indexPath.row].style ?? "N/A"
detail.strFamily = plants[indexPath.row].family ?? "N/A"
detail.strBloomSeason = plants[indexPath.row].blooming_season ?? "N/A"
detail.strWatering = plants[indexPath.row].watering ?? "N/A"
detail.strIdealLight = plants[indexPath.row].light_ideal ?? "N/A"
detail.strGrowth = plants[indexPath.row].growth ?? "N/A"
detail.strClimat = plants[indexPath.row].climat ?? "N/A"
detail.strDisease = plants[indexPath.row].disease ?? "N/A"
detail.strInsects = plants[indexPath.row].insects?.first ?? "N/A"
detail.strLeafColour = plants[indexPath.row].color_of_leaf?.first ?? "N/A"
detail.strBloomsColour = plants[indexPath.row].color_of_blooms ?? "N/A"
detail.strAvailability = plants[indexPath.row].availability ?? "N/A"
detail.strBearing = plants[indexPath.row].bearing ?? "N/A"
detail.strAppeal = plants[indexPath.row].appeal ?? "N/A"
self.navigationController?.pushViewController(detail, animated: true)
}
In the Manager folder I created class called "APICaller" where I fetch the data from the API. This is the function that does that:
func getAllPlants (completion: #escaping (Result<[Plant], Error>) -> Void) {
guard let url = URL(string: "\(Constants.baseURL)/all/?rapidapi-key=\(Constants.API_KEY)") else {return}
let task = URLSession.shared.dataTask(with: URLRequest(url: url)) { data, _, error in
guard let data = data, error == nil else {return}
do {
let results = try JSONDecoder().decode([Plant].self, from: data)
completion(.success(results))
} catch {
completion(.failure(APIError.failedTogetData))
}
}
task.resume()
}
And finally this is the Plant struct model:
struct Plant: Codable {
let appeal: String?
let availability: String?
let bearing: String?
let blooming_season: String?
let categories: String?
let climat: String?
let color_of_blooms: String?
let color_of_leaf: [String]?
let common_name: [String]?
let disease: String?
let family: String?
let growth: String?
let insects: [String]?
let latin_name: String?
let light_ideal: String?
let other_names: String?
let style: String?
let use: [String]?
let watering: String?
let id: String?
let img: String?
let url: String?
private enum CodingKeys: String, CodingKey {
case appeal = "Appeal"
case availability = "Availability"
case bearing = "Bearing"
case blooming_season = "Blooming season"
case categories = "Categories"
case climat = "Climat"
case color_of_blooms = "Color of blooms"
case color_of_leaf = "Color of leaf"
case common_name = "Common name"
case disease = "Disease"
case family = "Family"
case growth = "Growth"
case insects = "Insects"
case latin_name = "Latin name"
case light_ideal = "Light ideal"
case other_names = "Other names"
case style = "Style"
case use = "Use"
case watering = "Watering"
case id = "id"
case img = "Img"
case url = "Url"
}
}
I think the problem is that each image is a string which contains a link, and to be able to display it in the table view cells I used SDWebImage. The question is how do I do that to display the image in the detail view controller? Thank you for your time. Any help or piece of advice is greatly appreciated :)
UPDATE- I tried to display it like this :
I wrote this in the viewdidload function in the detail view controller:
var selectedImage: String?
if let imageToLoad = selectedImage {
plantImage.image = UIImage(named: imageToLoad)
}
and then I added this line in the didselectrowat function:
detail.selectedImage = plants[indexPath.row].img
It still doesn't work and I don't know what I am doing wrong

Swift 5.5, Xcode 14.2
plantImage.image = UIImage(named: imageToLoad) is wrong, named is to local images, when you want get images from one API, like "http://www.tropicopia.com/house-plant/thumbnails/5556.jpg", you need use :
Github Example: https://github.com/MaatheusGois/answer-75361391
let url = URL(string: image.url)
func downloadImage(from url: URL) {
print("Download Started")
getData(from: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
// always update the UI from the main thread
DispatchQueue.main.async { [weak self] in
self?.plantImage.image = UIImage(data: data)
}
}
}
func getData(from url: URL, completion: #escaping (Data?, URLResponse?, Error?) -> Void) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
IMPORTANT (Common error)
https://developer.apple.com/forums/thread/119977

Related

Passing Data from Struct to ViewController

This is the data I have got by decrypting an encrypted String:
{"CustomerId":"ibex","AccessToken":"_!b3xGl0b#L","Cnic":"2323232323232","Mobile":"03200428778","Email":"abc#email.com","SimOwner":"SELF"}
Now. I have made a struct and added its objects.
> struct CustomerInfo: Codable {
> let CustomerId: String?
> let AccessToken: String?
> let Cnic: String?
> let Mobile: String?
> let Email: String?
> let SimOwner: String? }
when I try to access in my view Controller, it says nil data. I am trying to assign its value to a label. Here is my View Controller:
class ViewController: UIViewController {
#IBOutlet weak var CnicLabel: UILabel!
#IBOutlet weak var AccessTokenLabel: UILabel!
#IBOutlet weak var CustomerLbl: UILabel!
let Key = "UsmanAlmeezan123"
let iv = "Hello World12345"
let encryptionString: String = "xdLjc9sbYSE0Z/QEN8E7GbAdPUNLTBQ9eyAQZVmbvd/9WqxKjX1QfnpwuJZ9ITEhz9A1IHfhRp97HsH58U0qi8sYoBfyeEd4LGfD3WGDjk6kkBRFoxyhW8Fu8Ztj8QuxTcSScA0hUk0iYPDy4QhqCcPDXfdmmmZRyTdRF4dVDYS948CSIxMCicN7FMdShDR3"
private var EncryptDecrypt = EncryptionDecryption()
var Customer: CustomerInfo?
private var decrypt = String()
override func viewDidLoad() {
super.viewDidLoad()
decrypt = try! EncryptDecrypt.aesDecrypt(key: Key, iv: iv, decrptyData: encryptionString)
print(decrypt)
print(Customer?.Cnic)
CnicLabel.text = Customer?.Cnic
}
}
I should expect 2323232323232 in my label or value instead of nil
Anyone can help me If I am doing something wrong?

save entity array under another entity CoreDataRelationships

Im working on an app where a merchant can add a bunch of products into a persons tab.
After selecting the customer from a table view the user can see a list of products and the total amount which I'd like to save under that customers name for him to come pay later. I've done a lot of research about relationships in CoreData but have not found a way to save many items at once.
Here is a screenshot of the view controller showing the customer and the products to add to his tab.
Add to tab view controller
I've created the data models and all and everything works great just can't link the products to each customer. I want to be able to click on a customer and see all the products in his tab. I've spent weeks now trying to find an answer and its getting very frustrating. Just need to be able to save and retrieve the items and my app will be done.
Really looking forward to an answer!
import UIKit
import MapKit
import GoogleSignIn
import CoreData
class addToTabViewController: UIViewController {
// Data Arrays
var myCart = [Cart]()
var myCartUz: [Cart] = []
var selectedIndex: Int!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var amount: String = ""
var transaction: String = ""
#IBOutlet weak var profilePicture: UIImageView!
#IBOutlet weak var customerName: UILabel!
#IBOutlet weak var phoneNumber: UILabel!
#IBOutlet weak var emailAddress: UILabel!
#IBOutlet weak var customerAddress: UILabel!
#IBOutlet weak var profileView: UIView!
#IBOutlet weak var map: MKMapView!
#IBOutlet weak var receiptView: UIView!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var customerProfile: UIImageView!
#IBOutlet weak var customerProfileView: UIView!
#IBOutlet weak var totalAmount: UILabel!
#IBOutlet weak var merchantName: UILabel!
#IBOutlet weak var merchatEmail: UILabel!
// Variable
var customers: Cutomers!
override func viewDidLoad() {
super.viewDidLoad()
// Show data
configureEntryData(entry: customers)
fetchCartData()
totalAmount.text = amount
// Design parameters
hutzilopochtli()
}
// Info profile button
#IBAction func infoButton(_ sender: Any) {
profileView.isHidden = !profileView.isHidden
receiptView.isHidden = !receiptView.isHidden
customerProfileView.isHidden = !customerProfileView.isHidden
}
// Add to tab button
#IBAction func addToTabButton(_ sender: Any) {
}
// Show customer details
func configureEntryData(entry: Cutomers) {
let name = entry.name
let address = entry.address
let phone = entry.phoneNumber
let email = entry.email
customerName!.text = name
customerAddress!.text = address
phoneNumber!.text = phone
emailAddress!.text = email
self.title = name
let image = entry.profileicture as Data?
profilePicture!.image = UIImage(data: image!)
customerProfile!.image = UIImage(data: image!)
}
// Get cart data
func fetchCartData() {
do {
myCart = try context.fetch(Cart.fetchRequest())
myCartUz = myCart
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
}
merchantName?.text = GIDSignIn.sharedInstance().currentUser.profile.name
merchatEmail?.text = GIDSignIn.sharedInstance().currentUser.profile.email
}
// Design parameters function
func hutzilopochtli(){
profilePicture.roundMyCircle()
customerProfile.roundMyCircle()
profileView.layer.cornerRadius = 15
receiptView.layer.cornerRadius = 15
profileView.isHidden = true
map.layer.cornerRadius = 13
}
}
// Table view dataSource and delegates
extension addToTabViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myCartUz.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "discountCell", for: indexPath) as! discountTableViewCell
let price = myCartUz[indexPath.row].price
let xNSNumber = price as NSNumber
cell.productName?.text = myCartUz[indexPath.row].product
cell.amountLabel?.text = "IDR \(xNSNumber.stringValue)"
return cell
}
}
Here is the customer class
class constantCustomer: NSObject {
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
class func saveObject(customerId: String, name: String, phone: String, address: String, email: String, picture: NSData) -> Bool {
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "Cutomers", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(customerId, forKey: "customerID")
managedObject.setValue(NSDate(), forKey: "date")
managedObject.setValue(name, forKey: "name")
managedObject.setValue(phone, forKey: "phoneNumber")
managedObject.setValue(address, forKey: "address")
managedObject.setValue(email, forKey: "email")
managedObject.setValue(picture, forKey: "profileicture")
do {
try context.save()
return true
} catch {
return false
}
}
class func fetchObject() -> [Cutomers]? {
let context = getContext()
var myCustomers: [Cutomers]? = nil
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Cutomers")
let sort = NSSortDescriptor(key: "date", ascending: true)
fetchRequest.sortDescriptors = [sort]
do {
myCustomers = try context.fetch(Cutomers.fetchRequest())
return myCustomers
} catch {
return myCustomers
}
}
}
Without knowing about the Customers class I can only create an example. This is for the saving process:
func saveCustomer(entry: Customers) {
let entity = NSEntityDescription.entity(forEntityName: "EntityName", in: viewContext)
let customer = Customers(entity: entity!, insertInto: viewContext)
// add data to your customer class
customer.price = price
for journalEntry in entry.entry {
/// Your class with the Relationship
let persistent = CustomersDetail(context: viewContext)
persistent.question = journalEntry.question
persistent.answer = journalEntry.answer
customer.addToRelationship(persistent)
}
/// do saving
do {
try viewContext.save()
} catch let error {
print(error.localizedDescription)
}
}
loading Customer for a specific CostumerName:
func loadCustomerData(customerName: String) -> Customers {
let fetch:NSFetchRequest<Customers> = Customers.fetchRequest()
fetch.predicate = NSPredicate(format: "customerName = %#", "\(customerName)")
var customer = [Customers]()
do {
customer = try viewContext.fetch(fetch)
} catch let error {
print(error.localizedDescription)
}
return customer
}
enter image description here

How do I store a calculated result in UserDefaults to display in a "results" View controller [duplicate]

This question already has answers here:
How can I use UserDefaults in Swift?
(14 answers)
Closed 4 years ago.
First time poster so sorry for the incorrect format/length of the question.
I am building an app in Xcode that allows users to input various inputs among numerous view controllers and then have output in a single view controller with results displayed through labels.
The raw inputted textfield data is stored into UserDefaults and can display them later in the resulting VC with no problem. Im having trouble with calculated outputs (in this example "papiresult") however.
Can anyone provide guidance how to print out the calculated result several view controllers later using UserDefaults?
This is the rough layout
Here is the code I have in the first ViewController:
import UIKit
let userDefaults = UserDefaults()
var papiresult = Double()
class ViewController1: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
textField3.delegate = self
}
//Declaring data input into UserDefaults//
#IBAction func sendDataToVC2(_ sender: Any) {
let systPA = Double(textField1.text!)
let diastPA = Double(textField2.text!)
let cvPressure = Double(textField3.text!)
papiresult = ((systPA!-diastPA!)/cvPressure!)
userDefaults.set(textField1.text, forKey: "PASP")
userDefaults.set(textField2.text, forKey: "PADP")
userDefaults.set(textField3.text, forKey: "CVP")
userDefaults.set(papiresult, forKey: "PAPI")
}
}
Here is the code in the last (result) view controller:
import UIKit
class ViewController3: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
//Recalling data from UserDefaults//
override func viewWillAppear(_ animated: Bool) {
if let data1 = userDefaults.object(forKey: "PASP") {
if let message1 = data1 as? String {
self.label1.text = message1}
}
if let data2 = userDefaults.object(forKey: "PADP") {
if let message2 = data2 as? String {
self.label2.text = message2}
}
if let data3 = userDefaults.object(forKey: "CVP") {
if let message3 = data3 as? String {
self.label3.text = message3}
}
if let data4 = userDefaults.object(forKey: "Age") {
if let message4 = data4 as? String {
self.label4.text = message4}
}
if let data5 = userDefaults.object(forKey: "PAPI") {
if let message5 = data5 as? Double {
self.label5.text = "\(message5)"}
}
}
Basically, you should use UserDefaults.standard rather than creating a new instance of UserDefaults class. So I think this code
let userDefaults = UserDefaults()
should be replaced with this:
let userDefaults = UserDefaults.standard

How to grab the value of a WebView in Swift

Suppose I have a label that is a NSTextField. I know I can access the value of that label by:
#IBOutlet weak var label: NSTextField!
let labelValue = label.stringValue
And then I can use that variable accordingly.
The same is easily said for an NSImage:
#IBOutlet weak var productImageView: NSImageView!
let img = productImageView.image
My question is how do I grab the value of a WebView. I am unsure which property allows me to use a WebView.
#IBOutlet weak var videoTemp: WebView!
let videoPassed = videoTemp //how do I access this videoTemp's value much like .stringValue and .image
I am trying to load dynamic video URL's to Youtube videos when I click on a collection view item. The line that I have commented in my setupAppVideo method is where my fatal error occurs:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
but when I print out the url and request variables their are no nil values and all of them are the correct links in the console.
import Cocoa
import WebKit
class test1: NSCollectionViewItem {
#IBOutlet weak var label: NSTextField!
#IBOutlet weak var label2: NSTextField!
#IBOutlet weak var productImageView: NSImageView!
#IBOutlet weak var videoTemp: WKWebView!
var buildProduct: ProductModel? {
didSet{
label.stringValue = (buildProduct?.product_name)!
label2.stringValue = (buildProduct?.product_price)!
setupAppIconImage()
setupAppVideo()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func setupAppIconImage() {
if let appIconImageURL = buildProduct?.product_image {
let url = NSURL(string: appIconImageURL)
URLSession.shared.dataTask(with: url! as URL,completionHandler:{(data, response, error) in
if error != nil {
print(error)
return
}
DispatchQueue.main.async(){
self.productImageView.image = NSImage(data: data!)
}
}).resume()
}
}
func setupAppVideo(){
if let appVideoURL = buildProduct?.product_video{
let url = NSURL(string: appVideoURL)
print(url)
let request = NSURLRequest(url: url as! URL)
print(request)
//self.videoTemp.load(request as URLRequest)
}
}
}

Getting a nil error with UITextView

I am creating an app that will have several segments of it that will connect to parse, so I thought I would try to create a custom Class for the parse functions.
This address book tab is the first attempt.
I hit a snag with something that I thought would be so simple, but after 10 hours of research, I am turning here.
Here is the ViewController
var addressUUID = NSUUID().UUIDString
class AddViewController : UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var addressImage : UIImageView!
#IBOutlet weak var nameField : UITextField!
#IBOutlet weak var lastNameField : UITextField!
#IBOutlet weak var phoneField : UITextField!
#IBOutlet weak var emailField : UITextField!
#IBOutlet weak var addressCityField : UITextField!
#IBOutlet weak var addressCountryField : UITextField!
#IBOutlet weak var nameFieldLabel : UILabel!
#IBOutlet weak var lastNameFieldLabel : UILabel!
#IBOutlet weak var phoneFieldLabel : UILabel!
#IBOutlet weak var emailFieldLabel : UILabel!
#IBOutlet weak var addressCityFieldLabel : UILabel!
#IBOutlet weak var addressCountryFieldLabel : UILabel!
#IBOutlet weak var doneButton: UIButton!
#IBOutlet weak var scrollView: UIScrollView!
var scrollViewHeight : CGFloat = 0
var person : Person?
var parse : ParseData?
// creating frame for keyboard to force scroll view up
var keyboard = CGRect()
#IBAction func addButtonPressed(sender : UIButton) {
//NSLog("Button pressed")
print ("\(nameField.text)")
parse = ParseData.init(firstName: nameField.text!)
// Saves data to Parse class, regardless of if new or updated record
do {
try parse!.setFirstName(nameField.text!)
try parse!.setLastName(lastNameField.text!)
try parse!.setPhone(phoneField.text!)
try parse!.setEmail(emailField.text!)
try parse!.setAddressCity(addressCityField.text!)
try parse!.setAddressCountry(addressCountryField.text!)
try parse!.setAddressImage(addressImage.image!)
try parse!.setUUID(addressUUID)
} catch let error as PersonValidationError {
var errorMsg = ""
switch(error) {
case .InvalidFirstName:
errorMsg = "Invalid first name"
case .InvalidAddressCity:
errorMsg = "Invalid City"
case .InvalidEmail:
errorMsg = "Invalid email address"
case .InvalidPhone:
errorMsg = "Invalid phone number"
case .InvalidAddressImage:
errorMsg = "Invalid Image"
case .InvalidAddressCountry:
errorMsg = "Invalid Country"
}
let alert = UIAlertController(title: "Error", message: errorMsg, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Okay", style: .Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
} catch {
}
if person == nil
{
parse!.saveAddressToParse()
} else {
parse!.updateAddressToParse()
}
As noted, the error is the first line of "try"
The strange thing is the data sent to the Person class works fine.
Also, when I had the Parse functions on this VC, it worked (albeit with a modified code)
Here is the class ParseData
import Foundation
import Parse
enum ParseValidationError : ErrorType {
case InvalidFirstName
case InvalidAddressCity
case InvalidPhone
case InvalidEmail
case InvalidAddressCountry
case InvalidAddressImage
}
// class ParseData : PFObject, PFSubclassing
class ParseData : PFObject, PFSubclassing
{
private(set) var firstName : String?
private(set) var lastName : String?
private(set) var addressCity : String?
private(set) var addressCountry : String?
private(set) var phone : String?
private(set) var email : String?
private(set) var uuid : String?
private(set) var addressImageFile : UIImage?
var person : Person?
init?(firstName fn: String) {
super.init()
do {
try setFirstName(fn)
} catch {
return nil
}
}
static func parseClassName() -> String {
return "ParseData"
}
func saveAddressToParse () {
print ("saveToParse function begins")
let savedAddressObject = PFObject(className: "addressBook")
savedAddressObject["firstName"] = self.firstName!
savedAddressObject["lastName"] = self.lastName!
savedAddressObject["phone"] = self.phone!
savedAddressObject["email"] = self.email!
savedAddressObject["addressCity"] = self.addressCity!
savedAddressObject["addressCountry"] = self.addressCountry!
savedAddressObject["username"] = PFUser.currentUser()!.username
savedAddressObject["uuid"] = addressUUID
savedAddressObject["entryFrom"] = "Divelog New"
let addressBookImageData = UIImageJPEGRepresentation(self.addressImageFile!, 0.5)
let addressBookImageFile = PFFile(name: "addressBookImage.jpg", data: addressBookImageData!)
savedAddressObject ["addressBookImage"] = addressBookImageFile
savedAddressObject.pinInBackground()
savedAddressObject.saveEventually()
}
func updateAddressToParse () {
print ("updateToParse function begins")
let updateAddressQuery = PFQuery(className: "addressBook")
updateAddressQuery.whereKey("uuid", equalTo: person!.uuid!)
updateAddressQuery.getFirstObjectInBackgroundWithBlock {(objects: PFObject?, error: NSError?) -> Void in
if error == nil {
if let updateAddressObject = objects {
updateAddressObject.setValue(self.firstName!, forKey: "firstName")
updateAddressObject.setValue(self.lastName!, forKey: "lastName")
updateAddressObject.setValue(self.phone!, forKey: "phone")
updateAddressObject.setValue(self.email!, forKey: "email")
updateAddressObject.setValue(self.addressCity!, forKey: "addressCity")
updateAddressObject.setValue(self.addressCountry!, forKey: "addressCountry")
updateAddressObject.setValue("Divelog Update", forKey: "entryFrom")
let addressBookImageData = UIImageJPEGRepresentation(self.addressImageFile!, 0.5)
let addressBookImageFile = PFFile(name: "addressImage.jpg", data: addressBookImageData!)
updateAddressObject.setValue(addressBookImageFile!, forKey: "addressBookImage")
updateAddressObject.pinInBackground()
updateAddressObject.saveEventually()
}
}
}
}
func setFirstName(fn : String) throws {
firstName = fn
}
func setLastName(ln : String) throws {
lastName = ln
}
func setPhone (ph : String) throws {
phone = ph
}
func setEmail (em : String) throws {
email = em
}
func setAddressCity(adc : String) throws {
addressCity = adc
}
func setAddressCountry(ad : String) throws {
addressCountry = ad
}
func setAddressImage(ai : UIImage) throws {
addressImageFile = ai
}
func setUUID(ui : String) throws {
uuid = ui
}
}
Needed to add to the AppDelete:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
ParseData.registerSubclass()
Parse.enableLocalDatastore()
The above is the corrected answer and it works fine.
I cant see, where you create an instance of ParseData. I see, that you declare it with
var parse : ParseData?
and then in addButtonPressed you use it. But in between, where is the code that defines it? Something like:
parse = ParseData()