Saving Firebase snapshot array to NSUserDefaults












1














I am using Swift to retrieve data from my Firebase database. When the user first logs in, I'd like to save the 'places' from my Firebase snapshot as a UserDefault.



static func getAllPlaces(){

databaseRef = Database.database().reference()

databaseRef.database.reference().child("places").observe(.childAdded) { (snapshot: DataSnapshot) in

if let value = snapshot.value as? NSDictionary {

let place = Place()

let id = value["id"] as? String ?? "ID not found"
let title = value["title"] as? String ?? "Title not found"
let type = value["type"] as? String ?? ""

place.id = id
place.title = title
place.type = type

DispatchQueue.global().async {
// Something here to append place data to UserDefaults?
places.append(place) // appends to NSObject for later use
}
}

}
}


The current code works fine - I just need to add something to get it stored so I can grab it later.



Bonus question: I am storing a good few hundred snapshots in the Firebase database. The reason I want to store them on the device is so that the user doesn't have to keep downloading the data. Is this a good idea? Would it take up a lot of memory?



Any help would be appreciated.










share|improve this question
























  • Limit yourself to one question per post please. If your bonus question is a new question, put it in a new post. But note that you might want to do some profiling of your app yourself before doing that.
    – Frank van Puffelen
    Nov 22 at 19:48


















1














I am using Swift to retrieve data from my Firebase database. When the user first logs in, I'd like to save the 'places' from my Firebase snapshot as a UserDefault.



static func getAllPlaces(){

databaseRef = Database.database().reference()

databaseRef.database.reference().child("places").observe(.childAdded) { (snapshot: DataSnapshot) in

if let value = snapshot.value as? NSDictionary {

let place = Place()

let id = value["id"] as? String ?? "ID not found"
let title = value["title"] as? String ?? "Title not found"
let type = value["type"] as? String ?? ""

place.id = id
place.title = title
place.type = type

DispatchQueue.global().async {
// Something here to append place data to UserDefaults?
places.append(place) // appends to NSObject for later use
}
}

}
}


The current code works fine - I just need to add something to get it stored so I can grab it later.



Bonus question: I am storing a good few hundred snapshots in the Firebase database. The reason I want to store them on the device is so that the user doesn't have to keep downloading the data. Is this a good idea? Would it take up a lot of memory?



Any help would be appreciated.










share|improve this question
























  • Limit yourself to one question per post please. If your bonus question is a new question, put it in a new post. But note that you might want to do some profiling of your app yourself before doing that.
    – Frank van Puffelen
    Nov 22 at 19:48
















1












1








1







I am using Swift to retrieve data from my Firebase database. When the user first logs in, I'd like to save the 'places' from my Firebase snapshot as a UserDefault.



static func getAllPlaces(){

databaseRef = Database.database().reference()

databaseRef.database.reference().child("places").observe(.childAdded) { (snapshot: DataSnapshot) in

if let value = snapshot.value as? NSDictionary {

let place = Place()

let id = value["id"] as? String ?? "ID not found"
let title = value["title"] as? String ?? "Title not found"
let type = value["type"] as? String ?? ""

place.id = id
place.title = title
place.type = type

DispatchQueue.global().async {
// Something here to append place data to UserDefaults?
places.append(place) // appends to NSObject for later use
}
}

}
}


The current code works fine - I just need to add something to get it stored so I can grab it later.



Bonus question: I am storing a good few hundred snapshots in the Firebase database. The reason I want to store them on the device is so that the user doesn't have to keep downloading the data. Is this a good idea? Would it take up a lot of memory?



Any help would be appreciated.










share|improve this question















I am using Swift to retrieve data from my Firebase database. When the user first logs in, I'd like to save the 'places' from my Firebase snapshot as a UserDefault.



