Swift2 cast NSArray to Array - swift

Im trying to put fetched objects into an Array, but I'm lost here... Any help would be greatly appreciated! I have an Entity with an attribute 'date' which is a NSDate type. The other attributes are NSNUmber types. I want to put all 'dates' into an array that I will use for a UIPicker, but I'm unable to cast NSArray to a Swift Array. Please see the code below:
var context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var request = NSFetchRequest(entityName: "Diary")
request.returnsObjectsAsFaults = false
//Fetching Data
do {
self.DataArray = try context.executeFetchRequest(request) as! [Diary]
} catch {
print("error")
}
var DATES = (self.DataArray as NSArray).valueForKey("date") as! NSArray
print(DATES) // all content is visible
months = DATES as! [String] // here the app crashes with error in the console - months = ([String]!) nil

I have an Entity with an attribute 'date' which is a NSDate type
So why are you trying to as! it into a String. A date is not a string. This should be [NSDate], not [String].

Related

Swift JSON to Dictionary<String: Any>. Then cast "Any" as NSMutableArray

I am trying to read from a JSON String and draw a graph with its data:
{"y-axis-data":{"min":0.0,"max":1000,"Step":100.0},"x-labels":[1994,2000,2005],"y-values":[20,305,143]}
I wrote a function to create a dictionary from the string:
func jsonToDictionary(jsonString: String) -> [String: Any]? {
if let jsonData: Data = jsonString.data(using: String.Encoding.utf8) {
do {
return try (JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any])!
} catch {
some bla bla
}
}
return nil
}
The return dictionary should count 3 elements inside when I pass my JSON string, and it does.
I can then change of some variables (Double) which are 0 until now and give them the values of min max and Step from the "y-axis-data" key of my dictionary, using {"min":0.0,"max":1000,"Step":100.0} as a dictionary it self. Works fine.
My trouble comes when trying to initialize other atributes:
self.my_view!.x-labels = (jsonToDictionary!["x-labels"]) as? NSMutableArray
my_view has already been initialized as UIViewCustomClass(frame: someFrame)
myview.x-labels is an NSMutableArray and it is initialized as nil. After executing that line of code it is still nill, of course myview.x-labels.count is nil. if I do it this way:
self.my_view!.x-labels = (jsonToDictionary!["x-labels"]) as! NSMutableArray
I get a warning :
Treating a forced downcast to NSMutableArray as optional will never produce nil.
It then crashes on runtime with this error:
Could not cast value of type '__NSArrayI' (0x110ed5448) to 'NSMutableArray' (0x110ed4598).
of course the exact same thing happens with "y-values"
What is the right way to do this?
It was because your json!["x-labels"] is implicitly treated as NSArray, so you somehow had to do a "double-force-cast"
// get the converted json
let j = jsonToDictionary(jsonString: dict)
// double cast
let m = (j!["x-labels"] as! NSArray).mutableCopy() as! NSMutableArray
Result:
I think, JSONSerialization class converts into Array, and then Swift cannot cast Array to NSMutableArray. You can do this (Swift4):
let array = (jsonToDictionary!["x-labels"]) as? [Int]
if array != nil {
self.my_view!.x-labels = NSMutableArray(array: array!)
}

swift core data executeFetchRequest always crash with propertiesToGroupBy

i am having a problem with executeFetchRequest when i use propertiesToGroupBy. I need to fetch dates(saved as string) but similar dates should be avoided, so that i get unique date array. below is the code i used
var arrDates: NSArray = NSArray()
let fetchRequestDates = NSFetchRequest(entityName: "Schedule")
fetchRequestDates.propertiesToGroupBy = ["date"]
fetchRequestDates.propertiesToFetch = ["date"]
fetchRequestDates.resultType = .DictionaryResultType
do {
let result = try managedContext.executeFetchRequest(fetchRequestDates)
arrDates = result as NSArray
} catch {
NSLog("Failed to fetch dates: \(error)")
}
the execution doesn't go further
let result = try managedContext.executeFetchRequest(fetchRequestDates)
and causing SIGBART. If I comment
fetchRequestDates.propertiesToGroupBy = ["date"]
it works but will fetch duplicate dates too. what is the work around?

Delete core data entry cannot invoke 'deleteObject' with an argument list of '([AnyObject]?)'

When I try to remove a core data entry from my project, I bump into the error
cannot invoke 'deleteObject' with an argument list of '([AnyObject]?)'
I think this basically asking me to cast the object but when I try this, I get the same error. My code is as follows:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context = appDelegate.managedObjectContext
var error:NSError? = nil
let request = NSFetchRequest(entityName: projectEntityName)
let pred = NSPredicate(format: "projectName = %#", projectName)
request.predicate = pred
let objects = context?.executeFetchRequest(request, error: &error)
if let objectList = objects {
for thisProject in objectList {
thisProject.deleteObject(objects)
}
}
appDelegate.saveContext()
Can anyone help with this?
You have your variables mixed up. deleteObject is a method of the NSManagedObjectContext, and you pass the object to be deleted as the parameter:
if let objectList = objects {
for thisProject in objectList {
context!.deleteObject(thisProject)
}
}
Use as.
thisProject.deleteObject(objects as! [type])

Issue: Saving Json data to Core Data

