CoreData: Loading Integers out of a File - swift

I got following code to load the data stored:
func loadLevel(){
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context:NSManagedObjectContext = appDel.managedObjectContext
let request = NSFetchRequest(entityName: "Level")
request.returnsObjectsAsFaults = false
do{
let results:NSInteger = try context.executeFetchRequest(request)
level = results
}catch{
print("Error")
}
}
In the line where I am trying to store the data in the variabel results I get following error:
Cannot convert value of type '[AnyObject]' to specified type 'NSInteger' (aka 'Int')
I do know that I am not doing the error handling correct and as it should be. Thats the 'second step' on my list. Hopefully you can help me on my first problem.

The executeFetchRequest returns an array of results, because fetches can and usually do return more than one result. These results can be of different types depending on how the fetch request was configured. So the return type is [AnyObject].
You're attempting to assign the result of the fetch to a single NSInteger. You can't just assign an array of AnyObject like that. Your results will be zero or more instances of your Level instance, either instances of NSManagedObject or instances of a custom subclass you've configured for the entity.
What you should do is:
Change results to be of type [AnyObject]
Look through this array to find instances of Level
Get integer values from whichever attribute of Level contains the integer that you need.

Related

How to get value of a NSSingleObjectArrayI

func responseDataHandler(data: NSDictionary) {
let temperature_c = data.value(forKeyPath: "data.current_condition.temp_C")
DispatchQueue.main.async{
self.Temperature.text = temperature_c as? String
}
}
I have the above code where I am accessing a weather API which returns data in the form of an NSDictionary to this function. I need to access the value in temperature_c which when I try to print it, it says that it is: Optional(<__NSSingleObjectArrayI 0x600002147fd0>(
25
)
). Temperature is the outlet for label on my storyboard which I want to take on the value of 25 however as written now, it doesn't work and I have tried everything to try and access the value in the Single Object Array but nothing is working. I found this stack overflow question that was similar but it doesn't work for my situation because I keep getting the error that temperature_c is of type any and doesn't have subscripts.
The issue is that you can't cast to String an array, you should try to convert it to [String]. So could change your code to:
self.Temperature.text = (temperature_c as? [String])?.first ?? "Not available"
Let's go step by step:
temperature_c as? [String] tries to convert the NSDictionary to a String array which is the expectable type.
Since the previous step may return nil we have to use optional chaining ?. If we got a valid array using first return the the arrays first element.
Since both previous steps can return nil we can use nil coalescing operator to return a default value. In this case I use "Not available" but you can set any value.
You could write it in a more verbose way like this:
var text2Display2 = "Not available"
if let theArray = temperature_c as? [String] {
if let element = theArray.first {
text2Display2 = element
}
}
self.Temperature.text = text2Display2

How to fetch core data objects into Dictionary in Swift?

I've saved objects in core data, and I am looking how to fetch those objects as a Dictionary
Here is an example of my code where sections is keys for the dictionary and Company as an array of core data objects.
private var companies = Dictionary<String, Array<Company>>()
private var sections: [String] = ["Pending", "Active", "Pending"]
override func viewWillAppear(_ animated: Bool) {
let fetchRequest : NSFetchRequest<Company> = Company.fetchRequest()
let moc = DatabaseController.getContext()
do {
let request = try moc.fetch(fetchRequest)
for case let (index, object) in request.enumerated() {
companies[sections[index]]!.append(object)
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}}
When I am trying to execute my code, I have an error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Could anyone help me with that issue?
That error message means that you're force unwrapping an optional that doesn't have a value. In other words you're using ! where you shouldn't. (You should basically never use the force unwrap operator (!).)
Let's look at the line where you do that:
companies[sections[index]]!.append(object)
If we break this down and add the inferred types we have:
let section: String? = sections[index]
let companyArray: Array<Company> = companies[section]!
You're crashing because companies starts off empty, so asking for any of the arrays will return nil. (Actually, I'm not sure how your code is compiling, since you can't subscript into the dictionary with an optional.)
However, if you fix that, we still have a problem because you're using the index of the fetched array to look up the section. If you have more than three companies, that will start to fail.
I suspect you want something like:
for let company in result {
if var companyArray = companies[company.status] {
companyArray.append(company)
} else {
companies[company.status] = [company]
}
}
Where status is an invented property on Company that returns a String like "Pending" or "Active".
I've found the solution, just need to use NSFetchResultController in order to display data in TableView by different sections.

Variable used within its own initial value Swift 3

I try to convert my code to swift 3 an I have spent hours on the following error:
Type 'Any' has no subscript members
Here's was my original code:
let data: AnyObject = user.object(forKey: "profilePicture")![0]
I looked at the answers here but I'm still stuck. (I do programming as a hobby, I'm not a pro :/)
I've try that:
let object = object.object(forKey: "profilePicture") as? NSDictionary
let data: AnyObject = object![0] as AnyObject
But now I get this error:
Variable used within its own initial value
Second issue: Use always a different variable name as the method name, basically use more descriptive names than object anyway.
First issue: Tell the compiler the type of the value for profilePicture, apparently an array.
if let profilePictures = user["profilePicture"] as? [[String:Any]], !profilePictures.isEmpty {
let data = profilePictures[0]
}
However, the array might contain Data objects, if so use
if let profilePictures = user["profilePicture"] as? [Data], !profilePictures.isEmpty {
let data = profilePictures[0]
}
Or – what the key implies – the value for profilePicture is a single object, who knows (but you ...)
And finally, as always, don't use NSArray / NSDictionary in Swift.