static func getAllPlaces(){

databaseRef = Database.database().reference()

databaseRef.database.reference().child("places").observe(.childAdded) { (snapshot: DataSnapshot) in

if let value = snapshot.value as? NSDictionary {

let place = Place()

let id = value["id"] as? String ?? "ID not found"
let title = value["title"] as? String ?? "Title not found"
let type = value["type"] as? String ?? ""

place.id = id
place.title = title
place.type = type

DispatchQueue.global().async {
// Something here to append place data to UserDefaults?
places.append(place) // appends to NSObject for later use
}
}

}
}


The current code works fine - I just need to add something to get it stored so I can grab it later.



Bonus question: I am storing a good few hundred snapshots in the Firebase database. The reason I want to store them on the device is so that the user doesn't have to keep downloading the data. Is this a good idea? Would it take up a lot of memory?



Any help would be appreciated.







swift firebase firebase-realtime-database nsuserdefaults






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 at 19:47









Frank van Puffelen

227k28369396




227k28369396










asked Nov 22 at 18:47









Ryan

3819




3819












  • Limit yourself to one question per post please. If your bonus question is a new question, put it in a new post. But note that you might want to do some profiling of your app yourself before doing that.
    – Frank van Puffelen
    Nov 22 at 19:48




















  • Limit yourself to one question per post please. If your bonus question is a new question, put it in a new post. But note that you might want to do some profiling of your app yourself before doing that.
    – Frank van Puffelen
    Nov 22 at 19:48


















Limit yourself to one question per post please. If your bonus question is a new question, put it in a new post. But note that you might want to do some profiling of your app yourself before doing that.
– Frank van Puffelen
Nov 22 at 19:48






Limit yourself to one question per post please. If your bonus question is a new question, put it in a new post. But note that you might want to do some profiling of your app yourself before doing that.
– Frank van Puffelen
Nov 22 at 19:48














1 Answer
1






active

oldest

votes


















3














One way to save custom classes/data to UserDefaults is to encode them like this:



let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: place)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()


Then you can decode it like this:



if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
let decodedPlace = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as! Place
}


Updated for swift 4 and iOS 12:



do {
let encodedData: Data = try NSKeyedArchiver.archivedData(withRootObject: place, requiringSecureCoding: false)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()
} catch {
//Handle Error
}

do {
if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
if let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? Place {
//Do Something with decodedPlace
}
}
}
catch {
//Handle Error
}





share|improve this answer























  • Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
    – Ryan
    Nov 22 at 23:22








  • 1




    i updated the answer for iOS 12 and swift 4 @Ryan
    – Arie Pinto
    Nov 23 at 0:45










  • I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
    – Ryan
    Nov 23 at 11:55










  • Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
    – Arie Pinto
    Nov 23 at 11:58










  • Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
    – Ryan
    Nov 23 at 12:11











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436673%2fsaving-firebase-snapshot-array-to-nsuserdefaults%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














One way to save custom classes/data to UserDefaults is to encode them like this:



let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: place)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()


Then you can decode it like this:



if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
let decodedPlace = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as! Place
}


Updated for swift 4 and iOS 12:



do {
let encodedData: Data = try NSKeyedArchiver.archivedData(withRootObject: place, requiringSecureCoding: false)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()
} catch {
//Handle Error
}

do {
if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
if let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? Place {
//Do Something with decodedPlace
}
}
}
catch {
//Handle Error
}





share|improve this answer























  • Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
    – Ryan
    Nov 22 at 23:22








  • 1




    i updated the answer for iOS 12 and swift 4 @Ryan
    – Arie Pinto
    Nov 23 at 0:45










  • I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
    – Ryan
    Nov 23 at 11:55










  • Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
    – Arie Pinto
    Nov 23 at 11:58










  • Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
    – Ryan
    Nov 23 at 12:11
















3














One way to save custom classes/data to UserDefaults is to encode them like this:



let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: place)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()


Then you can decode it like this:



if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
let decodedPlace = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as! Place
}


Updated for swift 4 and iOS 12:



do {
let encodedData: Data = try NSKeyedArchiver.archivedData(withRootObject: place, requiringSecureCoding: false)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()
} catch {
//Handle Error
}

