How to fetch Images from CoreData correct? - swift

this is the code how I save images in CoreData:
lazy var dataImage = profileIcon.jpegData(compressionQuality: 1.0)
//MARK: - Saving the Workout Image
func savePUValues() {
// Kontext Identifiziern
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let context = appDelegate.persistentContainer.viewContext
let entityName = "PushUps" //Tabellenname im DatenModell
//Neuen Datensatz anlegen:
guard let newEntity = NSEntityDescription.entity(forEntityName: entityName, in: context)
else {
return
}
let newSet = NSManagedObject(entity: newEntity, insertInto: context)
let savingImage = dataImage
newSet.setValue(savingImage, forKey: "image")
// Datensatz speichern
do {
try context.save()
} catch {
print("An error appeared")
}
}
Now I want to fetch the image data and load it into a UITableView:
With this code:
func loadValues() -> [CellData] {
//Kontext identifizieren
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//Anfrage stellen
let context = appDelegate.persistentContainer.viewContext
let entityName = "PushUps"
//MARK: - Request
// Use a specific fetch request
let request = NSFetchRequest<PushUps>(entityName: entityName)
// add a sort descriptor to sort the items by highScore descending
request.sortDescriptors = [NSSortDescriptor(key: "count", ascending: false)]
do {
// results is an array of PushUps instances, no type cast needed
let results = try context.fetch(request)
for r in results {
if let result = r as? NSManagedObject {
let titletext = "\(count!) Push-Ups"
var cellTitleLabel = UILabel()
cellTitleLabel.text = titletext
let workoutImage = result.value(forKey: "image") as? UIImageView
print("Image was loaded into the array")
var Data1 = CellData(imageData: workoutImage ?? oImageView, titleData: cellTitleLabel)
print("Image: \(String(describing: workoutImage)), TitLe: \(cellTitleLabel) ")
cellDataArray.append(Data1)
}
}
} catch {
print(error)
}
return cellDataArray
}
The problem is that the it's loading the image as nil.
The console is giving me this back: "Image: nil, TitLe: <UILabel: 0x115f17980; frame = (0 0; 0 0); text = '0.0 Push-Ups'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x28249cfa0>> "
So where is the problem? What is wrong with my Code?
Thanks for your help!

The problem is that you are saving Data and trying to retrieve it as a UIImageView, which is doomed to failure:
lazy var dataImage = profileIcon.jpegData(compressionQuality: 1.0)
// Data
let savingImage = dataImage
newSet.setValue(savingImage, forKey: "image")
// still Data
// ---------------------
let workoutImage = result.value(forKey: "image") as? UIImageView
// UIImageView?????
However, don't save image data into Core Data in the first place. Save to disk and store the partial path (e.g. the file name).

Related

pull details from local database

I want to pull details from local database but when I do the necessary operations, it returns null as a result. I can't understand where I went wrong.
var chosenCar=""
var chosenCarId : UUID?
the arrays I created, I transfer data to these arrays, there is no problem with that, I did a test
if chosenCar != "" {
//core data
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "CarsInformation")
let idString = chosenCarId?.uuidString
fetchRequest.predicate = NSPredicate(format: "id = %#", idString!)
fetchRequest.returnsObjectsAsFaults = false
do {
let results = try context.fetch(fetchRequest)
if results.count > 0 {
for result in results as! [NSManagedObject] {
if let name = result.value(forKey: "models") as? String {
modelTextField.text = name
}
if let year = result.value(forKey: "year") as? Int {
yearTextField.text = String(year)
}
if let price = result.value(forKey: "price") as? Int {
priceTextField.text = String(price)
}
if let imageData = result.value(forKey: "image") as? Data {
let image = UIImage(data: imageData)
imageView.image = image
}
}
}
} catch{
print("error")
}
} else {
modelTextField.text = ""
priceTextField.text = ""
yearTextField.text = ""
}
After doing these operations, I can't get the result I want.

Lottie Animation stopped working when I want to save something in CoreData

I want to download data from Firebase Database and save it into CoreData. Because this takes a few seconds I wanted to present a Lottie animation during the downloading and saving process. The animation works, but during this process the app doesn't play the animation. Does anyone know how to solve this?
How I set up the Lottie Animation
let lottieView: AnimationView = {
let lottieView = AnimationView()
lottieView.animation = Animation.named("animation")
lottieView.loopMode = .loop
lottieView.translatesAutoresizingMaskIntoConstraints = false
return lottieView
}()
When it should be played
var entityName = "Words"
var level = "Beginner"
Database.database().reference().child("Words").child(level).observe(.childAdded) { (snapshot) in
self.lottieView.play()
if let dict = snapshot.value as? [String: Any] {
let word = Word(original: "\(dict["original"]!)", translated: "\(dict["translated"]!)", level: "\(dict["level"]!)", phase: "1", lastQuery: dateFormatter.string(from: date), learned: false)
allWords.append(word)
self.saveWord(entity: newEntityName, word: word)
self.lottieView.stop()
}
}
How I save the words
func saveWord(entity: String, word: Word) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let context = appDelegate.persistentContainer.viewContext
let entityName = entity
guard let newEntity = NSEntityDescription.entity(forEntityName: entityName, in: context) else {
return
}
let newWord = NSManagedObject(entity: newEntity, insertInto: context)
let original = word.original
let translated = word.translated
let level = word.level
let phase = "1"
let lastQuery = word.lastQuery
let learned = false
newWord.setValue(original, forKey: "original")
newWord.setValue(translated, forKey: "translated")
newWord.setValue(level, forKey: "level")
newWord.setValue(phase, forKey: "phase")
newWord.setValue(lastQuery, forKey: "lastQuery")
newWord.setValue(learned, forKey: "learned")
do {
try context.save()
print("Saved: \(original)")
} catch {
print(error)
}
}

