Stepping through Plist and writing - swift

I created a app for personal use to write data into two Plist files from a template in my BundlePath.
was working great until Swift 3 and i'm unsure about passing the index of the template as the key.
for index in 0 ..< number {
var diction = (resultQDictionary?.object(forKey: "Questions"))
print("diction = \(diction)")
//PROBLEM HERE!! - cannot call value of non function type 'Any?!' for dictionaryQItem and dictionaryAItem
var dictionaryQItem = (resultQDictionary?.object(forKey: "Questions") as AnyObject).object(index)
var dictionaryAItem = (resultADictionary?.object(forKey: "Answers") as AnyObject).object(index)
print("dQitem = \(dictionaryQItem)")
//print("this is DI for question = \(dictionaryItem?.objectForKey("Question"))")
//print(dictionaryItem?.objectForKey("Title"))
var cAns = inputSheetObjectArrayKey[index] //c
var quest = questionArray[index]
var title = titleArray[index]
var block = pickerBlock // blockArray[index]
var answerA = answerAArray[index]
var answerB = answerBArray[index]
var answerC = answerCArray[index]
//print("quest = \(quest)")
let trimmedcAns = (cAns as AnyObject).trimmingCharacters(in: CharacterSet.whitespaces)
let trimmedQuest = quest.trimmingCharacters(in: CharacterSet.whitespaces)
let trimmedTitle = title.trimmingCharacters(in: CharacterSet.whitespaces)
//let trimmedBlock = block.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let trimmedAnswerA = answerA.trimmingCharacters(in: CharacterSet.whitespaces)
let trimmedAnswerB = answerB.trimmingCharacters(in: CharacterSet.whitespaces)
let trimmedAnswerC = answerC.trimmingCharacters(in: CharacterSet.whitespaces)
dictionaryQItem.setValue(trimmedcAns, forKey: "CorrectAnswer")
dictionaryQItem.setValue(trimmedQuest, forKey: "Question")
dictionaryQItem.setValue(trimmedTitle, forKey: "Title")
dictionaryQItem.setValue(pickerBlock, forKey: "Block")
dictionaryAItem.setValue(trimmedAnswerA, forKey: "A")
dictionaryAItem.setValue(trimmedAnswerB, forKey: "B")
dictionaryAItem.setValue(trimmedAnswerC, forKey: "C")
dictionaryAItem.setValue(trimmedTitle, forKey: "Title")
dictionaryAItem.setValue(" ", forKey: "FEEDBACK")
}
resultQDictionary?.write(toFile: docsQPath, atomically: false)
resultADictionary?.write(toFile: docsAPath, atomically: false)
}
cannot call value of non function type 'Any?!' for dictionaryQItem and dictionaryAItem - was working great in Swift 2.3 but i'm unsure how to pass in the index. Any help appreciated!

I'd define DictionaryAItem and DictionaryQItem as class objects and use them to manage the Questions and Answers data especially as you seem to have well defined structures.

Related

Retrieve data from Firebase before adding to a map

