Cannot set value of Textfield as Firebase search result - Swift - swift

I have a search function in my app to search my firebase db based on a pub name entered. This is working correctly & returning the correct record in my console. However I'm trying to display the relating info to that search query as values on my textfields.
var drinkReference: DatabaseReference!
let databaseRef = Database.database().reference()
#IBOutlet weak var pintImage: UIImageView!
#IBOutlet weak var pubName: UITextField!
#IBOutlet weak var pubLocation: UITextField!
#IBOutlet weak var price: UITextField!
#IBOutlet weak var rating: UITextField!
#IBOutlet weak var comment: UITextField!
#IBOutlet weak var searchText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(AddDrinkVC .dismissKeyboard))
view.addGestureRecognizer(tap)
drinkReference = Database.database().reference().child("Drinks");
NotificationCenter.default.addObserver(self, selector: #selector(SearchVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SearchVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#IBAction func searchIsClicked(_ sender: Any) {
searchT()
}
#IBAction func homeClicked(_ sender: Any) {
homeClicked()
}
func searchT() {
// You must cast pub variable as String.
guard let pub: String = searchText.text else { return }
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "pub").queryStarting(atValue: pub).queryEnding(atValue: "\(String(describing: pub))\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else {
let alert = UIAlertController(title: "", message: "This pub hasn't been visited yet. We'll get there.", preferredStyle: UIAlertControllerStyle.alert)
let search = UIAlertAction(title: "Want to add the drink yourself?", style: .default) { [weak self] _ in
self?.uploadClicked()
}
alert.addAction(search)
alert.addAction(UIAlertAction(title: "Close & Search again", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
return }
print(snapshot.value as Any)
DispatchQueue.main.async {
guard let dict = snapshot.value as? [String:Any] else {
print(snapshot)
return
}
let returnedPubName = dict["pub"] as? String
let returnedPubLocation = dict["location"] as? String
let returnedPintPrice = dict["price"] as? String
let returnedPintRating = dict["rating"] as? String
let returnedComment = dict["comment"] as? String
self.pubName.text?.append(returnedPubName!)
self.pubLocation.text?.append(returnedPubLocation!)
self.price.text?.append(returnedPintPrice!)
self.rating.text?.append(returnedPintRating!)
self.comment.text?.append(returnedComment!)
}
}
}
When I try to assign the value of 'pubName' to the textfield of the same name it's receiving nil. Is this due to my 'guard let dict....' code?
Does anyone know how & where I'm going wrong here?
Thanks, E

Create a struct like this:-
struct Names {
var pub: String = ""
var location: String = ""
var price: String = ""
var rating: String = ""
var comment: String = ""
init(data: [String:Any]) {
if let obj = data["pub"] as? String {
self.pub = obj
}
if let obj = data["location"] as? String {
self.location = obj
}
if let obj = data["price"] as? String {
self.price = obj
}
if let obj = data["rating"] as? String {
self.rating = obj
}
if let obj = data["comment"] as? String {
self.comment = obj
}
}
}
And in your controller class create a variable
var names: [Names] = [Names]()
Then in your searchT method do this
guard let dict = snapshot.value as? [String:Any] else {
return
}
self.names.append(Names(data: dict))
print(self.names)
And then use
self.pubName.text = names.first?.pub
And if it not works just try after
DispatchQueue.main.async {
guard let dict = snapshot.value as? [String:Any] else {
return
}
self.names.append(Names(data: dict))
print(self.names)
}
self.pubName.text = names.first?.pub

