[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York and L.A. bid on iOS developers, providing them with salary and equity upfront. The average iOS developer gets an average of 5-15 introductory offers and an average salary offer of $130,000/year. Users can either accept an offer and go right into interviewing with a company or deny them without any continuing obligations. It’s totally free for users, and when you're hired they also give you a $2,000 signing bonus as a thank you for using them. But if you use the iPhreaks link, you’ll get a $4,000 bonus instead. Finally, if you're not looking for a job but know someone who is, you can refer them on Hired and get a $1,337 bonus as thanks after the job. Go sign up at Hired.com/iphreaks]
[This episode is sponsored by DevMountain. DevMountain is a coding school with the best, world-class learning experience you can find. DevMountain is a 12-week full-time development course. With only 25 spots available, each cohort fills quickly. As a student, you’ll be assigned an individual mentor to help answer questions when you get stuck and make sure you are getting most out of the class. Tuition includes 24-hour access to campus and free housing for our out-of-state applicants. In only 12 weeks, you’ll have your own app in the App store. Learn to code, it’s time! Go to devmountain.com/iphreaks. Listeners of Iphreaks will get a special $250 off when they use the coupon code IPHREAKS at checkout.]
JAIM:
Hey everybody and welcome to the Episode 103 of the iPhreaks show. Today in our panel we have Andrew Madsen.
ANDREW:
Hi from Salt Lake City.
JAIM:
Alondo Brewington.
ALONDO:
Hello from North Carolina.
JAIM:
I should say Alondo Golden Ticket Brewington.
ALONDO:
[chuckles] Nice.
JAIM:
You know the lottery's fair when all of us don't go because we're such big shots in the iOS community if we get the automatic tickets, but it doesn't work that way. Congratulations Alondo.
ALONDO:
Thank you! I'm excited about going this year.
ANDREW:
Yeah, I'm jealous. I actually ended up deciding not to put my name in. I just decided that - on the off-chance that I got a ticket - I couldn't afford it so no trip for me.
JAIM:
Yup. I put mine in, didn't win. I'll be going to AllConf so I'll be in the area.
ALONDO:
Awesome.
JAIM:
It'll fan out. I have to have an iPhreak meetup so let’s do it out there too
ALONDO:
Yeah, we should definitely do that.
ANDREW:
Yeah, you guys should. What are we talking about today?
JAIM:
Today, we're going to talk about persistence.
ANDREW:
Persistence. What's that?
JAIM:
If you persist at your goals, you will succeed them.
ANDREW:
I do feel like that a lot of times when I'm programming.
JAIM:
If you persist like Core Data, do we just make more crashes?
ALONDO:
Definitely, if you use the [chuckles] stack sample code. [chuckles]
ANDREW:
Yeah. That's an interesting question – but, seriously, what does persistence mean?
ALONDO:
Well, my working definition is basically keeping data that's not – you're not relying on data that's on a remote server is going to live on the device and it's going to live beyond the current instance of the running app.
ANDREW:
I like that. It's not data on a server; it's not data in RAM that goes away when the app quits. It's data that needs to stick around.
JAIM:
What are some common approaches for persistence?
ANDREW:
I know the approach that a lot of brand new iOS developers find and like because it's really easy, and that's to use NSUserDefaults to store everything. [Chuckles]
JAIM:
This is true.
ALONDO:
Okay. You bring up a good thing because, depending on how much data you actually need to persist – the one you need to keep – that's not necessarily untenable solution. It can work. It just depends. I think people go over-board with it. In fact, I came from the reverse. I was using one of the other methods that we'll discuss later and back into using NSUserDefaults – but only because my primary understanding was that was for very small pieces of data that serve preferences and things like that that you won't necessarily need a full-pledged persistence solution for.
ANDREW:
Yeah. My own thought on that is that NSUserDefaults was never intended to be a general-purpose data storage for your app. It's meant to store preferences, and you can use it for things that are not really preferences but don't go over-board. It's meant to handle small amounts of simple data.
JAIM:
What are some things that you should put in NSUserDefaults?
ANDREW:
Preferences are the big one. If your app has settings, that's the place to store them. On iOS that’s true but particularly on the Mac that's true -- because users have access to the stuff stored in NSUserDefaults with the command line tool defaults and also to those gets stored in a standard location in Library/Preferences – in plist. You're violating somewhat of a contract with users by not storing your preferences there, I think.
JAIM:
Definitely a good idea to store your preferences there. What are some examples of things you should not store there? I'll start, passwords.
ANDREW:
That's a good one.
JAIM:
Actually you don't store your passwords unless they're encrypted – but that's a discussion for a different day.
ANDREW:
Yeah, but even then we have an API for that, right? But I've seen people who have their – all of the data that their app needs to store, say it's some user contact management app, so they've got records about people and people's addresses and they've got images for the people on – they're storing all of that in NSUserDefaults. That's not really the way you're supposed to do things, and so I guess what the question is “What's the next step from there?” NSUserDefaults does have the advantage of being really simple. You don't need a lot of code to use it.
JAIM:
It's true. It's in there. It's baked in. You can just use it, set user defaults and the next time you launch your app, it'll be there.
ANDREW:
Right.
JAIM:
That's the benefit of it. Next step, we're talking about storing to a file system, what would you do next?
ANDREW:
Again, for simple stuff, plists can be an option. Make your objects so that they conform to NSCoding and then it's pretty easy to use an NSKeyedUnarchiver to store them to a plist file on disc and read them back. It's a little bit more code that NSUserDefaults but not a whole lot.
JAIM:
We talked about the NSCoding. What is that?
ANDREW:
NSCoding is a protocol that your own classes can adopt and there are just two methods that they need to implement: encodeWithCoder and initWithCoder. When you implement those methods, essentially all you do is store all of your objects' properties off into this thing called an NSCoder that you're handed with those methods.
Then, the nice thing about that is if you’ve got, say an array of objects that are instances of classes that conform to NSCoding, you can use NSKeyedArchiver to store that whole array to disc. You don't have to go through a for loop and pull out some standard representation. The system handles that all for you or NSKeyedArchiver does. So that's the standard way to make your custom classes so that they can be persisted to disc and reloaded or sometimes people say – so they can be serialized and de-serialized.
JAIM:
Okay. I frequently hear people talking about plists formats. How are those related?
ANDREW:
When you store – when you use an NSKeyedArchiver to archive some hierarchy of NSCoding and plain objects off to a file, it gets stored as a plist.
JAIM:
Okay. Is this what's happening when you – say you have a dictionary and you write to file?
ANDREW:
Yeah. It's same thing. So a lot of the system classes are already conformed to NSCoding but there's a little bit of a nuance there. We have the plist classes, right? So you can – I can't remember them off the top of my head there. NSDictionary, NSData, NSString and - help me fill them out. But those can be stored to a plist by default and there are actually some APIs that will say that they only take objects that are in a set of plist classes.
JAIM:
It's a common first error when trying to persist things to a file system. It fails you have no idea why like “Oh, because I tried to save an int or a float or something like that.” And that just won’t work.
Do we have more to take on that?
ALONDO:
I've used plist a bit more recently in an app I'm currently working on. I don't use it as a way to save data though. Basically read-only data at this point was persisted data. Really, the thing that I don't really like about it at this stage – I know I could write to the plist, it's just that I'm using – the data is not changing frequently but if it did, I definitely would consume a service. I move that data to a web service and make API calls and then maybe persist a local cache to that data or a local store and update as needed when that data changes upstream.
ANDREW:
I think the important point about plists is that this is the next step above NSUserDefaults and, in fact, NSUserDefaults uses plists behind the scenes. That's exactly what it's doing but it's the next step beyond that where you have some control over what's being saved. But there's still a lot of help there and the APIs for storing and retrieving that data can be very very simple.
So, what are the downsides? Why not just use Property Lists for everything now?
ALONDO:
Well, I definitely don't think – if you're wanting to get somewhat like relational aspects or using – trying to think of smart advanced features that you would not get with plists. You're definitely like querying the data, things of that nature, and there's definitely some more powerful options available to you if you wanted to something a little more advanced as far as how you retrieve the data and how much of it you want to load every particular time.
ANDREW:
Yeah. With plists, you basically just – assuming you're just using the APIs that are built in for them, NSKeyedUnarchiver essentially – you just load the whole plist up at once. There's no way to just get some piece of it that you want out. You have to load the whole thing up and then in the memory and then find the data you want. There's no API for searching or querying or anything like that.
Plists use xml on disc so another big downside to Property Lists is that they're not very performant. If you've got a huge set of data, particularly if you're storing binary data, you're putting that all in a big xml file. Xml is good for some things but performance with huge data sets is not one of its strengths.
JAIM:
Okay. Its sounds like plist is good for things with complex data except that wouldn't be a user setting – let's say UserProfile you maybe want to store, an image [inaudible] their name so you get complex data but not something you want to store a bunch of data. If you have a bunch of users that store all of your friends, you wouldn't want to put that into a plist – every friend you have into an array in a plist – because you get to load all that in memory to search through it. And that could be a pain. That would be a pretty bad performance. That sound right?
ANDREW:
Sounds good to me.
ALONDO:
Yeah.
JAIM:
If we do have something like that – where we do have a large number of elements that we're creating – friends in our user app, restaurants in a restaurant finder app. What are our options?
ALONDO:
I can think of at least two that I've seen – one I haven't used, one I've used a bit. The first one is using SQLite directly. The second one is Core Data. I don't have experience using SQLite directly at least in iOS but I have – but very first app I worked on, I was introduced to Core Data. It was really like I've dunked right into using it as soon as I started iOS development. I was using it pretty frequently until recently where we don't use a persistence model at all which is really weird. I feel like I'm regressing in so many ways. I am using NSUserDefaults so I was like saying I kind of work my way back down to the simplest solution that you can for persistence.
ANDREW:
Is whatever you're working on not storing a lot of data?
ALONDO:
Actually quite the opposite. We actually consume an API and we just load it in memory and we just keep it there. We're looking right now for a persistence solution and we haven't ruled out Core Data. We're looking at some other solutions but we just haven't come to an agreement on what we want to implement just yet; although I do believe we're probably going to cross that bridge for at least in this current quarter before our next major release.
ANDREW:
Interesting. So you brought up two options that a lot of people use and those are SQLite and Core Data. I wanted to add – I think most people when they SQLite directly, the most common way to do that, probably, is to use a third-party wrapper called FNDB. It's essentially an Objective-C wrapper for SQLite. I want to talk about those two.
I've used Core Data since the API came out in Mac OSX 10.4 and I've used it in really every serious app I've ever worked on I think. That's definitely the one I have the most experience. I've really only used SQLite a tiny bit in an app that I did – that I worked on for a contract gig but I didn't write it so it was an existing code. If you guys have any experience with these two, I'm curious to know what some of the downsides of both approaches are – so pros and cons for both approaches. Why might one want to use SQLite instead of Core Data?
JAIM:
I'm not sure what the motivation is in most cases. I've inherited some apps that use direct SQLite and it may have been just because the developer was more comfortable with the SQL-type approach where you're writing queries. You do have a lot of things where you have magic strings in your app doing your queries for you. It's also valuable if you're doing cross-platform code. One of the apps I worked with had a Windows app, had a Mac app, and so SQLite was one thing that was available on all those platforms – and probably available on Android too. If you wanted to have a cross-platform library, that's an option. We can do that. I did dig really heavily in it and I don't recommend it for most cases. I think there's better approaches but it’s an option and it wasn't terrible.
ALONDO:
One of the biggest ones that I've heard – and again this is coming from some of the more popular apps that have lots of records – was that, for a really fast update across all records like you wanted to update a read flag on tens of thousands of records, that it was a lot easier and a lot faster to do in SQLite versus trying to accomplish that in Core Data.
ANDREW:
So that's one that was held up a lot a while ago although I think they actually added an API for that exact scenario to Core Data in iOS8. I think in iOS8 - might have been in iOS7. I've heard the exact same thing which is that SQLite in certain situations performs a lot better than Core Data.
ALONDO:
In my experience – it's just the number of records has not been an issue so it's not an example where it really applied for me not using Core Data.
ANDREW:
Yeah. That's an interesting point. In general, which is that if you're choosing one of these persistence technologies, you're exact application is important. If you're only storing a hundred records at most, performance is probably going to be fine with any of these solutions. If you're storing millions of records, performance is probably going to be a big deal. You want to eke out whatever you can get.
I think another thing that people – that makes people use SQLite beyond just plain familiarity with it is that you can do really complex queries in SQL and there are a lot of people that know how to do those. Core Data really has a pretty much completely different way of querying your database. In fact, people who are really into Core Data will tell you Core Data is not meant to be a true database like a SQL database. It's not a relational database like that. It's an object graph persistence framework. That's what they say.
JAIM:
Alright. I'm going to call all your bluff there. Everyone says that when you start talking about Core Data. “Hey, it's not an ORM. It’s not a relational mapper.” But then they use all the terms that we use for ORMs. So what's the difference between an object graph and an ORM?
ANDREW:
Hey, don't ask me. I didn't say I knew [chuckles] anything about that. I just told you what people say.
ALONDO:
I’ll actually group that because I've heard that same mantra. In fact the first time, coming from Windows and being a big – a heavy Oracle and SQL server developer, I add they were drilling it to my head and I still haven't seen that difference. It still feels very database and relational to me.
JAIM:
Yup. We're very emphatic. It's not ORM but we treat it like one. I think what people get to is – I'm repeating myself -- but it’s an object graph, it's not meant to be relational. One relationship is fine. I'm not a huge Core Data expert but if you get into many-to-many relationships, it won't give you the functionality that you expect in a SQL server or PostGres or something like that.
ANDREW:
So I was being a little bit silly with the last comment but the problem is I know way more about Core Data than I know about something like SQLite or PostGres or one of the other common database systems; but I think one thing that Core Data does – that it's good at – is, in fact, managing this big graph of objects where objects can have multiple relationships to other objects and those relationships are largely managed for you by Core Data. Keeping that relationships or that relationship graph valid is done for you so if you have an object that has a bunch of children and you delete that object, depending on the rules you've specified, Core Data will take care of deleting all of its children objects for you. It will also take care of – if you have two objects with a relationship to each other and you set that relationship on one of those objects, the corresponding relationship on the other object is automatically set for you by Core Data.
I have the feeling that a lot of the other database systems probably have those kind of features but I don't know if they're the core features of those databases. Those are core features of Core Data.
That's the feeling I get but maybe I'm wrong.
ALONDO:
I think there's some validity to that. I mean, I definitely know – some of the things as far as like how do you want to handle cascading deletes and things like that are definitely available in a something like a SQL server or Oracle in limitation but it's just a matter of where they are. It's not something you necessarily deal with frequently. It’s not at the forefront of sort of the feature set there.
JAIM:
Yeah. It's definitely [inaudible] I've used cascading deletes in there but generally I don't do a lot with it. It’s been a while since I did heavy database work where I’ve needed to but I think that's fair. Another thing that separates the two, an object graph does not need to be persisted. It could be in memory which is one thing you don't really think about when you're doing database.
ANDREW:
Yeah. In fact, we call Core Data a persistence framework and obviously that's how it's most often used to save things to disc. But it can be run entirely in memory and still do all that object graph management stuff without saving to disc.
ALONDO:
Yeah. I definitely think that's one of the things that really interested me when I first started to work with it – I haven't really taken full advantage of it – is that you have a persistence Core Data, you actually have the option of where you want to persist that data should you decide. It's definitely something that I think is as I deepen my knowledge and experience with it, I definitely try to take advantage rather - I can't think of a case of the top of my head – it's one of those nice to have features though. I like that in the way that the solutions are architected.
For me, the biggest thing right now in working with that is learning a better way of managing the data that’s available and accessible – the main context -- and start to take advantage of these additional contexts now in the later revisions of Core Data I have access to and implement it properly because I've run into some problems before.
ANDREW:
That's actually an interesting point and one that a lot of people hold up as one the big problems with Core Data which is that's it really a pain to use in a multithreaded environment. Especially in the olden days that was really true because there was not really – there was no API level support for multithreading in Core Data. There were these rules. You could use Core Data on multiple threads but you have to follow these really strict rules and API didn't give you any help.
That's not true anymore. They’ve added API now for having a multiple contexts on different queues, really. They've made things much much better and easier for doing multithreaded Core Data. It is possible to use Core Data from multiple threads now but it’s still tricky and I think there's some other persistence solutions that have come out that makes some of that easier. That’s one thing to think about when you’re choosing a persistence solution.
One thing that I always like to point out about Core Data that I think is overlooked – and I think it’s particularly overlooked by iOS developers because I think it’s less common they need this feature than OSX developers - Core Data, as part of its Object Graph management stuff, has complete Undo support – Undo/Redo support completely for free. If you have UI that’s creating Core Data objects and changing their properties and all that, it’s trivial to hook up your Edit/Undo menu to your Core Data managedObjectContext and just have Undo/Redo support work without you writing any code. You definitely do not get that free with other persistence solutions. For me, that’s actually a big one.
ALONDO:
You just made me break out into a big CoolAid smile because one of my apps, that is a big big headache. I have to revisit it in an update and one of the problems is I actually walk the user down a trail of changes particularly with additions with some of dependent objects. A lot of times a user will cancel all of those changes and I’d love to be able to roll those back. Are you saying that I can do that like as a transaction per se?
ANDREW:
Yeah. If you look at the NSUndoManager API, really, all that Core Data does is it creates and exposes an UndoManager – an instance of NSUndoManager to you. Most often you just hook that up to the menu or whatever – if it’s in an iOS app, you add an Undo button. You could also use that programmatically to roll back changes. I’ve never done anything more than just hooking it up to the UI in a really simple way but I don’t think there’s any reason at all why you couldn’t do stuff that’s much more sophisticated. In fact, NSUndoManager has an API for undo groupings and you can also disable/enable undo registration which is something I’ve used.
I think what you could do is to create a grouping. When they start this flow or whatever it is that you’re doing – I’m assuming you have a series of UI that they walk through – you could start a group at the beginning and then whenever the cancel, you’ve got this whole group of actions that they’ve taken and you can undo them all at once. At least I think that should work and it would be quite a bit simpler than having to manage that all yourself. I think that can be a really powerful feature that doesn’t get discussed often enough.
ALONDO:
Awesome.
ANDREW:
Another thing Core Data has that doesn’t get talked about a whole lot and is maybe not useful to other people but it can use different stores for its backend. Most often I think people use the SQLite store but there’s also a binary store. On OSX, there’s an xml store which can be nice for debugging anyway. You can write your own custom persistence store. If you want to have your Core Data stuff gets stored in your own custom file format or possibly even send it to a web API or something like that, that’s all possible.
JAIM:
I’ve got a new open-source library idea. You got a Core Data wrapper backed by NSUserDefaults. What do you think? [Chuckles]
ANDREW:
Yeah. You should do it Jaim.
JAIM:
Throwing it out there. Anyone can take it and round with it. Just give me credit. Actually no [crosstalk].
ANDREW:
Don’t, don’t.
ALONDO:
You don’t get credit for that.
JAIM:
If you do this, it wasn’t me. I will deny anything under oath but that’s interesting. The typical approach for doing Core Data is the SQLite back and that’s what most of us are talking about.
Have any of you run into projects or done it in different implementations of it?
ANDREW:
I haven’t written a custom implementation but I did do – story time - my first Core Data app which is an app that I still sell called Aether is a document-based app on the Mac. I didn’t really know anything about any of this when I started and so I chose the xml store type because I thought “Oh, xml. It’s nice.” and I could open them up in a text editor and see what was going on. That actually worked great for a while but I had all the problems that we talked about with plists where once you got up to a few thousand records, performance started to get really slow. Particularly, it started to get really slow for searching. If you wanted to search through the records in a document, that just took forever.
The cool thing about it was the switching to SQLite. It’s like a one line code change and then suddenly just worked. I didn’t have to change anything else that I did in the code. It was like – when I set up the persistence store, tell it I want to use SQL instead of xml, everything else worked fine. I got a huge performance boost too.
JAIM:
For free? Okay. Here's a consulting tip. You start up with your app in xml.
ANDREW:
Yeah, right.
JAIM:
It felt so slow then you're like “Oh! I'm a genius. It doesn't take me a week to fix it.” and go off and go on vacation or something in bail out for the whole week.”
ANDREW:
Actually.
JAIM:
Just saying. I'm full of bad ideas today.
ANDREW:
Well, unfortunately, in that case, I was paying myself - my standard self-employment contract rate of 15 cents an hour to work on my own app.
JAIM:
Here we go.
ALONDO:
Oh wow.
ANDREW:
So.
JAIM:
If anyone wants say stock tips, that's not the thing I should be doing [chuckles] – giving out today. [chuckles] Xml is one of the stock options for Core Data backing, are there other ones that Apple gives for free.
ANDREW:
There's the binary store type.
JAIM:
Okay.
ANDREW:
I can't really say anything about that. I don't know why you would want to use it.
ALONDO:
Yeah. I remember once hearing a case that someone made for binary. I can't remember off the top of my head. It sounded good at that time when I heard it though. That's all I can say right now.
JAIM:
It would probably be a bit faster than xml but not by a ton. You probably still have to load it all in the memory so I can't really think of a clear use case where I would say that’s the way to do it.
ALONDO:
Yeah.
ANDREW:
Yeah.
ALONDO:
Agree.
ANDREW:
I really don't know.
JAIM:
Unless you had a binary data format that you're used to using. You can download it from a web service that you already have like “Oh, we want to read on this binary data format.”
ANDREW:
Sure but that binary store I'm talking about is Core Data's own binary store. It's some opaque – I don't know - who knows what the format is. It's defined by Apple and I don't think its public.
JAIM:
Oh, okay. Yeah, I don't know. Alright, it will stomp the iPhreaks. We have no idea why anyone would use a binary store.
ANDREW:
There's also the in-memory store. We touched on that but you can just have Core Data store everything in memory and not use the whole persistence part of it.
JAIM:
What are some of the advantages of using Core Data just in memory without persisting it?
ANDREW:
It should be really fast because it doesn't have to hit the disc. If you're using for data that – you just want the object graph management stuff for data. You're not actually storing to disc or maybe you're even storing it to disc later in your own format, you could use the in-memory store for that. Of course, the disadvantage is all of your data is in memory all the time. In general, memory usage is going to be worse.
JAIM:
Are there any provisions for preventing a crash if you load too much stuff in memory?
ANDREW:
It's a good question. I don't know. I've never used in-memory store.
ALONDO:
Yeah. You don't have to – it seems that you'd really have to be trying to take advantage of some of the features like the object wrap because I can understand why you would do an NSManagedObjects versus just having a bunch of NSObjects loaded in memory.
Andrew:
Well, unless you want the relationship management or Undo support or something like that.
ALONDO:
Okay.
ANDREW:
That's the only thing I can't think of. Like I said, I've never actually used the in-memory store.
JAIM:
What are some of the big headaches people encounter when trying to do Core Data the first time?
ANDREW:
Let's see. Multithreading is a big one. It's a little bit tricky although that, again, has gotten better.
JAIM:
It's gotten better with iOS7?
ANDREW:
Actually, iOS5 I think was the first one. They added some of these what we call modern APIs. They've been around for a while now. The other thing that I think that trips people up with Core Data – that really is weird – is that objects that are Core Data objects or subclasses of NSManagedObject. They're not – they are regular Objective-C objects but they're not exactly like a normal NSObjects subclass. The big one regarding multithreading is that if given a Core Data object is in a certain ManagedObject context, you can't access that object. You can't even read its properties from a thread other than the correct one – other than the one that's associated with its context.
So, it's in a multithreading environment, it’s weird that you have these objects that even reading properties from them at all – period – is just not thread-safe. You have to be on the correct thread or the correct queue. That's a little bit weird. It's a complicated API so I think another thing that gets to people is that there's a lot of what you would call boilerplate just to set up the stack. There's example code in OSX. There are even – when you create an app, there's a checkbox to make it use Core Data. I don't know if – I can't remember – if that's on iOS.
ALONDO:
There was when we created a project and to use Core Data. That's usually the biggest objection I hear is that it’s just too much boilerplate code and you have to watch out for some of that code too because of how it handles exceptions and crashing automatically. Make sure you do not use that.
ANDREW:
Yeah. That's the other thing. You get this boilerplate code from Apple and it's really not quite right, you know? You're not going to know that so you go out and find somebody else has got their version that fixes these problems and whatever. That's not exactly beginner-friendly.
JAIM:
What exactly are the problems with the boilerplate code?
ALONDO:
There's a lot of it for starters. I think just learning – when I was first introduced to it, I really was intimidated by the entire stack. It just seemed to be a lot of moving pieces when you first get started. When you're talking about just a simple object model that you want to create news, you're not really thinking in terms of all the internal plumbing that you need to create in order to do that.
You get used to it but it definitely is intimidating at the outset.
ANDREW:
I want to bring up a few other things. Maybe you guys have some experience with them. I'd be interested to know. Lately there have been other persistence frameworks or libraries that have come up that are made by third parties that are starting to get pretty popular. I think Realm is the biggest or the one that I've heard the most about. There's another one called YapDatabase that I've heard recently people talking about. And then, of course, FNDB is a big one. These are – you might call – I think Realm sells themselves as a replacement for Core Data. I've heard some good things about them.
JAIM:
We should do a show on Realm.
ANDREW:
Yeah, we should.
JAIM:
I wonder if we could set it up next week, maybe.
[chuckles]
ANDREW:
We’ll have to see what we can do.
JAIM:
Next week on the iPhreaks, we're talking Realm. Actually that's true and that is a good idea. There's also a CouchDB?
ANDREW:
Yeah. That's right.
JAIM:
For no SQL-type approach which I haven't used heavily but – or I haven't used well in iOS – but they've got their own backing stores. You do have different options. Are there any pros and cons you're aware of with the different solutions?
ANDREW:
I should have done my research better. I think Realm is supposed to just be a lot simpler and easier to use than Core Data. Another thing about it is it's cross-platform. They have Android and iOS versions which can be a big deal for a lot of people that are developing their apps for both iOS and Android and want to be able to share data back and forth or even – it's hard to share code because you got to write it in C++ basically. That can be a big one.
I get the feeling that Realm makes some of the multithreading stuff easier although I don't really know. I guess we have a lot of questions for our episode next week.
JAIM:
Yeah. I'm only PowerPoint-familiar with Realm but it seems like it does more proper ORM-type functionality – getting objects to a database and back in a reusable fashion. I'm not sure but we'll find out. I'm looking forward to that episode. That will be cool to learn about.
ANDREW:
We can maybe see if we can do an episode about YapDatabase too because that's another one that I've heard some people that are now huge vocal proponents of this thing. I'd like to find out more about it.
There's a whole part of persistence that I think is relevant to a lot of iOS developers that I'd like to touch on a little bit and that is the – I think these days most iOS apps are consuming some web API, some REST API. Often they'll pull a bunch of data down and you want to put that into some persistent stores so that you don't have to hit the network for all that data every single time the app launches.
What about actually getting data from – so you've got this JSON API and you put it in to some persistence store. How do you do that? How do people tend to do that?
JAIM:
My basic approach – generally, I'm getting the data and manually mapping it and put it in Core Data which gives me control over what's happening. There are other approaches. We can do that. I know RestKit has a way you can wire up your Core Data to your RESTful API calls and it's all one big solution. You can get your git from your API and it'll actually end up in your data model or in Core Data.
Does it use the best algorithm for doing that? It's kind of naïve. It just goes through everyone. Does it insert each time? At least the last time I looked at it did. I know Mattt Thompson, the person who did AFNetworking, they've got a different solution which does a similar thing. It's more '”componentized” where you can break out different parts. But for the most part, I do it manually. Just do in code and if needs to go to Core Data, goes to Core Data but if not, I do other things with that.
A lot of the apps I worked with aren't using Core Data really heavily. I think it's – if you can get away with it, it’s an element of complexity that you can improve your app with. A lot of the Core Data apps I worked with have crash problems just from random things. Not that you're doing anything wrong but I guess things where you get crashes in apps I'm working with. I got the crash letter support for the app I'm working with versus some other apps by the same client. We're at a hundred percent crash-free users. Thumbs up. We're still in beta but still [chuckles] that's easy for not doing Core Data.
ANDREW:
Yeah. I must admit that I'm actually a big Core Data fan. I think the problems with it are mostly over-blown but the one app at Mixed in Key where I'm in-charge of our crash report – Star Crash Triage – the only crash we have right now is a Core Data crash. It only comes in. We only see one a week or something like that. It's not a major thing but that makes it really hard to track down.
I'm quite convinced we are doing something wrong but I have yet to figure out what that is. I must admit that is frustrating to have this crash that is going on because Core Data is complicated and we're doing something wrong and yet it's very difficult for me to figure out what that wrong thing is.
ALONDO:
Yes, I agree with you Jaim. I'm using – mostly on the apps I've worked on that use Core Data, I do manual mapping. The only time that I went in to crashing issues is if something has changed on the data that's coming from the API. It's usually something very small. In your head there was an issue before I worked in the last year with regards to changes in iOS8, but mostly something in the data that comes down and in that manual conversion may cause something to blow up.
JAIM:
That leads to the point to something I wanted to talk about with Core Data. If you're using a database: SQL server, PostGres and you change the data. You run your script if you’re doing something like Rails, you run a migration to change your database. How do we keep track of Core Data changes when there are data model changes?
ALONDO:
You got the different model versions and you can do the model, you can do – you can set the automigration. I'm only using it for simple migration and it's worked pretty well. Usually I'm only adding another entity, might add or change a couple of attributes - nothing major. So I don't know how well the automigration works when you step outside of additions and maybe a simple remove or name change on an attribute.
ANDREW:
Yeah. There's this support for light-weight migrations where Core Data can infer your changes. You don't need to tell what they were. But it's limited to pretty simple changes like adding a property that wasn't there before and that kind of really simple thing. There's also support, though, if you – even for huge changes, you can do migration. You have to do more work than that but Core Data has API built in where you can migrate from one data format to another. That can be really useful because it’s that app that never changes its data model. It's pretty rare, right? A lot of times, adding a new feature means you need to store some new data or store data differently or something like that and so migration support is important.
JAIM:
So when do these migrations happen? You do this and you update the app. Does it happen when the user installs the app for the first time or updates it?
ANDREW:
No, it happens the first time they try to load or your app tries to load up some data that was saved using the old model. Say they have version 1.0 and they had a bunch of data they saved and then they update to 2.0 and they launch it. As soon as your code tries to load the old data that was stored in 1.0, it will be migrated. Of course, that migration can be automatic for simple changes like we said but they give you hooks so that even if it's not – can't be automatic, you get some pretty easy hooks to do the migration whenever that's updated or whenever old stores opened.
There's even support for doing – it takes a little bit more work - but there's even support for doing migration across multiple versions. So maybe they use JABPACK in 1.0 – they never updated 2.0 and finally they updated 3.0 and you've changed it twice - you can actually do that migration from 1.0 to 3.0.
JAIM:
Does that do it interactively through each different one? Or does it run them all together somehow?
ANDREW:
Well, there are multiple approaches. Depending on the changes that you've made again, you can go from – for complex mappings – if you do this, you create something that's a migration map. I think it's called migration mapping, model mapping or something like that that tells Core Data how to migrate from the old version to new version. You could create a mapping model that went from version 1 to version 3. In addition to the one that goes from version 2 to version 3. Then it can do it in one pass. You could also do incremental migration where you go from 1 to 2 and the 2 to 3.
JAIM:
Very cool.
ANDREW:
Both approaches are possible.
JAIM:
Is there anything in persistence that we should get to before pick time?
ANDREW:
I feel like we've talked about a tiny little bit of this subject and yet we've covered everything I want to cover.
ALONDO:
Yeah. I think anything else would probably require a deeper dive into one of those areas like maybe a deeper dive into Core Data or of course the upcoming Realm.
JAIM:
Very cool. Alright! Let's get to the picks. Alondo.
ALONDO:
Okay. I have two picks. I hope I don't step on anyone else.
JAIM:
If you go first, then [crosstalk]
ALONDO:
I came across a recent blog post – I think it’s from last month – from Marcus Zarra on The Syndicate MartianCraft blog on the Core Data stack. He talks about some updates in the focus of taking advantage of the new NSManagedObjectContext design approach he has. I've been reading throughout – I've gone through it once, actually twice now. Definitely, it's helped me think through on how I want to approach my rewrite of my Core Data app.
The second one is something I just actually found. Thanks to you Andrew. The NSHipster article by Delisa Mason on NSUndoManager. Again, it’s a good resource as I can see how I can approach this entire approach to creating a transaction – allow my users to add some objects and see the best way I could unroll back if they do change their minds or something happens.
Those are my two picks.
JAIM:
Very cool. Andrew.
ANDREW:
I've only got one pick today and that's the Lytro Camera. Woot was having a DL where you could get the first generation Lytro for $60. It's normally $400. I got one. It's still a few years old and I'm sure they're trying to clear them out that's why I got it so cheap. But it's still fun to play with. It's a camera that instead of taking pictures like a traditional camera, it actually stores the – it can detect and store the direction of the light that’s hitting it comes from so it records light rays instead of just light coming into it. That makes – so that the focus on the picture is not determined at the time you take the picture. You can change the focus later on the fly. It's cool. I'm having fun playing around with it. Unfortunately the deal is done but the technology is cool. They actually have a newer model that's more like an SLR. It's kind of more high-end professional served camera. Also much more expensive though.
That's my pick.
JAIM:
Very nice. I've got one pick. It's more of a life hack. I've been drinking coffee most every day since I was about 15. Wait up McDonalds across the street from our high school so I'd stop by there. I had a pretty serious caffeine tolerance going for a while and I read a life hack that --- actually when you first wake up which when I would first start drinking coffee; you don't really need that much.
You get a dose of cortisol just from waking up. The sun's coming up. You're doing whatever you're doing. I said “Okay. I’m going to not have coffee the first thing in the morning and wait an hour or two.” It has actually helped quite a bit so I'm drinking a lot less coffee. I didn't really have a problem with – I didn't feel bad or anything but I actually feel better drinking a little bit less caffeine, feeling a little bit of my energy lasting throughout the day. If you're looking to back off a little bit with your caffeine consumption, just start drinking later in the day. It works out because you get a boost of the cortisol just from waking up and being up.
That's my pick.
That does it for the picks. If you want to support the show, we've created some T-shirts that are available. To show all your support - we have had run into some financial troubles. Andrew has been by the freeway of the sign saying, “Will code for a WWC ticket” [chuckles]. We really need your help to get these T-shirts filled so Andrew can get his ticket next time. But, hey, you can go to teespering.com /iphreaks and get a T-shirt. I've ordered one. I got the long sleeve one. Anyone – Andrew, did you get the short sleeve?
ANDREW:
I got the short sleeve – the standard one. I'm actually really excited about this. This is the first time we've done T-shirts for iPhreaks. I know Chuck's done them for some of his other shows and I'm excited to have an iPhreaks T-shirt to wear. As of this show, you have six days left to buy them.
Time is running out. Hurry and go buy your iPhreaks T-shirt.
JAIM:
This is your last chance. Help people like Andrew to get into the things they need to do.
ANDREW:
Yeah, before I get evicted.
JAIM:
Right. So I’ve got mine. I’ll probably be wearing it in AllConf. So, I'll be down there. Alondo?
ALONDO:
I'm ordering as we speak.
JAIM:
He's ordering as we speak. He'll have it at the Big Conference so if you find one of us say “Hi.”
That's it for our show. Next week we’re going to talk about Realm and we'll see you all next week.
[This episode is sponsored by MadGlory. You've been building software for a long time and sometimes it gets a little overwhelming. Work piles up, hiring sucks and it's hard to get projects out the door. Check out MadGlory. They're a small shop with experience shipping big products. They're smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter @MadGlory.]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit cachefly.com to learn more]
[Would you like to join a conversation with the iPhreaks and their guests? Want to support the show? We have a forum that allows you to join the conversation and support the show at the same time. You can sign up at iphreaksshow.com/forum]