I'm building an application where a user can store companies information (like name, address, latitude, longitude to a Firebase real-time database).
With that information, those companies are then presented in a map as annotations.
My viewDidLoad is shown below
override func viewDidLoad() {
super.viewDidLoad()
// Definitions
let autenticacao = Auth.auth()
let idUsuarioLogado = (autenticacao.currentUser?.uid)!
let database = Database.database().reference()
let usuarios = database.child("usuarios")
let clinicas = database.child("clinicas")
// Map - User location
self.mapa.delegate = self
self.gerenciadorLocalizacao.delegate = self
self.gerenciadorLocalizacao.desiredAccuracy = kCLLocationAccuracyBest
self.gerenciadorLocalizacao.requestWhenInUseAuthorization()
self.gerenciadorLocalizacao.startUpdatingLocation()
// retrieve user information
usuarios.child(idUsuarioLogado).observe(DataEventType.value) { (snapshot) in
let dados = snapshot.value as? NSDictionary
let emailUsuario = dados?["email"] as! String
let nomeUsuario = dados?["nome"] as! String
let perfilUsuario = dados?["perfil"] as! String
let idUsuario = snapshot.key
let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
print("User profile \(perfilUsuario)")
}
// Clinicas listeners
clinicas.observe(DataEventType.childAdded) { (snapshot) in
let dados = snapshot.value as? NSDictionary
//print("Dados na leitura \(dados)")
let clinica = Clinica()
clinica.identificador = snapshot.key
clinica.nome = dados?["nome"] as! String
clinica.endereco = dados?["endereco"] as! String
clinica.cidade = dados?["cidade"] as! String
clinica.cep = dados?["cep"] as! String
clinica.estado = dados?["estado"] as! String
clinica.latitude = dados?["latitude"] as! String
clinica.longitude = dados?["longitude"] as! String
clinica.urlImagem = dados?["urlImagem"] as! String
clinica.idImagem = dados?["idImagem"] as! String
self.clinicasR.append(clinica)
}
// add annotations to the map
for oneObject in self.todasAnotacoes {
print("Oneobj \(oneObject)")
let umaAnotacao = MinhaAnotacao()
var oneObjLoc: CLLocationCoordinate2D = CLLocationCoordinate2DMake(oneObject.objLat, oneObject.objLong)
umaAnotacao.coordinate = oneObjLoc
umaAnotacao.title = oneObject.objName
umaAnotacao.subtitle = oneObject.objDesc
umaAnotacao.category = oneObject.objCat
self.anotacaoArray.append(umaAnotacao)
self.mapa.addAnnotations(self.anotacaoArray)
}
}
My viewDidLoad is "structured" in 4 main blocks (even though they run in a different order given they are asynchronous):
Definition;
Retrieve user profile;
Retrieve companies information (name, latitude, longitude);
Add annotations to the map.
As those are asynchronous functions, they run in different order and this is what is causing trouble to me.
note: There is still one piece missing here that is to feed all annotations to the variable todasAnotacoes which I'll do once I can retrieve data before triggering add annotation "block".
As annotation info comes from the firebase database, I should only have it executed once the clinicas.observe(DataEventType.childAdded) { (snapshot) in is concluded.
As is today, the sequence Xcode runs is:
Definitions
Add annotations;
retrieve data from firebase with companies details
I've tried adding the add annotation block to the closure, adding a dispatchqueue but none of those really worked. I also did a lot os search in stackoverflow but I couldn't find anything that i can use (or I wasn't able to understand).
So, in summary I need to run the add annotations after retrieving all data from Firebase.
Any ideas on how I could do that?
EDIT 1 - Final code with the suggested updates
override func viewDidLoad() {
super.viewDidLoad()
// Retrieving Logger user data and hidding "add" button if applicable
ProgressHUD.show("Carregando...")
let autenticacao = Auth.auth()
let idUsuarioLogado = (autenticacao.currentUser?.uid)!
let database = Database.database().reference()
let usuarios = database.child("usuarios")
var isUserLoaded = false
var isClinicsLoaded = false
usuarios.child(idUsuarioLogado).observe(DataEventType.value) { (snapshot) in
let dados = snapshot.value as? NSDictionary
let emailUsuario = dados?["email"] as! String
let nomeUsuario = dados?["nome"] as! String
let perfilUsuario = dados?["perfil"] as! String
let idUsuario = snapshot.key
let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
isUserLoaded = true
if (isUserLoaded && isClinicsLoaded) {
self.addAnnotationsToMap();
}
//print("\(usuario.email) e \(usuario.nome) e \(usuario.uid) e \(usuario.perfil)")
}
// Option to code above
/*if Auth.auth().currentUser != nil {
if let uid = (Auth.auth().currentUser?.uid) {
let database = Database.database().reference()
let usuarios = database.child("usuarios").child(uid)
usuarios.observe(.value) { (snapshot) in
let dados = snapshot.value as? NSDictionary
let emailUsuario = dados?["email"] as! String
let nomeUsuario = dados?["nome"] as! String
let perfilUsuario = dados?["perfil"] as! String
let idUsuario = snapshot.key
let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
print("Got here \(usuario.email) e \(usuario.nome) e \(usuario.uid) e \(usuario.perfil)")
if perfilUsuario != "admin" {
self.navigationItem.rightBarButtonItems?.remove(at: 1)
print("Disable + Button")
}
}
}
}*/
// Map - User location
self.mapa.delegate = self
self.gerenciadorLocalizacao.delegate = self
self.gerenciadorLocalizacao.desiredAccuracy = kCLLocationAccuracyBest
self.gerenciadorLocalizacao.requestWhenInUseAuthorization()
self.gerenciadorLocalizacao.startUpdatingLocation()
let clinicas = database.child("clinicas")
// Clinicas listeners
clinicas.observe(DataEventType.value) { (snapshots) in
for child in snapshots.children {
let snapshot = child as! DataSnapshot
print("Clinicas Mapeadas - end")
let dados = snapshot.value as? NSDictionary
//print("Dados na leitura \(dados)")
let clinica = Clinica()
clinica.identificador = snapshot.key
clinica.nome = dados?["nome"] as! String
clinica.endereco = dados?["endereco"] as! String
clinica.cidade = dados?["cidade"] as! String
clinica.cep = dados?["cep"] as! String
clinica.estado = dados?["estado"] as! String
clinica.latitude = dados?["latitude"] as! String
clinica.longitude = dados?["longitude"] as! String
clinica.urlImagem = dados?["urlImagem"] as! String
clinica.idImagem = dados?["idImagem"] as! String
self.clinicasR.append(clinica)
self.todasAnotacoes.append((objLat: Double(clinica.latitude) as! CLLocationDegrees, objLong: Double(clinica.longitude) as! CLLocationDegrees, objName: clinica.nome, objDesc: clinica.endereco, objId: clinica.identificador))
}
isClinicsLoaded = true
if (isUserLoaded && isClinicsLoaded) {
self.addAnnotationsToMap();
}
}
/* NOT IN USE FOR NOW
let latitude = Double(-23.623558)
let longitude = Double(-46.580787)
let localizacao: CLLocationCoordinate2D = CLLocationCoordinate2D.init(latitude: latitude, longitude: longitude)
let span: MKCoordinateSpan = MKCoordinateSpan.init(latitudeDelta: 0.01, longitudeDelta: 0.01)
let regiao = MKCoordinateRegion.init(center: localizacao, span: span)
self.mapa.setRegion(regiao, animated: true)*/
ProgressHUD.dismiss()
}
// add annotations to the map
func addAnnotationsToMap() {
anotacaoArray = []
for oneObject in self.todasAnotacoes {
for oneObject in self.todasAnotacoes {
// print("Oneobj \(oneObject)")
let umaAnotacao = MinhaAnotacao()
var oneObjLoc: CLLocationCoordinate2D = CLLocationCoordinate2DMake(oneObject.objLat, oneObject.objLong)
umaAnotacao.coordinate = oneObjLoc
umaAnotacao.title = oneObject.objName
umaAnotacao.subtitle = oneObject.objDesc
umaAnotacao.identicadorMapa = oneObject.objId
self.anotacaoArray.append(umaAnotacao)
print("Annotation added \(todasAnotacoes.count) - end")
}
self.mapa.addAnnotations(self.anotacaoArray)
self.todasAnotacoes = []
self.anotacaoArray = []
// print("Annotations added 2 - end")
}
}
The second observer in your code is using .childAdded, which means that closure gets called for each individual child node under clinicas. This makes it hard to know when you're done with clinics, so I recommend first switching that observer over to .value, with something like:
clinicas.observe(DataEventType.value) { (snapshots) in
for child in snapshots.children {
let snapshot = child as! DataSnapshot
let dados = snapshot.value as? NSDictionary
//print("Dados na leitura \(dados)")
let clinica = Clinica()
clinica.identificador = snapshot.key
clinica.nome = dados?["nome"] as! String
clinica.endereco = dados?["endereco"] as! String
clinica.cidade = dados?["cidade"] as! String
clinica.cep = dados?["cep"] as! String
clinica.estado = dados?["estado"] as! String
clinica.latitude = dados?["latitude"] as! String
clinica.longitude = dados?["longitude"] as! String
clinica.urlImagem = dados?["urlImagem"] as! String
clinica.idImagem = dados?["idImagem"] as! String
self.clinicasR.append(clinica)
}
// At this point we're done with all clinics
}
As you'll have notice this code now uses a loop to iterate over snapshots.children. So we're processing all child nodes of clinicas in one closure, which makes it much easier to know when we're done.
Now with the above change we have two closures that get called individually, and you have some code that you want to run when both of them are done. There are a few ways to synchronize this code.
The first way is what you've already tried: putting the clinicas.observe block into the closure of usuarios.child(idUsuarioLogado).observe(. Now that the clinics observer uses .value, you'll find that this is much easier to get working.
But I'd like to show an alternative below, where we use two simple flags to determine if both closures are done. For this you will have to put the code that runs after the data is loaded into a separate function, something like this:
func addAnnotationsToMap() }
for oneObject in self.todasAnotacoes {
...
}
}
Now in each of the two closures, we're going to set a flag when they're done. And then at the end of each of the closures, we'll detect whether both flags are set, and then call the new function if we have all data we need.
So at the start of viewDidLoad we define our two flags:
let isUserLoaded = false
let isClinicsLoaded = false
And then at the end of loading the user:
usuarios.child(idUsuarioLogado).observe(DataEventType.value) { (snapshot) in
let dados = snapshot.value as? NSDictionary
let emailUsuario = dados?["email"] as! String
let nomeUsuario = dados?["nome"] as! String
let perfilUsuario = dados?["perfil"] as! String
let idUsuario = snapshot.key
let usuario = Usuario(email: emailUsuario, nome: nomeUsuario, uid: idUsuario, perfil: perfilUsuario)
isUserLoaded = true
if (isUserLoaded && isClinicsLoaded) {
addAnnotationsToMap();
}
}
And similar code (setting the isClinicsLoaded flag) to the other closure.
With these in place, you'll start loading the user data and clinics when the code runs, and then whichever one of them completes last, will call the new addAnnotationsToMap function.
Another alternative is to use a DispatchGroup, which is an Apple-specific construct that can also make this much simpler. Read more about it in this answer (and the links from there): Wait until swift for loop with asynchronous network requests finishes executing

