Im trying to populate an NSMutableArray from the CoreData database (using swift) but not sure what I'm doing wrong. Here's my code:
var stuff: NSMutableArray = []
populating the NSMutableArray:
override func viewDidAppear(animated: Bool) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
let freq = NSFetchRequest(entityName: "MyData")
stuff = context.executeFetchRequest(freq, error: nil)
tableView.reloadData()
}
Error:
Just define stuff as
var stuff : Array<AnyObject> = []
Which will create stuff as an array suitable for the return type of executeFetchRequest().
When you then access elements of the array you will also need to satisfy the type constraints. You should look into the Apple documentation for as, as? and is and the associated usage examples. In the very simplest case it would be something like:
var aThing : NSManagedObject? = stuff[0] as? NSManagedObject
For the above aThing would be nil if stuff[0] is not an NSManagedObject nor subclasses.
Related
I have a request for an entity in core data:
override func viewWillAppear(animated: Bool) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Constants")
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
Within the entity Constants there are 4 attributes: moneyPerSecondSave,moneySave,tapMultiplierSaveandtapValueSave.
My question is, is there a way that after I have got the results can I make four variables which each hold each of the values of the attributes.
I have already tried using valueForKey:
moneyConstants.money = results.valueForKey("moneySave")
However when I try this it pulls up an error: `Value of type '[AnyObject]' has no member 'valueForKey'. Any help would be appreciated.
'results' is an array which holds 'Any' type. You can cast it to an array with the type you expect and get the rest of the data like this:
if let constants = results as? [Constants] {
let moneyPerSecond = constants[0].moneyPerSecondSave
print("moneyPerSecond: \(moneyPerSecond)")
}
You can also use valueForKey of course, like this:
if let match = results[0] as? Constants {
let money = match.value(forKey: "moneySave") as! Float
print("money: \(money)")
}
You can use propertiesToFetch & resultType attribute of NSFetchRequest to retrieve only specific property values of Constants.
You can take inspiration from https://stackoverflow.com/a/6267875/3339346
I have an object called Projects that I save to core data. I then add multiple projects to core data. I want to retrieve those objects as an array from core data. The following code gets this error:
-[NSAsynchronousFetchResult mutableCopyWithZone:]: unrecognized selector sent to instance
var uploadPhotos : NSMutableArray? = []
var activeProject : String!
override func viewDidLoad() {
super.viewDidLoad()
projectPicker.dataSource = self
projectPicker.delegate = self
isInSegmentPhoto = true
//let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Project")
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Project.fetchRequest()
let entityDescription = NSEntityDescription.entity(forEntityName: "Project", in: sharedDelegate.managedObjectContext)
fetchRequest.entity = entityDescription
do {
let result = try self.sharedDelegate.managedObjectContext.execute(fetchRequest)
print(result)
projects = result.mutableCopy() as! [Project]
} catch {
let fetchError = error as NSError
print(fetchError)
}
}
When I run the program it prints out the list of projects, but crashes on the first line of the do-catch.
Please, please use Swift native types, NSMutableArray has no type information.
var projects = [Project]()
...
projects = try defaultManagedObjectContext().fetch(fetchRequest) as! [Project]
Since the fetch request is clearly a Project request you can safely unwrap the result.
mutableCopy() causes the error, because NSFetchRequestResult(the umbrella protocol of all possible result types) does not respond to that method.
Figured it out! I was using the wrong method. Replace execute with fetch.
self.sharedDelegate.managedObjectContext.fetch(fetchRequest)
I use Swift. I can save data into a core data base. And I can even print out the data in a for loop but I can't load it into a table view. I have an empty string array(called subjects) that the table view uses it as a data source but I would like to load the data in a for loop into that array.
Here's how I save the data:
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var newSubject = NSEntityDescription.insertNewObjectForEntityForName("Subjects", inManagedObjectContext: context) as NSManagedObject
newSubject.setValue("" + classTextField.text, forKey: "subjectName")
context.save(nil)
Here's how I retrieve the data:
I have an empty string array in the class called subjects.
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Subjects")
request.returnsObjectsAsFaults = false
var results:NSArray = context.executeFetchRequest(request, error: nil)!
if(results.count > 0){
for res in results{
println(res)
subjects.append(res)
}
}else{
println("0 Results.")
}
So, I can print out the data as you can see in the for loop, but I can't add that res value into my subjects array which is used by the table view. But I get the AnyObject is not convertible to String error message.
Edit:
Sorry, I misunderstood the code.
You need to unwrap the results to an array of Subjects
if let resultsUnwrapped = results as? [Subjects] {
for res in resultsUnwrapped{
println(res.description())
subjects.append(res.subjectName)
}
}
It's the first time I'm trying to save and retrieve custom data to/from my core data, but I've run into an error saying:
fatal error: array cannot be bridged from Objective-C
when I try to load the data back.
My code looks like this, the arrayOfNames is declared as [String]:
#IBAction func saveTap(sender: AnyObject) {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let contxt: NSManagedObjectContext = appDel.managedObjectContext!
let en = NSEntityDescription.entityForName("Indexes", inManagedObjectContext: contxt)
let arrayData: NSData = NSKeyedArchiver.archivedDataWithRootObject(arrayOfNames)
let newIndex = Indexes(entity: en!, insertIntoManagedObjectContext: contxt)
newIndex.monday = arrayData
println(newIndex.monday)
contxt.save(nil)
}
#IBAction func loadTap(sender: AnyObject) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let fetchReq = NSFetchRequest(entityName: "Indexes")
let en = NSEntityDescription.entityForName("Indexes", inManagedObjectContext: context)
var myList:[String] = context.executeFetchRequest(fetchReq, error: nil) as! [String]
println(myList)
}
My model-file looks like this:
#objc(Indexes)
class Indexes: NSManagedObject {
#NSManaged var monday: NSData
#NSManaged var tuesday: NSData
#NSManaged var wednesday: NSData
#NSManaged var thursday: NSData
#NSManaged var friday: NSData
}
I've also set all the attributes to transformable in my data model. As I said, it's the first time I'm doing this, so sorry if the solution is obvious.
Any suggestions would be appreciated.
executeFetchRequest returns [AnyObject]?, not [String], indeed the objects in the array should be Indexes instances which contain your archived arrays of strings.
So, you need to correct the array type that the results of the fetch are being placed into.
This question already has an answer here:
Sorting Array received from Core Data in Swift
(1 answer)
Closed 8 years ago.
I want to sort the array with usernames that I retrieve from my core data. I retrieve it like this:
override func viewDidAppear(animated: Bool) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let freq = NSFetchRequest(entityName: "User")
let en = NSEntityDescription.entityForName("User", inManagedObjectContext: context)
myList = context.executeFetchRequest(freq, error: nil)!
tv.reloadData()
}
And later I set the cells in my tableview like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID:NSString = "cell"
var cell: UITableViewCell = self.tv.dequeueReusableCellWithIdentifier(CellID) as UITableViewCell
if let ip = indexPath as Optional {
var data:NSManagedObject = myList[ip.row] as NSManagedObject
cell.textLabel!.text = data.valueForKeyPath("username") as String!
}
I tried to use the sorting function for in the viewDidAppear function like this:
var sortedList = myList.sorted { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
But this gives me an error saying: "Could not find member 'localizedCaseInsensitiveCompare'"
Any suggestions on how to proceed would be appreciated.
executeFetchRequest returns [AnyObject]? and you need to convert this as [NSManagedObjet] array and sort on user key
if let myList = myList as? [NSManagedObject] {
var sortedList = myList.sorted { ($0.valueForKeyPath("user") as String).localizedCaseInsensitiveCompare(($1.valueForKeyPath("user") as String)) == NSComparisonResult.OrderedAscending }
}
else {
println("My List not contains the NSManagedObject array")
}
I like to use a separate function to fetch and sort the array. You sort the array by using an NSSortDescriptor. You can add the capitalization check as a selector for the sort descriptor. I got the separate function idea from this tutorial. I used it and it works for me. I got the idea for the selector idea by referencing this Objective-C code.
var objectives: [NSManagedObject]!
func fetchUsernames() {
static let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let freq = NSFetchRequest(entityName: "User")
let sortDescriptor = NSSortDescriptor(key: "username", ascending: true, selector: "localizedCaseInsensitiveCompare:")
freq.sortDescriptors = [sortDescriptor]
do {
let fetchedResults: [NSManagedObject] = try managedContext.executeFetchRequest(freq) as! [NSManagedObject]
if let results: [NSManagedObject] = fetchedResults {
objectives = results
}
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
tableView.reloadData()
}