I am trying to learn how to read data from a blog and save it to core data but the save is not working as intended. There are 4 blog entries and I expect to have 4 different entries in core data. Please see the code below and let me know where i went wrong:
let task = session.dataTaskWithURL(url!, completionHandler:{(data , response, error) -> Void in
if (error != nil){
println(error)
}else{
var jsonResult:NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSDictionary
var managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext!
let newBlog = NSEntityDescription.insertNewObjectForEntityForName("BlogDetails",inManagedObjectContext:managedObjectContext) as NSManagedObject
var dateFormater = NSDateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd HH:mm:ss" //"yyyy-MM-dd"
var readRequest = NSFetchRequest(entityName: "BlogDetails")
for var i = 0; i < ((jsonResult["items"] as? NSArray)?.count)!; i++ {
var item = jsonResult["items"]![i] as NSDictionary
var blogAuthorDirectory = item["author"]! as NSDictionary
var blogAuthor = blogAuthorDirectory["displayName"] as NSString
var blogAuthorImageDirectory = blogAuthorDirectory["image"] as NSDictionary
// concatenate String
var blogAuthorImage = blogAuthorImageDirectory["url"] as NSString
var blogAuthorImageUrl = ("https:" + blogAuthorImage)
var title = item["title"] as String
// convert date from String
var publishedDate:NSDate = dateFormater.dateFromString(stringTmp as NSString)!
// read content
var content = item["content"] as? NSString
// Write it to core data
newBlog.setValue(blogAuthorImageUrl, forKey: "image")
newBlog.setValue(blogAuthor, forKey: "author")
newBlog.setValue(title, forKey: "title")
newBlog.setValue(publishedDate, forKey: "publisheddate")
managedObjectContext.save(nil)
var results = managedObjectContext.executeFetchRequest(readRequest, error: nil)
println(results)
}
}
})
task.resume()
following are the entries in result in the last iteration:
1. It only has 3 dictionary counts out of which values in first 2 count has all items as nil. how is that being generated?
2. With every iteration, it overwrites value in last count and doesn't append it.
Thanks for your help.
If you want to append objects to your CoreData, you need to do insertIntoManagedObjectContext before you call the managedContext.save(nil) method.
However, your
let newBlog = NSEntityDescription.insertNewObjectForEntityForName("BlogDetails",inManagedObjectContext:managedObjectContext) as NSManagedObject
is declared outside of your for loop, so probably no new blog created after each iteration.

Swift - Why can I not return an NSNumber or Double data type from this NSDictionary object?

The second line of the code segment below returns an error unless I change the portion that reads "as NSNumber" to "as String". The value returned in rowData["lngID"] is a numeric value. Can someone please explain this to me?
let rowData: NSDictionary = objReport as NSDictionary
let lngReportID = rowData["lngID"] as NSNumber
What I'm actually attempting to do here is take a JSON response and load it into an array of objects as follows. Perhaps there is a better way to achieve this. Any suggestions for a better approach is much appreciated. First, the function didReceiveAPIResults returns the results to the app. Then the function loadReportsIntoArray is called.
func loadReportsIntoArray(pReports: NSArray) {
arrayPoints = []
for (intRow, objReport) in enumerate(pReports) {
// index is the index within the array
// participant is the real object contained in the array
let rowData: NSDictionary = objReport as NSDictionary
let lngReportID = rowData["lngID"] as NSNumber
let lngReportTypeID = rowData["lngTypeID"] as NSNumber
let strOtherTypeName = rowData["strOtherTypeName"] as String
let strDescription = rowData["strDescription"] as String
let dtmFirstReport = rowData["dtmFirstReport"] as String
let dblLat = rowData["dblLat"] as NSNumber
let dblLong = rowData["dblLong"] as NSNumber
let strReportedByUsername = rowData["strReportedByUsername"] as String
let lngReportedByID = rowData["lngReportedBy"] as NSNumber
let lngCommentCount = rowData["lngCommentCount"] as NSNumber
let lngNumLikes = rowData["lngNumLikes"] as NSNumber
let blnUserLikedEvent = rowData["blnUserLikedEvent"] as Bool
var objReport = Report(plngReportID: lngReportID, plngReportTypeID: lngReportTypeID, pstrOtherTypeName: strOtherTypeName, pstrDescription: strDescription, pdtmFirstReport: dtmFirstReport, pdblLat: dblLat, pdblLong: dblLong, pstrReportedByUsername: strReportedByUsername, plngReportedByID: lngReportedByID, plngCommentCount: lngCommentCount, plngNumLikes: lngNumLikes, pblnUserLikedEvent: blnUserLikedEvent)
//arrayPoints.append(objReport)
}
}
func didReceiveAPIResults(results: NSDictionary) {
var success: NSInteger = results["success"] as NSInteger
if success == 1 {
var resultsArr = results["geopoints"] as NSArray
dispatch_async(dispatch_get_main_queue(), {
self.loadReportsIntoArray(resultsArr)
})
}
else {
// Error occurred
}
}
I was able to recreate your error using the following code:
let objReport = NSDictionary(object: "string", forKey: "lngID")
let rowData: NSDictionary = objReport as NSDictionary
let lngReportID = rowData["lngID"] as NSNumber // Error
However, changing the objReport to NSDictionary(object: NSNumber(integer: 0), forKey: "lngID") solved the problem. Therefore, I think your problem is the object stored for the key lngID isn't an NSNumber.
For the solution to this you should look at Kumar Nitin's answer to check you've got a number stored, or you could use the code, they both do the same thing pretty much:
if let lngID = rowData["lngID"] as? NSNumber {
// Do stuff with lngID.
}
In swift, you don't have NSNumber, however you can use the Obj C's NSNumber if need be.
The above code for NSNumber should be as follows if you are expecting a double or float or int. Add a check to ensure the value is not nil, or else it will crash your app.
if let lngReportID = rowData["lngID"] as? Int {
//Do the task required
}