aDecoder crash when try to fetch nil value also encoding decoding enum values not working

I have a class with some properties, and I am using encode while saving and decoder while fetching, but some of the data are not optional, but at the first time when I am fetching it's null so when the decoder is calling and it found nill value it crashes the app.
So what I want is when I fetch the data and if no data found I can set some default value instead of crashing I can solve this by making those properties optional but I don't want that. and also not able to add try catch to make sure it doesn't crash
Please tell what changes should I make to this class and also share some example or links or tutorial that explains everything about encoder and decoder in depth (not some medium article with just overview)
I am new to swift so if you find anything wrong with this class do tell in comments and best ways to do with latest swift
import Foundation
enum AcModeType {
case acModeCool
case acModeDry
case acModeHeat
case acModeFan
case acModeTimer
}
enum FanModeType {
case fanModeLow
case fanModeMid
case fanModeHigh
case FanModeAuto
}
class AcDevice: Device {
var brandId: String?
var variant: String?
var brandName: String?
var acTemperature: Int = 16
var acMinTemperature: Int = 16
var acMaxTemperature: Int = 32
var weatherTemperature: Int = 0
var roomTemperature: Int = 0
var timeTable = [TimeTable]()
var currentAcMode: AcModeType = .acModeCool
var currentFanMode: FanModeType = .fanModeLow
var lastPowerOnTime: Double = 0.0
var isPowerOn = false
var isSleepOn = false
var isTimeTableOn = false
var hasScreen = false
required public init?(coder aDecoder: NSCoder) {
super.init();
brandId = (aDecoder.decodeObject(forKey: "brandId") as! String?)
variant = (aDecoder.decodeObject(forKey: "variant") as! String?)
brandName = (aDecoder.decodeObject(forKey: "brandName") as! String?)
acTemperature = (aDecoder.decodeObject(forKey: "temperature") as! Int)
acMinTemperature = (aDecoder.decodeObject(forKey: "acMinTemperature") as! Int )
acMaxTemperature = (aDecoder.decodeObject(forKey: "acMaxTemperature") as! Int )
weatherTemperature = (aDecoder.decodeObject(forKey: "weatherTemperature") as! Int)
roomTemperature = (aDecoder.decodeObject(forKey: "roomTemperature") as! Int )
currentAcMode = (aDecoder.decodeObject(forKey: "currentAcMode") as! AcModeType)
currentFanMode = (aDecoder.decodeObject(forKey: "currentFanMode") as! FanModeType)
lastPowerOnTime = (aDecoder.decodeObject(forKey: "lastPowerOnTime") as! Double)
if let timeTable = aDecoder.decodeObject(forKey: "timeTable") as! [TimeTable]? {self.timeTable=timeTable}
}
public override func encode(with aCoder: NSCoder) {
aCoder.encode(self.brandId, forKey: "brandId")
aCoder.encode(self.variant, forKey: "variant")
aCoder.encode(self.brandName, forKey: "brandName")
aCoder.encode(self.acTemperature, forKey: "temperature")
aCoder.encode(self.timeTable, forKey: "timeTable")
aCoder.encode(self.acMinTemperature, forKey: "acMinTemperature")
aCoder.encode(self.acMaxTemperature, forKey: "acMaxTemperature")
aCoder.encode(self.weatherTemperature, forKey: "weatherTemperature")
aCoder.encode(self.roomTemperature, forKey: "roomTemperature")
aCoder.encode(self.currentAcMode, forKey: "currentAcMode")
aCoder.encode(self.currentFanMode, forKey: "currentFanMode")
aCoder.encode(self.lastPowerOnTime, forKey: "lastPowerOnTime")
}
required public init() {
super.init();
brandId = ""
variant = ""
brandName = ""
isPowerOn = false;
isSleepOn = false;
isTimeTableOn = false;
hasScreen = false;
currentAcMode = .acModeCool
acMinTemperature = 16;
acMaxTemperature = 32;
currentFanMode = .fanModeLow
lastPowerOnTime = -1;
timeTable = [TimeTable]()
}
}
In your required public init?(coder aDecoder: NSCoder) you're using as! to force cast the results of decodeObject, so this will crash your app if it fails. Instead you could use as? in combination with a default value to unwrap your optionals.
For example:
brandId = aDecoder.decodeObject(forKey: "brandId") as? String ?? "your default string"
This uses ?? which is the nil coalescing operator to provide a default value when the left hand side is nil.
You can do that with Codable protocols in swift. Just have a look at the below link.
https://hackernoon.com/everything-about-codable-in-swift-4-97d0e18a2999
and,
Apple documentation for this:
https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