So through trial and error & with the help of a few folk this is the working code, as a note I'm not sure if this is the most efficient way or anything, but it works so c'est la vie.
func searchT() {
// You must cast pub variable as String.
guard let pub: String = searchText.text else { return }
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "pub").queryStarting(atValue: pub).queryEnding(atValue: "\(String(describing: pub))\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else {
let alert = UIAlertController(title: "", message: "This pub hasn't been visited yet. We'll get there.", preferredStyle: UIAlertControllerStyle.alert)
let search = UIAlertAction(title: "Want to add the drink yourself?", style: .default) { [weak self] _ in
self?.uploadClicked()
}
alert.addAction(search)
alert.addAction(UIAlertAction(title: "Close & Search again", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
return }
print(snapshot.value as Any)
DispatchQueue.main.async {
// DATA WAS FOUND
for user_child in (snapshot.children) {
let user_snap = user_child as! DataSnapshot
let dict = user_snap.value as! [String: String?]
// DEFINE VARIABLES FOR LABELS
let returnedPubName = dict["pub"] as? String
let returnedPubLocation = dict["location"] as? String
let returnedPintPrice = dict["price"] as? String
let returnedPintRating = dict["rating"] as? String
let returnedComment = dict["comment"] as? String
self.pubName.text?.append(returnedPubName!)
self.pubLocation.text?.append(returnedPubLocation!)
self.price.text?.append(returnedPintPrice!)
self.rating.text?.append(returnedPintRating!)
self.comment.text?.append(returnedComment!)
}
}
}
}
Pay particular attention to the code following the comment //DATA WAS FOUND, that's accessing the values of the children data records.

Related

Use of unresolved identifier 'self' (CoreData)

I am using this line below :
self.present(activityViewController, animated: true, completion: nil)
And I am getting an error of - Use of unresolved identifier 'self'. Any ideas about how to resolve this? To me it looks as it it is subordinate to the class, but clearly doing something wrong. Any help would be appreciated.
import UIKit
import CoreData
class CoreDataViewController: UIViewController {
#IBOutlet weak var CoreDataView: UITableView!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var items:[Checkins]?
var btnnames = [""]
override func viewDidLoad() {
super.viewDidLoad()
// CoreDataView.dataSource = self
// CoreDataView.delegate = self
storeTranscription()
// Loads the current data
getTranscriptions()
// fetchCheckins()
let btn1name = btnnames[0]
let btn2name = btnnames[1]
let btn3name = btnnames[2]
let btn4name = btnnames[3]
let btn5name = btnnames[4]
let btn6name = btnnames[5]
// print(btnnames)
print(btn1name, btn2name, btn3name, btn4name, btn5name, btn6name)
}
#IBAction func export(_ sender: Any) {
exportDatabase()
}
#IBOutlet weak var Table_label: UILabel!
}
var CheckinDate: Date? = Date()
var fetchedStatsArray: [NSManagedObject] = []
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func storeTranscription() {
//retrieve the entity that we just created
let entity = NSEntityDescription.entity(forEntityName: "Checkins", in: context)
let transc = NSManagedObject(entity: entity!, insertInto: context) as! Checkins
//set the entity values
transc.who = "Who"
transc.reason = "Reason for visit"
transc.date = CheckinDate
//save the object
do {
try context.save()
print("saved!")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
func getTranscriptions () {
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<Checkins> = Checkins.fetchRequest()
do {
//go get the results
let searchResults = try context.fetch(fetchRequest)
fetchedStatsArray = searchResults as [NSManagedObject]
//I like to check the size of the returned results!
print ("num of results = \(searchResults.count)")
//You need to convert to NSManagedObject to use 'for' loops
for trans in searchResults as [NSManagedObject] {
//get the Key Value pairs (although there may be a better way to do that...
print("\(trans.value(forKey: "who")!)")
let mdate = trans.value(forKey: "CheckinDate") as! Date
print(mdate)
}
} catch {
print("Error with request: \(error)")
}
}
func exportDatabase() {
let exportString = createExportString()
saveAndExport(exportString: exportString)
}
func saveAndExport(exportString: String) {
let exportFilePath = NSTemporaryDirectory() + "Checkins.csv"
let exportFileURL = NSURL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
//var fileHandleError: NSError? = nil
var fileHandle: FileHandle? = nil
do {
fileHandle = try FileHandle(forWritingTo: exportFileURL as URL)
} catch {
print("Error with fileHandle")
}
if fileHandle != nil {
fileHandle!.seekToEndOfFile()
let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
fileHandle!.write(csvData!)
fileHandle!.closeFile()
let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo
]
self.present(activityViewController, animated: true, completion: nil)
}
}
func createExportString() -> String {
var checkinwho: String?
var checkinreason: String?
var export: String = NSLocalizedString("who, reason, date \n", comment: "")
for (index, itemList) in fetchedStatsArray.enumerated() {
if index <= fetchedStatsArray.count - 1 {
checkinwho = Checkins.value(forKey: "who") as! String?
checkinreason = itemList.value(forKey: "reason") as! String?
let Datevar = Checkins.value(forKey: "date") as! Date
let whostring = checkinwho
let reasonstring = checkinreason
let DateSting = "\(Datevar)"
export += "\(whostring!),\(reasonstring!),\(DateSting) \n"
}
}
print("This is what the app will export: \(export)")
return export
}
Remove the } on this line
#IBOutlet weak var Table_label: UILabel!
}
and put another } at the end of this file.

