use helper method to fetch specific attribute from core data - swift

IN my swift 5 code below the goal would be to fetch the first item from core data entity Info attribute username. I am attempting to d that right now I am getting a error at titleLabel.text = String(user![0]) stating
no exact matches in call to initializer
Somehow I know I will need to attach .username somehow but I dont know what to do next at this point.
class ViewController: UIViewController {
var user : [User]? = nil
var titleLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
user = CoredataHandler.fetchObject()
titleLabel.text = String(user![0])
}
}
class CoredataHandler : NSManagedObject {
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
class func saveObject(username: String,password: String,tf: Bool) -> Bool{
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "User", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(username, forKey: "username")
managedObject.setValue(password, forKey: "password")
managedObject.setValue(tf, forKey: "tf")
do {
try context.save()
return true
} catch{
return false
}
}
class func fetchObject() -> [User]?
{
let context = getContext()
var user : [User]? = nil
do {
user = try context.fetch(User.fetchRequest())
return user
} catch {
return user
}
}
}

Related

save string over saved string in core data

In my swift code below the code saves an item in core data. The goal is to overwrite that item. I am getting a runtime error at
CoreDataHandler.changeName(user: fetchUser!\[indexNumber\], jessica: "jo")
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I don't know how to wrap in the index number. The goal is it to print judo then jo
import UIKit;import CoreData
class ViewController: UIViewController {
var fetchUser: [UserInfo]? = nil
var indexNumber : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
CoreDataHandler.saveObject2( name: "judo")
getText(textNo: indexNumber)
saveTheItem()
}
#objc func saveTheItem(){
CoreDataHandler.changeName(user: fetchUser![indexNumber], jessica: "jo")
}
func getText(textNo:Int) {
// first check the array bounds
let info = helpText.shareInstance.fetchText()
if info.count > textNo {
if let imageData = info[textNo].name
{
print(imageData)
} else {
// no data
print("data is empty Textss")
}
} else {
// image number is greater than array bounds
print("you are asking out of bounds")
}
}
}
class CoreDataHandler : NSManagedObject {
class func saveObject2( name: String) -> Bool {
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "UserInfo", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(name, forKey: "name")
do{
try context.save()
return true
}
catch {
return false
}
}
private class func getContext() -> NSManagedObjectContext{
let appD = UIApplication.shared.delegate as! AppDelegate
return appD.persistentContainer.viewContext
}
class func changeName(user: UserInfo,jessica : String) -> Bool
{
let context = getContext()
user.name = jessica
print(jessica)
do{
try context.save()
return true
}
catch{
return false
}
}
}
class helpText: UIViewController{
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
static let shareInstance = helpText()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func saveName(data: String) {
let imageInstance = UserInfo(context: context)
imageInstance.name = data
do {
try context.save()
} catch {
print(error.localizedDescription)
}
}
func fetchText() -> [UserInfo] {
var fetchingImage = [UserInfo]()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "UserInfo")
do {
fetchingImage = try context.fetch(fetchRequest) as! [UserInfo]
} catch {
print("Error while fetching the image")
}
return fetchingImage
}
}
No offense but your code is a mess.
And there is a big misunderstanding. Core Data records are unordered, there is no index. To update a record you have to fetch it by a known attribute, in your example by name, update it and save it back.
This is a simple method to do that. It searches for a record with the given name. If there is one, update the attribute with newName and save the record.
The code assumes that there is a NSManagedObject subclass UserInfo with implemented class method fetchRequest.
func changeName(_ name: String, to newName: String) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request : NSFetchRequest<UserInfo> = UserInfo.fetchRequest()
request.predicate = NSPredicate(format: "name == %#", name)
do {
let records = try context.fetch(request)
guard let foundRecord = records.first else { return }
foundRecord.name = newName
try context.save()
} catch {
print(error)
}
}
Regarding your confusing code:
Create CoreDataHandler as singleton (and it must not be a subclass of NSManagedObject). Move the Core Data related code from AppDelegate and the methods to read and write in this class.

Deleting a binary data image by a instance

In my Swift code below the goal is to delete a binary data by the corresponding var Int. The var Int is called counterImage. My code right now is causing a runtime error of counterImage
'Cannot convert value of type 'Int' to expected argument type 'TheBook''
What can I do to fix this? All the code is right here. You would have to add the images but after that you can just copy and paste the code.
import UIKit;import CoreData
class ViewController: UIViewController {
var counterImage = 1
override func viewDidLoad() {
super.viewDidLoad()
let gwen = UIImage(named: "h")
if let imageData = gwen.self?.pngData() {
helpImage.shareInstance.saveImage(data: imageData)
}
let gwen2 = UIImage(named: "hh")
if let imageData = gwen2.self?.pngData() {
helpImage.shareInstance.saveImage(data: imageData)
}
helpImage.shareInstance.deleteObject(user: counterImage)
}
}
class helpImage: UIViewController{
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
static let shareInstance = helpImage()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func saveImage(data: Data) {
let imageInstance = TheBook(context: context)
imageInstance.pic = data
do {
try context.save()
} catch {
print(error.localizedDescription)
}
}
func deleteObject(user: TheBook) {
let context = helpImage.getContext()
let delete = NSBatchDeleteRequest(fetchRequest: TheBook.fetchRequest())
do {
try context.execute(delete)
} catch {
}
}
}

save core data into boolean value