how to save/fetch non English characters into core data?

I have successfully added and fetched some data using core data. my entity attribute has the following scheme: productName, price and quantity.
price and quantity are displayed correctly in the console. On the other hand, product name is written in Arabic and therefore it is displayed in weird characters like: "\U062c\U064a\U0628 \U0627\U0644\U062a\U0627\U062c\U0631";
save to core data code:
#IBAction func submitOrderButton(_ sender: UIButton) {
let newItem = NSEntityDescription.insertNewObject(forEntityName: "OrderDetail", into: context)
newItem.setValue(String(self.productName.text!), forKey: "productName")
newItem.setValue(Int(self.productPrice.text!), forKey: "price")
newItem.setValue(self.orderQuantity, forKey: "quantity")
do{
try context.save()
}
catch{
// display in a uialert message
print("error has occured")
}
print("\(orderQuantity) items of this product")
}
fetch from core data code:
func fetchOrderDetails(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchedOrders = NSFetchRequest<NSFetchRequestResult>(entityName: "OrderDetail")
fetchedOrders.returnsObjectsAsFaults = false
do{
let result = try context.fetch(fetchedOrders)
if result.count > 0{
print()
}
}
catch{
}
}
output in console:
<OrderDetail: 0x604000480af0> (entity: OrderDetail; id: 0xd000000000040000 <x-coredata://109134CB-DCF5-45D8-9298-E8B43C51E5DA/OrderDetail/p1> ; data: {
price = 3;
productName = "\U062c\U064a\U0628 \U0627\U0644\U062a\U0627\U062c\U0631";
quantity = 2;
})
Thanks!
UPDATE
All I did was access the attributes and then I could either assign it to a label or print it in the console. Both worked.
Below is the code I added:
do{
let result = try context.fetch(fetchedOrders)
if result.count > 0{
// added code
var tempProd = result[0] as! NSManagedObject
productName.text = "\(tempProd.value(forKey: "productName"))"
for data in result as! [NSManagedObject]{
print(data.value(forKey: "productName") as! String)
}
// end of added code
}
}

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")
}
}
}

core data object not saved in sqlite

I'm having a problem that the sqlite file is only edited when adding the objects in the first time.After that only the sqlite-shm file is changed. So when I relaunch the app nothing changes.Here is the core data stack in the AppDelegate
lazy var managedObjectContext: NSManagedObjectContext = {
let modelURL = NSBundle.mainBundle().URLForResource("StoriesCoreData", withExtension: "mom")
let mom = NSManagedObjectModel(contentsOfURL: modelURL!)
let psc = NSPersistentStoreCoordinator(managedObjectModel: mom!)
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
print (urls[urls.endIndex-1])
let storeURL = (urls[urls.endIndex-1]).URLByAppendingPathComponent("stories.sqlite")
var error: NSError? = nil
var store: NSPersistentStore?
do {
store = try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil)
} catch var error1 as NSError {
error = error1
store = nil
} catch {
fatalError()
}
if (store == nil) {
print("Failed to load store")
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = psc
return managedObjectContext
}()
func saveContext() {
var error: NSError? = nil
let moc : NSManagedObjectContext? = self.managedObjectContext
if moc == nil {
return
}
if !managedObjectContext.hasChanges {
return
}
do {
try managedObjectContext.save()
return
} catch let error1 as NSError {
error = error1
}
print("Error saving context: \(error?.localizedDescription)\n\(error?.userInfo)")
abort()
}
Here is how the objects are initialized:
let aStory = NSEntityDescription.insertNewObjectForEntityForName("PersonalizedStory", inManagedObjectContext: managedObjectContext) as! PersonalizedStory
aStory.childrenMode = NSNumber(int: 0)
aStory.hidden = NSNumber(int: 0)
aStory.lastEdited = NSDate()
aStory.parentStoryDownloadDate = NSDate()
aStory.parentStoryID = "10000"
aStory.parentWriterID = "guest"
aStory.personalizedStoryID = "10"
aStory.pictureList = []
aStory.userID = "guest"
aStory.inSection = NSSet()
saveContext()
let aSection = NSEntityDescription.insertNewObjectForEntityForName("LibrarySection", inManagedObjectContext: managedObjectContext) as! LibrarySection
aSection.personalizedStoriesOrder = []
aSection.sectionName = "AllStories"
aSection.userID = "guest"
aSection.personalizedStoriesOrder!.append(aStory)
aSection.hasStory = NSSet()
saveContext()
aSection.addObject(aStory, forKey: "hasStory")
aStory.addObject(aSection, forKey: "inSection")
saveContext()
Here is the fetch request and modification:
func allStories () -> [PersonalizedStory]? {
var error : NSError? = nil
let fetchStories = NSFetchRequest(entityName: "LibrarySection")
let sectionsForUser = NSPredicate(format: "userID = %#", argumentArray: [userID])
let all = NSPredicate(format: "sectionName == %#", argumentArray: ["AllStories"])
let fetchPredicates = NSCompoundPredicate(andPredicateWithSubpredicates: [sectionsForUser,all])
fetchStories.predicate = fetchPredicates
var result : [LibrarySection]?
do {
result = try appDelegate.managedObjectContext.executeFetchRequest(fetchStories) as? [LibrarySection]
} catch {
result = nil
}
let theSection = result!.first!.personalizedStoriesOrder!
for story in theSection {
story.setValue(1, forKey: "childrenMode")
}
appDelegate.saveContext()
return theSection
}
So in when I print out the stories later on childMode is set to 1.
However when I relaunch every thing is set back to 0.
And when I check the app folder