binary data not fetching in UIImageView when called

My swift code below is using a textfield to enter a number. When the app builds 2 images are saved to core data binary data image. There is a index connected to it to control the order of the way the images are saved. When the user enters 1 in the textfield the 1st image should appear when 2 is entered. A gif is below of want I want to achieve.
import UIKit
import CoreData
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet var labelName : UILabel!
#IBOutlet var enterT : UITextField!
#IBOutlet var pic : UIImageView!
lazy var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var dx = [UIImage]()
var names = [String]()
override func viewDidLoad() {
super.viewDidLoad()
enterT.delegate = self
pic.backgroundColor = .cyan
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Users", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
let item2 = NSManagedObject(entity: entity, insertInto: managedContext)
let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
let vex = UIImage(named: "on.jpg")?.pngData()
if let data = vex{
item.setValue(data, forKey: "image")
}
let vex2 = UIImage(named: "house.jpg")?.pngData()
if let data2 = vex2{
item2.setValue(data2, forKey: "image")
}
do {
let result = try? managedContext.fetch(fetch) as? [Users]
print("Queen",result?.count)
try? managedContext.save()
}
catch {
print("Could not save")
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = (textField.text as? NSString)?.replacingCharacters(in: range, with: string), let index = Int(text) else { //here....
// display an alert about invalid text
return true
}
save(at: index )
return true
}
func save(at index : Int) {
let fetchRequest = NSFetchRequest<Users>(entityName: "Users")
fetchRequest.predicate = NSPredicate(format: "idx == %d", Int32(index))
do {
if let user = try context.fetch(fetchRequest).first {
pic.image = UIImage(data: user.image ?? Data())
}
} catch {
print("Could not fetch \(error) ")
}
return
}
#IBAction func add(){
fetch()
}
func fetch()
{
for i in 0..<dx.count {
let newUser = Users(context: context)
newUser.image = dx[i].jpegData(compressionQuality: 1)
newUser.idx = Int32(i + 1)
}
print("Storing Data..")
do {
try context.save()
} catch {
print("Storing data Failed", error)
}
return
}
}
You are mixing up fetching and saving
When you add items to the database create objects and save the context. Don't fetch.
When you load items from the database fetch the records. Don't save.
I don't know if shouldChangeCharactersIn works as expected. The other code is supposed to work.
And once again, on every application launch the (same) two items are added to the data base again.
Be aware of that. If the items exist delete or comment out the line populateData() in viewDidLoad.
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet var labelName : UILabel!
#IBOutlet var enterT : UITextField!
#IBOutlet var pic : UIImageView!
lazy var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
enterT.delegate = self
pic.backgroundColor = .cyan
populateData()
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = (textField.text as? NSString)?.replacingCharacters(in: range, with: string), let index = Int(text) else { //here....
// display an alert about invalid text
return true
}
loadImage(at: index )
return true
}
func loadImage(at index : Int) {
let fetchRequest = NSFetchRequest<Users>(entityName: "Users")
fetchRequest.predicate = NSPredicate(format: "idx == %d", Int32(index))
do {
if let user = try context.fetch(fetchRequest).first {
pic.image = UIImage(data: user.image!)
} else {
pic.image = nil
}
} catch {
print("Could not fetch \(error) ")
}
}
#IBAction func add(){
// fetch()
}
func populateData()
{
let item = Users(context: context)
let vex = UIImage(named: "on.jpg")!.pngData()
item.image = vex
item.idx = 1
let item2 = Users(context: context)
let vex2 = UIImage(named: "house.jpg")!.pngData()
item2.image = vex2
item2.idx = 2
print("Storing Data..")
do {
try context.save()
} catch {
print("Storing data Failed", error)
}
}
}

swift4 creating users info name, age and getting data back from fire base