Core Data is returning 0

Update: Following some advice from the comments, I am using NSManagedObject Subclassing. So my code is completely different so I am rewriting the question to better reflect what I am doing now.
So my question is: I am saving non-zero values to Core Data, but when I retrieve a value I am getting zero back. What could be wrong?
So now let's pretend I have two entities named FirstEntity, SecondEntity with two attributes named firstAttribute, secondAttribute. And since I did the NSManagedObject Subclassing I have two classes one named FirstEntity and the second named SecondEntity. Each class has an extension for the two attributes (firstAttribute, secondAttribute).
Saving Values:
So when I save a value I would use code along the lines of:
let number = 100
let firstEntity = NSEntityDescription.insertNewObjectForEntityForName("FirstEntity", inManagedObjectContext: managedObject) as! FirstEntity
firstEntity.firstAttribute = number
Retrieving Values: When I try to receive an attribute's value in Core Data I use code like this:
let firstEntity = NSEntityDescription.insertNewObjectForEntityForName("FirstEntity", inManagedObjectContext: managedObject) as! FirstEntity
print(firstEntity.firstAttribute) // This returns zero when I clearly saved a value of 100 above.
I am pretty new to Core Data, and I have looked up many examples of how to use Core Data online. I am still kind of confused about what I could possibly be doing wrong. If there is any clarification required just ask in the comments, and I will definitely respond.
Potential Error: So what I am doing is I am trying to save an attributes value in the completionHandler of a function. Also, if I print the variable's value inside the completionHandler I get the proper value of the attribute. For example:
someFunction() {
number in // Pretend number is 5000
let firstEntity = NSEntityDescription.insertNewObjectForEntityForName("FirstEntity", inManagedObjectContext: managedObject) as! FirstEntity
firstEntity.firstAttribute = number
print(firstEntity.firstAttribute) // Prints 5000 to the console
}
However, let's say I go to access the firstAttribute value outside of the completionHandler and I print the value to the console I get a value of 0. For example:
class MyClass {
func myFunction() {
let firstEntity = NSEntityDescription.insertNewObjectForEntityForName("FirstEntity", inManagedObjectContext: managedObject) as! FirstEntity
print(firstEntity.firstAttribute) // Prints 0
}
}
I also wanted to mention that I am making sure that the completionHandler in the function has set the value of the firstAttribute before calling the MyClass's myFunction().
Ok, so I think I found the answer I was creating too many instances of the entity. So what I ended up doing was I created a global constant:
let firstEntity = NSEntityDescription.insertNewObjectForEntityForName("FirstEntity", inManagedObjectContext: managedObject) as! FirstEntity
Then I referenced firstEntity whenever I needed to retrieve or save a value so I didn't have multiple instances of FirstEntity. Then I can access the value from anywhere.

Swift Error: Ambiguous reference to member 'subscript'

I'm new to coding and picked up some open source project to get the idea.
I'm getting the error:
Ambiguous reference to member 'subscript'
in the code below:
let pictures = ( selectedRestaurant["Pictures"] as! NSArray ) // Error
let picture = ( pictures[zoomedPhotoIndex] as! NSDictionary )
let pictureURL = picture["url"] as! String
let imageURL = NSURL(string: pictureURL)
let urlRequest = NSURLRequest(URL: imageURL!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) {
response, data, error in
if error == nil && data != nil {
self.imageView.image = UIImage(data: data!)
self.imageView.contentMode = UIViewContentMode.ScaleAspectFit
}
}
Just specify explicitly what is the type of pictures:
So instead of:
let pictures = selectedRestaurant["Pictures"] as! NSArray
Write:
let pictures: NSArray = selectedRestaurant["Pictures"] as! NSArray
For me the answer was to specifically state the type of array I was casting to:
if let foo = dictionary["bar"] as? [String]
It means that "Pictures" is not a valid subscript. It looks like you are creating a constant named pictures and you are trying to assign it a value of selectedRestaraunt["Pictures"] and then trying to cast it as an NSArray. If selectedrestaraunt is already an array, then what goes in the [] brackets after selectedRestaraunt should be an integer value which will refer to an index in the selectedRestaraunt array. Obviosuly "Pictures" is not an integer, it is a string.
If you are trying to access an array within an array. Meaning that Pictures is an array stored within the selectedRestarauntarray then you can access it by using selectedRestaraunt[index of Pictures array] where [index of pictures array] is an integer which is equal to the index number in which the Picutres array resides within the selectedRestaraunt array
I managed to get this error in a somewhat weird way. I had code like this:
cell.textLabel = anArrayOfStrings[indexPath.item].uppercased()
And I was stumped as to why it couldn't figure out that this was an array, even though I very clearly declared its type. I broke the line in two and finally got a helpful error message:
let name = anArrayOfStrings[indexPath.item].uppercased()
cell.textLabel = name
I was trying to assign a String to a UILabel, but somehow the point at which the type inference engine failed was at the subscript.
So my advice to anyone stumped by this is to try to break up your statement into bite-sized chunks that the Swift type inference engine can more easily digest.
As Eric and Eugene mentioned in their comments it is impossible to review the issue you are having without knowing the selectedRestaurant type. That is after all why you are getting the compiler ambiguity error.
I have to respectfully disagree with MikeG though. The problem is not one of a valid subscript. You'd be getting that kind of error, if for example you had a selectedRestaurant type of [NSNumber:AnyObject], where clearly String is no longer valid since the dictionary key could only be an NSNumber.