In my swift code below the goal is to save a boolean value into core data. I am getting a compile error stating Thread 1: "Unacceptable type of value for attribute: property = "bool"; desired type = NSNumber; given type = __SwiftValue; value = true.". I don't know what to do next. I also added a photo of my core data attributes. I have 2 classes a base class and a helper class.
pic
class ViewController: UIViewController {
var user : [User]? = nil
CoredataHandler.saveObject(username: "Yahs", password: "213", bool: true)
}
class CoredataHandler : NSManagedObject {
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
class func saveObject(username: String,password: String,bool: DarwinBoolean) -> Bool{
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "User", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(username, forKey: "username")
managedObject.setValue(password, forKey: "password")
managedObject.setValue(bool, forKey: "bool")
do {
try context.save()
return true
} catch{
return false
}
}
}

use uitextfield delegetate to fetch coredata binary data by its count number

My swift code saves 3 names to core data entity "username". I want to use uitextfield delegate to pull a specific string. So when the user enters 2 in the textfield. On the label labelName the name jessica Biel should appear. So the user enters a number into a textfield a string appears on the label. If number 1 is enter the 1st NSManagedObject into the core data entity userName. Link to project https://github.com/redrock34/jessicaBiel
import UIKit
import CoreData
class ViewController: UIViewController,uitextfielddele {
#IBOutlet var labelName : UILabel!
#IBOutlet var enterT : UITextField!
// MARK: Variables declearations
let appDelegate = UIApplication.shared.delegate as! AppDelegate //Singlton instance
var context:NSManagedObjectContext!
// MARK: View Controller life cycle methods
override func viewDidLoad() {
super.viewDidLoad()
openDatabse()
}
// MARK: Methods to Open, Store and Fetch data
func openDatabse()
{
context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Users", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
let newUser2 = NSManagedObject(entity: entity!, insertInto: context)
let newUser3 = NSManagedObject(entity: entity!, insertInto: context)
saveData(UserDBObj: newUser, UserDBObj2: newUser2, UserDBObj3: newUser3)
}
func saveData(UserDBObj:NSManagedObject,UserDBObj2:NSManagedObject,UserDBObj3:NSManagedObject)
{
UserDBObj.setValue("kim kardashian", forKey: "username")
UserDBObj2.setValue("jessica biel", forKey: "username")
UserDBObj3.setValue("Hailey Rienhart", forKey: "username")
print("Storing Data..")
do {
try context.save()
} catch {
print("Storing data Failed")
}
fetchData()
}
func fetchData()
{
print("Fetching Data..")
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
let userName = data.value(forKey: "username") as! String
print("User Name is : "+userName)
}
} catch {
print("Fetching data Failed")
}
}
}
First of all be aware that on each launch of the app the three records are inserted again and again so you'll get a bunch of duplicates.
As the names are apparently not related to any order add an unique identifier like an integer attribute index – or whatever name is reasonable – and then fetch the data with a predicate NSPredicate(format: "index == %ld", Int(enterT.text!) ?? 0).
You have to do that because Core Data saves the objects unordered.

Use core data index to fetch a specific item from core data

My swift code below when loaded places 3 items in the core data entity named "UserName". When the user enters a number into textfield enterT I want the label labelName to display it. So when the user enters 1 the label should display jessica biel because Jesical Biel is the first name entered. Someone stated the suggestion below to solve this problem. I dont know exactly how to do this.I have added a gif below.
Convert the entered number to Int. If this succeeds pass the integer to joke and fetch the record matching the idx attribute.
https://github.com/redrock34/index-fetch
import UIKit
import CoreData
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet var labelName : UILabel!
#IBOutlet var enterT : UITextField!
lazy var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
openDatabse()
fetchData()
enterT.delegate = self
}
func textFieldDidEndEditing(_ textField: UITextField) {
guard let index = Int(textField.text!) else {
// display an alert about invalid text
return
}
joke(at: index - 1)
}
func joke(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 {
labelName.text = user.username
}
} catch {
print("Could not fetch \(error) ")
}
}
func openDatabse()
{
let names = ["kim kardashian", "jessica biel", "Hailey Rienhart"]
for i in 0..<names.count {
let newUser = Users(context: context)
newUser.username = names[i]
newUser.idx = Int32(i + 1)
}
print("Storing Data..")
do {
try context.save()
} catch {
print("Storing data Failed", error)
}
}
func fetchData()
{
print("Fetching Data..")
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
let userName = data.value(forKey: "username") as! String
print("User Name is : "+userName)
}
} catch {
print("Fetching data Failed")
}
}}
Of course you have to assign values to the idx attribute and you have to assign the result of the fetch to the label.
First replace
let appDelegate = UIApplication.shared.delegate as! AppDelegate //Singlton instanc
var context:NSManagedObjectContext!
with
lazy var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Then replace both openDatabse and saveData with
func openDatabse()
{
let names = ["kim kardashian", "jessica biel", "Hailey Rienhart"]
for i in 0..<names.count {
let newUser = Users(context: context)
newUser.name = names[i]
newUser.idx = Int32(i + 1)
}
print("Storing Data..")
do {
try context.save()
} catch {
print("Storing data Failed", error)
}
}
Finally add a line in joke to display the value
func joke(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 {
labelName.text = user.username
}
} catch {
print("Could not fetch \(error) ")
}
}
It creates the records and assigns the proper indexes. Then entering a number in the text field should work.
But – once again – on each launch of the app the 3 records are inserted again with the same names and indexes. Be aware of that!