I have created firebase all good with sign in and signup I can
store images as well but can't get images back that are stored in firebase and I want to create user profile to store name and age of user,
success with login, storing image with firebase and have created real time data base child such as image user name and age but cant use in my app, issue in creating user profile and issue with getting image back from firebase storage.
import UIKit
import FirebaseAuth
import Firebase
import FirebaseStorage
class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var ref : DatabaseReference?
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var myImage: UIImageView!
#IBOutlet weak var userName: UITextField!
#IBOutlet weak var ageTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// get image from firebase
// imagesFolder.
// let imageBack = Database.database().reference().child("images").child("user")
// self.myImage.image = UIImage(data: data!)
// creating dataBase
ref = Database.database().reference()
if Auth.auth().currentUser != nil {
ref?.child("images").child("username").setValue(["name":"first", "age":28])
}
}
#IBAction func loginButtonPressed(_ sender: UIButton) {
}
// signUp Button pressed
#IBAction func signUpButtonPressed(_ sender: UIButton) {
Auth.auth() .createUser(withEmail: emailTextField!.text!, password: passwordTextField!.text!) {(user,error)
in
if user != nil
{
self.performSegue(withIdentifier: "goToHome", sender: self)
print("SignUp Sucessfull")
}
else {
print("unSucessfull")
// uiAlert
let alert = UIAlertController(title:"wrong Information", message: nil, preferredStyle: .alert)
let okButton = UIAlertAction(title: "ok", style: .default, handler: nil)
alert.addAction(okButton)
self.present(alert,animated: true,completion: nil)
print("login Failed")
}
guard let userName = self.userName.text,!userName.isEmpty else {
print("Email is Empty");return
}
guard let userAge = self.ageTextField.text,!userAge.isEmpty else {
print("Age is required"); return
}
}
// upload image data to firebase
let imagesFolder = Storage.storage().reference().child("images")
if let image = myImage.image {
if let imageData = image.jpegData(compressionQuality: 0.75) {
imagesFolder.child("\(NSUUID().uuidString).jpg").putData(imageData, metadata: nil,completion: { (metadata,error) in
if let error = error {
// alert notification
}
// putData(_:metadata:completion:)
})
}
}
I have crazy comment please ignore that !
I have found the answer myself for future coders this can be a reference !
// user info stored
let userID = Auth.auth().currentUser?.uid
let userData = ["userName": userName,
"userAge ": userAge] as [String? : Any]
let ref = Database.database().reference()
ref.child("users/\(userID ?? "")").setValue(userData)
}
now to retrieve data create a struct and put the code in view did load
func fetchCurrentUserData() {
guard let currentUid = Auth.auth().currentUser?.uid else { return }
let userRef = Database.database().reference().child("users").child(currentUid)
print("userRef: \(userRef)")
userRef.observeSingleEvent(of: .value) { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String, AnyObject> else { return }
let uid = snapshot.key
let user = User(uid: uid, dictionary: dictionary)
self.user = user
print(snapshot.key)
}
}

firebase upload after checkout