Using UserDefaults to save a high score in swift

I"m trying to get a high score to save each time the player exits the app, but I'm struggling to get it to work and I'm confused as to where I'm making a mistake.
var gameSettings = Settings.sharedInstance
let HIGHSCORE = "HIGHSCORE"
if gameSettings.highScore < score{
gameSettings.highScore = score
UserDefaults.standard.set(gameSettings.highScore, forKey: HIGHSCORE)
}
if gameSettings.highScore >= score{
gameSettings.score = score
}
let gameOverHighScore = SKLabelNode()
gameOverHighScore.name = "gameOverHighScore"
gameOverHighScore.fontName = "Helvetica Neue UltraLight"
if let HIGHSCORE = UserDefaults.standard.value(forKey: HIGHSCORE) {
gameOverHighScore.text = "HIGHSCORE : \(HIGHSCORE)M"
}
gameOverHighScore.fontColor = SKColor.white
gameOverHighScore.position = CGPoint(x: 0, y: -175)
gameOverHighScore.fontSize = 70
gameOverHighScore.zPosition = 52
addChild(gameOverHighScore)
In if let HIGHSCORE = UserDefaults.standard.value(forKey: HIGHSCORE) {
gameOverHighScore.text = "HIGHSCORE : \(HIGHSCORE)M"
}
you are try find value in UserDefaults not by key HIGHSCORE, but by new value HIGHSCORE of type ANY. If you want to fix it, you can do like this:
if let HIGHSCORE = UserDefaults.standard.value(forKey: self. self.HIGHSCORE) as! Int {
gameOverHighScore.text = "HIGHSCORE : \(HIGHSCORE)M" }
or you can unwrap value in new value with another name. And don't forget to cast value to appropriate type or use
UserDefaults.standard.integer(forKey: self.HIGHSCORE)
Here is a simple example on how to do it:
let firebaseId = user.uid // Variable we want to save
UserDefaults.standard.set(firebase, forKey: "firebase") // Saving the variable with key "firebase"
And now to retrieve:
if let firebaseId = UserDefaults.standard.string(forKey: "firebase") {
print("Firebase ID: \(firebase)")
}
On your code, you are retrieving to HIGHSCORE, and you should be retrieving to something like gameSettings.highScore (Based on what I can infer from your code)