do {
if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
if let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? Place {
//Do Something with decodedPlace
}
}
}
catch {
//Handle Error
}





share|improve this answer























  • Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
    – Ryan
    Nov 22 at 23:22








  • 1




    i updated the answer for iOS 12 and swift 4 @Ryan
    – Arie Pinto
    Nov 23 at 0:45










  • I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
    – Ryan
    Nov 23 at 11:55










  • Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
    – Arie Pinto
    Nov 23 at 11:58










  • Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
    – Ryan
    Nov 23 at 12:11














3












3








3






One way to save custom classes/data to UserDefaults is to encode them like this:



let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: place)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()


Then you can decode it like this:



if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
let decodedPlace = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as! Place
}


Updated for swift 4 and iOS 12:



do {
let encodedData: Data = try NSKeyedArchiver.archivedData(withRootObject: place, requiringSecureCoding: false)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()
} catch {
//Handle Error
}

do {
if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
if let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? Place {
//Do Something with decodedPlace
}
}
}
catch {
//Handle Error
}





share|improve this answer














One way to save custom classes/data to UserDefaults is to encode them like this:



let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: place)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()


Then you can decode it like this:



if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
let decodedPlace = NSKeyedUnarchiver.unarchiveObject(with: decodedData) as! Place
}


Updated for swift 4 and iOS 12:



do {
let encodedData: Data = try NSKeyedArchiver.archivedData(withRootObject: place, requiringSecureCoding: false)
UserDefaults.standard.set(encodedData, forKey: "place")
UserDefaults.standard.synchronize()
} catch {
//Handle Error
}

do {
if UserDefaults.standard.object(forKey: "place") != nil{
let decodedData = UserDefaults.standard.object(forKey: "place") as! Data
if let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? Place {
//Do Something with decodedPlace
}
}
}
catch {
//Handle Error
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 23 at 12:30

























answered Nov 22 at 18:52









Arie Pinto

703614




703614












  • Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
    – Ryan
    Nov 22 at 23:22








  • 1




    i updated the answer for iOS 12 and swift 4 @Ryan
    – Arie Pinto
    Nov 23 at 0:45










  • I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
    – Ryan
    Nov 23 at 11:55










  • Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
    – Arie Pinto
    Nov 23 at 11:58










  • Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
    – Ryan
    Nov 23 at 12:11


















  • Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
    – Ryan
    Nov 22 at 23:22








  • 1




    i updated the answer for iOS 12 and swift 4 @Ryan
    – Arie Pinto
    Nov 23 at 0:45










  • I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
    – Ryan
    Nov 23 at 11:55










  • Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
    – Arie Pinto
    Nov 23 at 11:58










  • Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
    – Ryan
    Nov 23 at 12:11
















Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
– Ryan
Nov 22 at 23:22






Thank you for your answer. I receive this warning: 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead and for the decoder 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
– Ryan
Nov 22 at 23:22






1




1




i updated the answer for iOS 12 and swift 4 @Ryan
– Arie Pinto
Nov 23 at 0:45




i updated the answer for iOS 12 and swift 4 @Ryan
– Arie Pinto
Nov 23 at 0:45












I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
– Ryan
Nov 23 at 11:55




I seem to be receiving this -[Place encodeWithCoder:]: unrecognized selector sent to instance any ideas?
– Ryan
Nov 23 at 11:55












Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
– Arie Pinto
Nov 23 at 11:58




Yes, your Place class should conform to the NSCoding protocol, please refer to this discussion stackoverflow.com/questions/22168753/…
– Arie Pinto
Nov 23 at 11:58












Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
– Ryan
Nov 23 at 12:11




Thank you! I'm nearly there - why does let decodedPlace = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as! Place return <Place: 0x283245c00>? I tried printing decodedPlace.title but it returns nil?
– Ryan
Nov 23 at 12:11


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436673%2fsaving-firebase-snapshot-array-to-nsuserdefaults%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

What visual should I use to simply compare current year value vs last year in Power BI desktop

Alexandru Averescu

Trompette piccolo