Been working on a new version of an app of mine called Closeby that I haven’t touched since iOS 6.
A few thoughts about the process:
- My design taste has come a long way in the last two years. Some features in I remember spending time on that now I can’t imagine why I’d want them. Others I didn’t do then seem obviously necessary and I have no idea why I didn’t.
- I really like iOS 7+ style design.
- I’m a lot better at programming than I was two years ago. It’s not awful, but there’s code in here I’d never have written today, and it’s nice to see than I haven’t stagnated.
- Cocoapods can be a pain in the ass, but it’s still the best bad choice.
Maybe I’ll post some before and after screenshots when I get a chance to work on it more.
Justin Williams recommends that you don’t spend more than ninety days on a 1.0. I’m with Brent that I want to see apps that take more than three months to make, but I still think Justin has the right advice.
Some apps are deep, and there’s no way around the time they’ll take to get right. Coda comes to mind. Overcast might too. A majority though — especially on iOS — are really all about one thing that makes it unique and everything else falls out of that one thing.
Don’t ship garbage. Do figure out what your app is really about, do the hell out of it, and then start shipping updates.
Alamofire is a new networking library — written in Swift — from the creator of AFNetworking. So far I’ve just read the post on NSHipster about it, but I like what I see. It’s not a value judgment, but something AFNetworking has never quite sat right with me. This looks very lightweight and more like something written to be idiomatic Swift rather than Objective-C in Swift’s clothing.
I haven’t needed to get a unique device ID since before we stopped being able to use
-[UIDevice uniqueIdentifier] until today. Apple added the method
-[UIDevice identifierForVendor] in iOS 6 which totally replaces the old method for any of my needs.
What the method does is give a unique ID for any apps from the same vendor on a given device. The part which might be a little confusing at first is that “vendor” does not mean the same developer account, but instead means any apps where the first part of the bundle identifier (
CFBundleIdentifier) is the same. So
com.collindonnell.myotherapp would get the same identifier, but
com.albinadevelopment.anyapp would not.
This is a really good post lamenting some of the direction Swift has chosen to take:
Gone is the dynamic nature of ObjC; it has instead been replaced by a rigid, generic based type system. I know the world of C++, Java, and C# programmers have rejoiced. Myself, having worked in Visual Studio building tools for .NET and Windows developers for many years and leaving that for the world of Cocoa and ObjC, I am greatly saddened by this turn of events.
Objective-C without the C is a worthwhile goal, but I don’t think anyone was asking for Objective-C without the Smalltalk. I’m still learning and planning to use Swift, but I think dividing into pro-Swift and anti-Swift crowds is probably too narrow of a view. Both languages are better and worse in different ways. It’s going to be up to us to learn those differences.
I’m considering how to handle a pretty big refactoring of how networking code is handled in this app, and after talking to my friend about how he’s handling networking/model object creation in an app he’s working on if the way I’m thinking is a good idea or not.
What my friend described is that he’s using the active record pattern, which roughly translates here to sticking everything into the model, and creating new
NSURLSession objects as needed. I don’t like the idea of needing to create a session object for every request, since the nice thing about
NSURLSession is that all of your requests get to share a delegate, which minimizes repeated code in a lot of cases. I also had an assumption that
NSURLSession has some smarts about managing its own queue of tasks and that creating separate session objects would mess that up. The other thing is that if you had some shared code specific to the service you were talking to, having all of your model objects manage all of their own networking seemed like a good way you might end up with some repeated code later on.
All of that aside, I do kind of like talking directly to the model objects when I need to get things done with them. It feels pretty natural that if you need to do something with SomeObject that you’d talk directly to it. The solution I’m thinking of is to borrow from Core Data and create a class that’s sort of like an
NSManagedObjectContext which manages an
NSURLSession and which I dependency inject as needed. It also gives me a nice place to stick things which are common to the service, so that code doesn’t get repeated across model classes.
For a service called
Foo whose API I need to interact with to create
Bar model objects by ID, I might have a class called
ALBFooAPIContext and do something like this:
[Bar objectWithID:barID usingContext:fooContext completionHandler:completionHandler];
That method could then talk to the context object however it needs to in order to get stuff done. Is this a terrible idea? I’d probably go for calling the context class something else, except I think it’d be a good place to store stuff that is actual contextual to how I’m talking to the service (maybe a
Marco thinks we should all suck it up and learn basic Linux server administration, and that a lot of people are going to get burned by highly abstracted solutions like Heroku and Azure:
There’s a learning curve and necessary integration work for every back-end option, from iCloud and Dropbox to your own colocated servers. AWS, Azure, Heroku, App Engine, Parse, and similar services aren’t free, easy, or automatic. (Neither is “scaling” with them, regardless of what you’ve heard.) Hosted infrastructure is like sync: it has a minimum, unavoidable level of complexity to accommodate. You can’t just check a box or set a BOOL and have it all taken care of for you.
We definitely had the experience at my old company of — even at our pretty small scale — not being able to get what we needed out of it and it getting prohibitively expensive. Marco would definitely know, so I’m inclined to listen to his advice. I’ve been leaning towards hosting my band app on WebFaction with Django instead of Azure, although not due to costs or because I think it’ll be a problem for me to scale, but because Django seems like a better fit for the specific thing I want to do. Maybe I should go all the way and put it on Linode?
Read Marco’s original post.
It’s less nuts to me how much different the source code for Tim Berner Lee’s WorldWideWeb than modern Objective-C than it is how little has actually changed in the past thirteen years. I don’t think it would be any issue for me if I was asked to start fixing bugs in this today.
On Saturday I used the ten hour drive from Portland to San Francisco to listen to all of the first season of The Record by Brent Simmons and Chris Parrish. This seasons topic was “Seattle Before the iPhone.” Since I started learning Cocoa about a year before the iPhone SDK became a thing a lot of the people that they interview are people who I looked up to, and later became friends with, and read the blogs of before I actually knew how I was going to make this into a career, so I think I’m what you’d call the core demographic.
You should check it out. The whole thing is fantastic.
Continued from this post.
My first thought is that it seems like I should be able to generate an RSS feed pretty easily. Maybe I should be looking to what gets RSS feeds contain as guidance for what I return from the feed endpoint.
My second thought is that a completely different approach would be to — instead of returning an array with a bunch of feed item dictionaries created on the server — return a JSON dictionary containing arrays for each item type (songs, shows, videos) and have the logic to display and sort them in the client. That would certainly make the server code simpler. The client could have a sync object that posts a notification when it starts and stops, and then I’d just do a Core Data fetch of all the different types and mash them together into an NSArray in the feed controller.
I’ll still keep it as one API endpoint (instead of calling shows, then songs, etc) since Azure charges me something per API call, it’s the same number of database calls, and it’s easier for dealing with when sync starts and ends on the client.
The reason this appeals to me is that I fear each of the different item types will end up being different enough that I won’t really save that much code on the client by trying to normalize feed items on the server. It feels like it could become kind of restrictive later. It should also make caching easier since it means I can have a one to one match between my server and client data model instead of needing the sort of imaginary “feed item” objects. The last benefit I can think of is that it saves me from having to make another API call every time I want to show a detail item.
The downside is that the RSS feed now would be extra code if I wanted to do that. Not much extra code though, and I was only really thinking of doing it because it seemed like kind of a freebie.
I think I’ll do this unless someone gives me a good reason why I shouldn’t.