This is shopping app after user select the products send to cart then checkout after fill the fields and press Checkout (Pay) send the details of the products to my firebase database please any one can help me I use json as my load products on tableview cell
I know I don't have payment serves but on this fields of payment information will be name , phone number, and location
[{
"name": "EGG",
"price": "3.00",
"image": "http://partiklezoo.com/Egg/u0001.jpg",
"description": "one Egg",
"category": "Food",
"uid": "u0001"
},]
Code
import UIKit
class CheckoutViewController: DetailViewController, UITableViewDataSource, UITableViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet var cardNumber: UITextField!
#IBOutlet var cardExpiryMonth: UITextField!
#IBOutlet var cardExpiryYear: UITextField!
#IBOutlet var cardCvv: UITextField!
#IBOutlet var pickerPickupPoint: UIPickerView!
#IBOutlet var tableViewOrderDetails: UITableView!
#IBOutlet var labelTotalPrice: UILabel!
var model = SingletonManager.model
override func viewDidLoad() {
super.viewDidLoad()
self.configureCheckout()
self.tableViewOrderDetails.dataSource = self
self.tableViewOrderDetails.delegate = self
self.pickerPickupPoint.dataSource = self
self.pickerPickupPoint.delegate = self
//Looks for single or multiple taps.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(CheckoutViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
self.view.endEditing(true)
}
func configureCheckout() {
pickerPickupPoint.selectedRow(inComponent: 0)
labelTotalPrice.text = "$" + String(format: "%.2f", model.calculateCartTotal())
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model.cart.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = model.products[Int(model.cart[indexPath.row][0])].name
cell.detailTextLabel?.text = String(Int(model.cart[indexPath.row][1])) + " x $" + String(format: "%.2f", model.cart[indexPath.row][4])
return cell
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return model.pickUpLocations.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return model.pickUpLocations[row]["street"]! + ", " + model.pickUpLocations[row]["suburb"]!
}
#IBAction func payNow(_ sender: Any) {
var error = ""
if self.model.cart.count == 0 {
error = "Your cart is empty."
}
else if (self.cardNumber.text?.isEmpty)! {
error = "Please enter your card number."
}
else if (self.cardExpiryMonth.text?.isEmpty)! {
error = "Please enter the expiry month of your card."
}
else if (self.cardExpiryYear.text?.isEmpty)! {
error = "Please enter the expiry year of your card."
}
else if (self.cardCvv.text?.isEmpty)!{
error = "Please enter the CVV number of your card."
}
if error.isEmpty {
showAlertMsg("Confirm Purchase", message: "Pay " + labelTotalPrice.text!, style: UIAlertControllerStyle.actionSheet)
}
else {
showAlertMsg("Error", message: error, style: UIAlertControllerStyle.alert)
}
}
var alertController: UIAlertController?
func showAlertMsg(_ title: String, message: String, style: UIAlertControllerStyle) {
self.alertController = UIAlertController(title: title, message: message, preferredStyle: style)
if style == UIAlertControllerStyle.actionSheet {
alertController?.addAction(UIAlertAction(title: "Pay", style: .default, handler: { _ in
self.checkout()
}))
alertController?.addAction(UIAlertAction(title: "Cancel", style: .cancel))
} else {
alertController?.addAction(UIAlertAction(title: "Okay", style: .default))
}
self.present(self.alertController!, animated: true, completion: nil)
}
func checkout() {
var success = true
for count in 0...self.model.cart.count - 1 {
let product = self.model.products[Int(self.model.cart[count][0])]
let quantity = Int(self.model.cart[count][1])
let total = self.model.cart[count][4]
let material = self.model.cart[count][3] == 0.0 ? "pla" : "abs"
let painting = self.model.cart[count][2] == 0.0 ? "false" : "true"
let temp = self.model.purchase(product: product, quantity: quantity, total: total, material: material, painting: painting)
if !temp {
success = false
}
}
if !success {
let error = "Oops! Something went wrong. Please try again later."
showAlertMsg("Error", message: error, style: UIAlertControllerStyle.alert)
} else {
print("Success! Checkout complete.")
self.cardNumber.text = ""
self.cardExpiryMonth.text = ""
self.cardExpiryYear.text = ""
self.cardCvv.text = ""
self.labelTotalPrice.text = "$0.00"
self.model.clearCart()
self.tableViewOrderDetails.reloadData()
self.performSegue(withIdentifier: "Thankyou", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let confirmationVc = (segue.destination as! UINavigationController).topViewController as! ConfirmationViewController
confirmationVc.location = self.model.pickUpLocations[self.pickerPickupPoint.selectedRow(inComponent: 0)]
}
}
this is my objective
Class Model: NSObject, CLLocationManagerDelegate {
var segueArray = [String]()
var seguesDictionary = Dictionary<String, UIImage>()
var products = [Product]()
var storedProducts = [NSManagedObject]()
var cart = [[Double]]()
var storedCart = [NSManagedObject]()
var pickUpLocations = [[String: String]]()
let locationManager = CLLocationManager()
override init() {
super.init()
segueArray.append("Home")
segueArray.append("List")
segueArray.append("Search")
segueArray.append("Cart")
segueArray.append("Finder")
segueArray.append("Checkout")
seguesDictionary["Home"] = UIImage(named: "home")
seguesDictionary["List"] = UIImage(named: "list")
seguesDictionary["Search"] = UIImage(named: "search")
seguesDictionary["Cart"] = UIImage(named: "cart")
seguesDictionary["Finder"] = UIImage(named: "finder")
seguesDictionary["Checkout"] = UIImage(named: "checkout")
self.loadProducts()
self.refreshProducts()
self.loadCart()
self.configureLocManager()
}
func loadProducts() {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Products")
do {
let results = try managedContext.fetch(fetchRequest)
storedProducts = results as! [NSManagedObject]
if storedProducts.count > 0 {
for index in 0...storedProducts.count - 1 {
let binaryData = storedProducts[index].value(forKey: "image") as! Data
let image = UIImage(data: binaryData)
let name = storedProducts[index].value(forKey: "name") as! String
let price = storedProducts[index].value(forKey: "price") as! Double
let details = storedProducts[index].value(forKey: "details") as! String
let category = storedProducts[index].value(forKey: "category") as! String
let uid = storedProducts[index].value(forKey: "uid") as! String
let loadedProduct = Product(name: name, price: price, image: image!, details: details, category: category, uid: uid)
products.append(loadedProduct)
}
}
}
catch let error as NSError
{
print("Could not load. \(error), \(error.userInfo)")
}
}
func refreshProducts() {
let url = NSURL(string: "http://partiklezoo.com/3dprinting/")
let config = URLSessionConfiguration.default
config.isDiscretionary = true
let session = URLSession(configuration: config)
let task = session.dataTask(with: url! as URL, completionHandler:
{(data, response, error) in
let json = JSON(data: data!)
for count in 0...json.count - 1
{
let newProduct = Product()
newProduct.name = json[count]["name"].string
newProduct.price = Double(json[count]["price"].string!)
newProduct.details = json[count]["description"].string
newProduct.category = json[count]["category"].string
newProduct.uid = json[count]["uid"].string
let imgURL = json[count]["image"].string!
self.addItemToList(newProduct, imageURL: imgURL)
}
})
task.resume()
}
func checkForProduct(_ searchItem: Product) -> Int {
var targetIndex = -1
if products.count > 0 {
for index in 0...products.count - 1 {
if products[index].uid == searchItem.uid {
targetIndex = index
}
}
}
return targetIndex
}
func addItemToList(_ newProduct: Product!, imageURL: String) {
if checkForProduct(newProduct) == -1 {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let picture = UIImageJPEGRepresentation(loadImage(imageURL), 1)
let entity = NSEntityDescription.entity(forEntityName: "Products", in: managedContext)
let productToAdd = NSManagedObject(entity: entity!, insertInto: managedContext)
productToAdd.setValue(newProduct.category, forKey: "category")
productToAdd.setValue(newProduct.details, forKey: "details")
productToAdd.setValue(picture, forKey: "image")
productToAdd.setValue(newProduct.name, forKey: "name")
productToAdd.setValue(newProduct.price, forKey: "price")
productToAdd.setValue(newProduct.uid, forKey: "uid")
do
{
try managedContext.save()
}
catch let error as NSError
{
print("Could not save. \(error), \(error.userInfo)")
}
storedProducts.append(productToAdd)
newProduct.image = UIImage(data: picture!)
products.append(newProduct)
}
}
func loadCart() {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Cart")
do {
let results = try managedContext.fetch(fetchRequest)
storedCart = results as! [NSManagedObject]
if storedCart.count > 0 {
for index in 0...storedCart.count - 1 {
let product = storedCart[index].value(forKey: "product") as! Double
let quantity = storedCart[index].value(forKey: "quantity") as! Double
let finish = storedCart[index].value(forKey: "finish") as! Double
let material = storedCart[index].value(forKey: "material") as! Double
let totalPrice = storedCart[index].value(forKey: "total") as! Double
let temp = [product, quantity, finish, material, totalPrice]
cart.append(temp)
}
}
}
catch let error as NSError
{
print("Could not load. \(error), \(error.userInfo)")
}
}
func addToCart(product: Product, quantity: Double, finish: Double, material: Double, totalPrice: Double) {
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Cart", in: managedContext)
let productToAdd = NSManagedObject(entity: entity!, insertInto: managedContext)
productToAdd.setValue(checkForProduct(product), forKey: "product")
productToAdd.setValue(quantity, forKey: "quantity")
productToAdd.setValue(finish, forKey: "finish")
productToAdd.setValue(material, forKey: "material")
productToAdd.setValue(totalPrice, forKey: "total")
do
{
try managedContext.save()
}
catch let error as NSError
{
print("Could not save. \(error), \(error.userInfo)")
}
let temp = [Double(checkForProduct(product)), quantity, finish, material, totalPrice]
storedCart.append(productToAdd)
cart.append(temp)
}
I am not sure I understand the question but from the comments I believe the OP is asking for example code to put into an action button to write date to Firebase. So here it is.
(note: please see comments as the OP didn't clarify what he was after so it's not clear if this is an answer or not)
Start with initialzing Firebase in your view controller
class ViewController: UIViewController {
var ref: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
self.ref = Database.database().reference()
then lets have a button press write two cars to firebase in a 'car_list' node
#IBAction func button0Action(_ sender: Any) {
let itemDict0 = [
"Name": "Car",
"price": "2000"]
let itemDict1 = [
"Name": "Car",
"price": "3000"]
let carRef = self.ref.child("car_list")
carRef.childByAutoId().setValue(itemDict0)
carRef.childByAutoId().setValue(itemDict1)
}
and the result in Firebase looks like this
car_list
-LKYuRKpLL_JXsDGsYWY
Name: "Car"
Price: "2000"
-LKYuRKpLL_JXsDGsYWZ
Name: "Car"
Price: "3000"
EDIT: I had intially set this up like a grocery list per the data in the question but per a comment from the OP they want to make it cars and prices, so that's how it is now.

How do I save and show a Image with core data - swift 3

I am doing a project in Swift 3 - xcode 8, and I am trying to use core data to save and show some images in a data base table "users".
This image is the user photo in his profile.
Now I've managed to save strings and showing them from core data but I am having problems in working this out with images.
This is what I have so far:
Adding USERS into core data
func addUser() {
let app = UIApplication.shared.delegate as! AppDelegate
let context = app.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false
let newUser = NSEntityDescription.insertNewObject(forEntityName: "Users", into: context)
if (firstName.text == "" && lastName.text == "" && contact.text == "" && email.text == "") { //if we have a user profile delete it
deleteUser()
} else { // add a new user profile
newUser.setValue(firstName.text, forKey: "firstName")
newUser.setValue(lastName.text, forKey: "lastName")
newUser.setValue(contact.text, forKey: "contact")
newUser.setValue(email.text, forKey: "email")
//newUser.setValue(imageView.image, forKey: "photo")
//let imgUrl = UIImagePickerControllerReferenceURL as! NSURL
let img = UIImage(named: "f.png")
let imgData = UIImageJPEGRepresentation(img!, 1)
newUser.setValue(imgData, forKey: "photo")
print ("Data added in Users")
}
do {
try context.save()
//print("saved!!!")
Alert.show(title: "Success", message: "Profile Saved", vc: self)
} catch {
// print ("Error")
Alert.show(title: "Error", message: "Profile not Saved", vc: self)
}
}
Showing Users from core data
func showUser() {
let app = UIApplication.shared.delegate as! AppDelegate
let context = app.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false
do {
let results = try context.fetch(request)
if results.count > 0 {
print("Profile: Data Found:")
for result in results as! [NSManagedObject] {
if let firstNameinData = result.value(forKey: "firstName") as? String{
firstName.text = firstNameinData
print(firstNameinData)
}
if let lastNameinData = result.value(forKey: "lastName") as? String{
lastName.text = lastNameinData
print(lastNameinData)
}
if let contactinData = result.value(forKey: "contact") as? String{
contact.text = contactinData
print(contactinData)
}
if let emailinData = result.value(forKey: "email") as? String{
email.text = emailinData
print(emailinData)
}
if let photoinData = result.value(forKey: "photo") as? UIImage{
imageView.image = photoinData
}
}
} else { // if there is not a user profile
firstName.text = ""
lastName.text = ""
contact.text = ""
email.text = ""
print("Profile : No data found")
}
//print("Loaded!!!")
} catch {
print ("Error Loading")
}
}
I cannot show the image I have saved.
Do you have any tips?
EDIT: Xcode gives me this message "Connection to assetsd was interrupted or assetsd died"
The property photo of Users is (NS)Data, as you do there, converting the
UIImage into NSData.
let img = UIImage(named: "f.png")
let imgData = UIImageJPEGRepresentation(img!, 1)
newUser.setValue(imgData, forKey: "photo")
While when you retrieve the info, you are doing like photo was a UIImage object:
if let photoinData = result.value(forKey: "photo") as? UIImage{
imageView.image = photoinData
}
This is not logical according to previous lines. It should be something like that:
if let imageData = result.value(forKey: "photo") as? NSData {
if let image = UIImage(data:imageData) as? UIImage {
imageView.image = image
}
}
Note: I don't speak Swift, so the proposed code may not compile, but you should get the idea of what's wrong and what's need to be done.
Larme has it almost spot on, but instead of this:
if let image = UIImage(data:imageData) as? UIImage
do this:
if let image = UIImage(data: imageData as Data)
Hope i helps you. work fine for me
var results :[Any] = []
let image = UIImage(named: "image.png")
//this is the line that appears to be wrong
let imageData = UIImagePNGRepresentation(image!) as NSData?
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
// 1
let managedContext =
appDelegate.persistentContainer.viewContext
// 2
let entity =
NSEntityDescription.entity(forEntityName: "Image",
in: managedContext)!
let person = NSManagedObject(entity: entity,
insertInto: managedContext)
// 3
person.setValue(imageData, forKeyPath: "name")
// 4
do {
try managedContext.save()
results.append(person)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
Hope this will help you. First I too had a great confusing of storing the image in core Data.
This is used to save the image in coreData
First create Nsmanaged Object Class
class Item: NSManagedObject {
}
Declare the image as NSData
import CoreData
extension Item {
#NSManaged var image: NSData?
#NSManaged var name: String?
#NSManaged var email: String?
}
Now go the View Controller you want to save the image .
class newViewController: UIViewController ,UIImagePickerControllerDelegate,UINavigationControllerDelegate{
var item : Item? = nil
var imagePicker = UIImagePickerController()
var PassImages = UIImage()
#IBOutlet var name: UITextField!
#IBOutlet var email: UITextField!
#IBOutlet var photoclick: UIButton!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
#IBAction func clickaction(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
print("Button capture")
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.sourceType = .photoLibrary
picker.delegate = self //Don't forget this line!
self.present(picker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedImage: UIImage?
if let editedImage = info[.editedImage] as? UIImage {
selectedImage = editedImage
self.image.image = selectedImage!
picker.dismiss(animated: true, completion: nil)
} else if let originalImage = info[.originalImage] as? UIImage {
selectedImage = originalImage
self.image.image = selectedImage!
picker.dismiss(animated: true, completion: nil)
}
}
func imagePickerControllerDidCancel(picker: UIImagePickerController!) {
self.dismiss(animated: true, completion: nil)
}
#IBOutlet var image: UIImageView!=nil
#IBAction func submit(_ sender: Any) {
if name.text != "" && email.text != ""
{
let entityDescription = NSEntityDescription.entity(forEntityName: "Table", in: context)
let item = Item(entity: entityDescription!, insertInto: context)
item.name = name.text
item.email = email.text
item.image = image.image!.pngData()! as NSData
do {
try context.save()
print("saved this moc")
} catch {
return
}
let UserDetailsVc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.navigationController?.pushViewController(UserDetailsVc, animated: true)
}
else
{
print("mail check")
let alertController1 = UIAlertController (title: "Fill Email id", message: "Enter valid email", preferredStyle: UIAlertController.Style.alert)
alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController1, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
if item != nil {
name.text = item?.name
email.text = item?.email
image.image = UIImage(data: (item?.image)! as Data)
}
}
This controller is used to fetch everything
class ViewController: UIViewController ,UITableViewDataSource,UITableViewDelegate,NSFetchedResultsControllerDelegate{
var userarray: [Table] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userarray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
let name = userarray[indexPath.row]
cell.username.text = name.name
cell.showImage?.image = UIImage(data: (name.image)!)
return cell
}
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
override func viewWillAppear(_ animated: Bool) {
fetchData()
}
func fetchData(){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
userarray = try context.fetch(Table.fetchRequest())
print(userarray,"user")
}catch{
print("error")
}
}
}