How to write inside a dictionary entry in NSUserDefaults without using temporary variables?

I have this code:
var address = Dictionary<String, AnyObject?>();
address["address1"] = "Here";
address["address2"] = "There";
...
let defaults = NSUserDefaults.standardUserDefaults();
var data = defaults.valueForKey("active_user")! as! Dictionary<String, AnyObject?>
data["address"] = address;
defaults.setValue(data, forKey: "active_user");
defaults.synchronize();
I want to change it into like this:
var address = Dictionary<String, AnyObject?>();
address["address1"] = "Here";
address["address2"] = "There";
...
let defaults = NSUserDefaults.standardUserDefaults();
defaults["active_user"]!["address"]! = address;
defaults.synchronize();
Is this possible? How can I do that?
This is somewhat possible by extending NSUserDefaults to have a subscript. See below:
extension NSUserDefaults {
subscript(key: String) -> Any {
get {
return value(forKey: key)
}
set {
setValue(newValue, forKey: key)
}
}
}
This can then be used like so:
let defaults = NSUserDefaults.standardUserDefaults()
defaults["myKey"] = "someValue"
let myValue = defaults["myKey"]
One limitation is that you won't be able to modify nested collections as you've done in your example. You'll always have to make a manual assignment back to the user defaults object to save something.
// this won't work
defaults["active_user"]!["address"]! = address;
// do this instead
let user = defaults["active_user"]!
user["address"] = address
defaults["active_user"] = user
Edit:
I figured out a way to overload the subscript so you can modify nested collections, with slightly different but very clean syntax. Only works at one level of nesting, but I think it could be taken further. Add this to your NSUserDefaults extension:
subscript(firstKey: String, secondKey: String) -> Any? {
get {
if let dict = value(forKey: firstKey) as? [String: Any] {
return dict[secondKey]
}
return nil
}
set {
if let dict = value(forKey: firstKey) as? [String: Any] {
dict[secondKey] = newValue
setValue(dict, forKey: firstKey)
}
}
}
Then you can do this:
defaults["active_user", "address"] = "some address"
let address = defaults["active_user", "address"]

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.