Google+ Badge

Thursday, May 14, 2015

I ripped out RestKit and replaced it NSURLSession and Mantle

When I started at my current job I knew I would be doing a lot of REST interaction with the server. I decided to use RestKit as I had seen it mentioned a number of times in various developer forums.

It worked for some time but I finally hit the breaking point and ripped it all out changing 265 to convert them to NSURLSession and Mantle. Was I insane? Pretty much as in the end it did not solve the problem I was originally attempting to address but I am happy with the change.

First off Mantle makes it much easier and cleaner to handle JSON. It is not as easy as GSON on the Android side but it is not too bad. That was a lot of my file conversions and I do find it easier to add a new JSON object due to a new REST call to the server. The one downfall is each of your JSON receiving objects has to be derived from a Mantle class. Objective C does not support multiple inheritance which could make this a very limiting factor for you.

The other area I am not too happy about with Mantle is it handles converting NSDictionary and NSArray to JSON. That means I get a big JSON string from REST and then I use NSJSONSerialization to convert it into a NSDictionary and then convert that via Mantle to Objective C objects. Waste of memory and processing to double convert things. Good thing the JSON data is reasonably small.

The other side was getting rid of RestKit calls. This helped the code a lot. I had one REST call manager class that tried to handle all the server calls with delegate callbacks. Now all the calls are inline where they are called in the code and that code has block processing to handle the results. This lets you see what is going on easier. Plus if it is a PUT call I only have to reference PUT in one line of code whereas I had to do that in three places when using RestKit. Setting up each call in RestKit took a boatload of error prone boilerplate code. I sure as heck don't miss that.

So why not go with AFNetworking? Seems to also be popular but in the end even AFNetworking is using NSURLSession in the end. Apple seems to put together a decent networking package learning from others. One less pod to include in my build and hopefully using the official Apple networking that appeared in iOS 7 will keep me in the safe zone.

On the Android side I am using Volley and GSON, both from Google but not part of the base Android SDK. Volley is very similar to NSURLSession which is good. GSON is easier to work with than Mantle in there is less boilerplate code. If your variable names match the property names in the JSON you get from the server there really is no boilerplate at all. If they don't match a simple annotation gets them to sync up.

So what was the original issue I was attempting to fix? I want to have two type of NSURLSessions going in the code, one to do the normal user interaction processing - they tap something, I make a server request, I get server result and I show new data in the current view or in a new view. The second was to be a background session for uploading video via Amazon Web Services.

I am using AWS but I am using the straight API from them. Yes, there is sample upload in the background code out there and it works when you don't have the other NSURLSession doing other work which really stinks. I want the user to be able to start a video upload and have it run in the background until complete even if they leave my app or turn off the phone screen. Works like a champ on the Android side where I set up a very basic service.

I realize Apple really does not want you do to anything in the background. They trust no one. They do have a new thing that lets you get maybe 10 minutes of time to do some background work. That is one of the things NSURLSession is set to allow. But I just can't get it to work. It will start, send up some % of the video then restart at 0% and do that over and over again. On the simulator, which does not run like a real device, it can get the whole video uploaded never triggering the restart you see on the iPhone or iPad. I have posted a message on Stack Overflow describing this issue but no answers.

I really wish Amazon would handle this for you in their API. Seems like background uploading would be a really common thing for a programmer to want to do with them. Maybe Apple could handle it in their API as well but I doubt that as they are anti-background as it is.

Tuesday, March 3, 2015

iOS battling 3rd party tools

I have been battling various items in iOS over that past week and it is getting really frustrating.

First up I really wanted a dialog with some text entry and a few buttons. They pulled the "custom view" part out post iOS 6 so I found a few GitHub repositories that should solve the problem. First once just did not pan out and the UIView just did not look right. Second one appeared to work OK at first but then it did not play well in iOS 8 in landscape.

Apple decided to change the way you get back height and width of the screen in iOS 8. Previously you always got height and width as if you were in portrait mode. Now they give it back for the current screen orientation. Huge change for programmers. People had height / width swapping code to handle this and you still have to do that for iOS 7 and older.

I fixed the code so landscape worked for iOS 8 on the simulator. Once I ran it on a real device things went to crap again. Extra things being painted and the keyboard popping up really screwed things. Lesson learned - iOS really does not like this sort of popup with editing.

Gut things yet again and go with a UIPopoverController on the iPad and navigation to a UIViewController on the iPhone. Can't say I am super happy with the iPhone version but it works and popping up the keyboard does not screw anything up.

Next up was the menu. iOS 7 has a bug. If you have too many items in a UIActionSheet on an iPhone you can't tap the top most item if it happens to cover the main navigation area. Works fine on iOS 8 but broken on iOS 7. UIActionSheet expects just a few items.

So I found a popup menu that allows up to 9 items per screen and you can swipe to scroll and see more. It is call btSimplePopUP. Now I should have known that someone using two menus - btSimplePopUp and btSimplePopUP - in the same directory structure was going to be iffy. The demo screens look nice though. I put in the code and I get the menu to appear but with a black background. What? It is not blurring out my UIViews, just blanking them out. Then I look for known issues and it turns out the control does not work in landscape which is a requirement for me.

Punt that control. I am now looking at KxMenu which seems to be working in portrait and landscape and takes up a lot less screen space than UIActionSheet. Hopefully it will be the solution.

Lots of GitHub projects lose support. iOS 8 was a big change and it takes some recoding especially with custom controls due to the changes Apple made. Stinks people don't have the time to keep things updated. Even worse when I waste the time trying to get them to work. I need to start looking at the known issues first. Anytime it does not support landscape I am not going to use it. Hopefully they also list if there is iOS 8 support issues as well.

Tuesday, January 20, 2015

MacOS has lost its stability

I do both iOS and Android development thus I have a MacBook Pro has my main development device. I have had one for the last 3 years. Since upgrading to Yosemite it has become the least stable development box I have worked on in a long time.

I leave the machine on and lock / put it to sleep when I am away from my desk. This may be going to a meeting, going to lunch or home for the evening. When I come back from lunch there is a very good chance, 2 out of 5 days, that the machine has rebooted. This also may happen during the day when I am actively working on the machine but that is pretty rare. The sleep cycle seems to be the main trigger.

This is an upper end machine with an SSD drive so the reboot does not take too long but it does interrupt my day and it may happen a couple of times a day, when I come in, after lunch and then maybe after a meeting. Yes, all the programs restart but they don't show up in the same position or with the same data showing. Sublime text appears on screen 1 instead of screen 2. Finder does not have the same tabs open. Chrome might be annoyed in some manner. I will not have the tabs in iTerm on the same directories.

This was never a problem in the past. The MacBook just worked. Now it reboots and has issues with DNS getting lost part way through the day as well. Ping will not find a machine but NSLookup will.

I also have a Dell PC that is used for my Windows activities running Windows 8.1. I leave Outlook, Hipchat, Sublime Text, Chrome and a few other things running on it as well. I do a lot of my graphics work on that machine because Paint.NET is free and pretty darn full featured. We also use TFS for version control and I do that work on that machine along with anything I need to do in Visual Studio including C#. I don't have a massive love for Windows but at least that machine is only rebooting when it needs to do updates, which does occur too often for an OS, but otherwise it is there ready to go.

iOS has become less stable as well. I think Apple needs to stagger the releases instead of trying to do MacOS, iOS and iOS hardware release all at the same time. I bet their QA department is hammered during that yearly cycle and it is really starting to show. I love new and exciting things but they need to be stable. Right now Yosemite is not stable and is highly annoying.

Tuesday, January 13, 2015

Why I have given up on Interface Builder and Story Boards

I just ran into another case where Interface Builder did not allow me to do what I wanted to do and I finally just gave up and pulled everything but the first view controller from the storyboard. This is the story of how I got to this point.

My first iOS app was one of "finish this". Another developer who was no longer with the company had developed the app. I had the job of finishing the app and converting it to Android. I already knew Java and had written an Android app that was in the store. The iOS version used NIBs as this was back in the iOS 4 timeframe.

I continued down the NIB path and converted the app to be universal with special code for iPad layouts. There was special cases for landscape vs. portrait on one of the screens as well. Seemed to work OK but it was a fairly straightforward app.

I worked only on Android apps for a some time before my next position where I did both iOS and Android work again.

The next iOS app I worked on was written by another developer and he used storyboards. Still using the old style layouts with pixel perfect positioning. I kept the storyboards in place seeing some of the advantages of using them and added the iPad storyboard side of things. I liked how much easier it was to get things going, used segues and like the idea of seeing the program flow in a visual designer. Took quite a bit of web research to understand how it all tied together and a lot of clicking on tabs in IB to find all the secret nooks and crannies where you could set things.

I did a couple of other apps for the company that I got to write from scratch. I used the new found storyboards for them as well. Sadly none of these apps went to market as they never finished the server side of the work. Lots of pretty apps to demo at sales meetings but they were just demos.

For my current job I am again getting to write the app from scratch. I am doing the same with the Android side of things. I started out using storyboards and it was time to get into autolayout. Since I have been doing Android work and I have also done a lot of Java desktop work I have a solid understanding of doing layouts that scale.

I dove into autolayout and found it rather confusing. It appears to me to be written in the land of academia instead of the land of real world programming. One layout to rule them all no matter how you have to force things into it. Very verbose in one code only format and very terse in the other. If you do it in Interface Builder then you just have to know how to do things. Click here, Ctrl + Click here, set up constraints, delete them, set them up again, have them conflict, pull hair. Always something wrong and it get really bad when you have a complex layout. For a company that prides itself in UI and UX I must say IB is not a good reflection of that goal.

After fighting it and working with other iOS devs over chat I found Masonry and switched to that. Yes, it is code and not WYSIWYG but I could create complex layouts and have them work. I could do different layouts for iPad and iPhone and follow them logically. I still have storyboard layouts but most of them were empty as the code created the real layout. I was just using them for segues and to see program flow. That was until yesterday.

There I was back in Interface Builder. I just wanted a UITableView to move down one level, to have another UIView as its parent. IB fought me tooth and nail. I could and a UIView to the list but it would not show up under the UIViewController no matter how I dragged and dropped and clicked. I then said screw it and deleted that entire view controller and created a new one where I could re-add the UITableView but then all my segue links broke and all the IBOutlets into the code broke and I would have to do it again for the iPad storyboard and all the work went on and on. Plus Xcode crashed more than once while I was in it doing simple things.

Storyboards end up sucking pretty quickly. There is not enough screen room to see your iPad layouts. You get to see one scene at a time. Sure you can zoom out but the minute you edit something it zooms back in. Just opening a storyboard seems to trigger Xcode into thinking there was a change. If you look in the XML you will see it changed x = 4.0 to x = 3.999999999 or something just as stupid. Everything I did I had to do twice, once for iPhone and once for iPad. The IDE does not tell you if you forget to wire up a UIView to an IBOutlet. Objective C does not care if you send messages to a nil object. Moving a UIView can screw up the whole layout quickly. You can't see all the constraints in one place, you have to look in each level of the layout to see them and they are terse and unrelated to each other. When you try to Ctrl+Drag a UIView into the code you hardly can see anything else on screen.

I gave up. IB was fighting me not helping me. I converted all the code to Masonry and I was able to control that layout exactly. I had to move all the segue processing in code as well. It took me all day to get my code back to where it was before but now I am in control of all of it.

I don't have to do things twice. iPad and iPhone both work from one code base. I may have some if statements in code to tweak layout for iPad but I don't have to double layout it out in a crappy UI editor called IB and I don't have to double connect every UIView to a IBOutlet.

I can move a control around in my layout by changing a few lines of code instead clicking a bunch of times in IB and having it get pissed and redo other constraints.

I can name my controls so when I do get log messages about my layout being screwy I know exactly which UILabel it is mad about instead of guessing.

Another issue that bit me, I fixed, that bit me again and I fixed the right way arose. I needed a second line for the title area on iPhone. iPad has enough horizontal space to not need this. I was using the navigation prompt property which adds a second line of text to the title area. On Android I could use title / subtitle to do same thing but on Android this requires no extra vertical space.

How did this bite me twice? A number of months ago I wanted to add a UILabel above my UITableView but I could not due to same issues that I just covered, I could not get the UITableView hosted by another UIView. Thus I used the prompt property. It worked OK. After the conversion away from storyboards everything in this UIViewController aligned just fine the first time I displayed it but when I tapped a table row and moved to the detail screen then back to the table screen setting the prompt caused the navigation area to grow and it covered up part of my table. Rotating to landscape and back would fix it. I tried all sorts of relayout, needs display, calculation of offsets etc. and could not get it to work. Why autolayout would not stay in sync is beyond me but I got sick of fighting that.

Then I remembered what I originally wanted to do - put a UILabel above the UITableView on iPhone only. Now I am in control as I am using Masonry. Put the UILabel in place and changed all code references from prompt = to promptLabel.text = and I have a working layout the way I originally wanted.

I have no plans use prompt again due to it screwing up layouts and I will not be using storyboards or Interface Builder either. They just are not stable and cause more trouble than they are worth. I also do most of my work in AppCode instead of Xcode as AppCode does a much better job in a lot of areas. Better editor, much better refactoring, GIT actually works properly and it is stable. I have had it crash on me once in the two plus years I have been using it.

The other added benefit - I can take my code and drop it in another project and it will work. I have no dependencies on copying the layouts twice and having to manually reconnect every single freaking UIView to an IBOutlet. My code is self contained. It lays itself out and knows how to talk to all of its controls.

Goodbye IB and storyboards. I don't miss you.

Friday, August 29, 2014

Switched to autolayout via Masonry

I have known for some time that I needed to start using autolayout for my iOS development. My current app is universal so I was doing things twice already in Interface Builder which was getting to be a real pain. Add the control, drag and drop the IBOutlet connections and don't forget to do it on the other side.

I tried to use autolayout in Interface Builder and finally got my fairly simple login screen to work but I cussed at it the whole time. Move a control, have IB tell you the constraints and form are out of sync, correct it and repeat. If you move a control that was used as a reference anchor for other controls then it got really lost. You end up manually deleting constraints that show up either below the control you are moving or maybe at the root view. Just way to painful and error prone.

Here is where comes into play. I have used a number of layout managers in the past including standard Java layouts, MigLayout for Java and the Android XML layouts. Masonry is similar to each of them in a number of areas.

A new layout with about 35 controls was the tipping point. No way I was going to do that after all the venom I spewed at IB doing the login view with only 7 controls. I got the new layout working pretty quickly in Masonry then I went back and ripped the login from IB and did it in Masonry where I can easily see the exact constraints and view relationships.

I attempting to use the Apple flavor of programmatically doing autolayout but I found it to be very verbose and nearly as confusing as IB. The other shorter syntax messed with my mind also. Masonry seemed to go right down the middle.

Not a huge fan of checking in the code for iPhone vs. iPad but for a universal app where you want special layouts that is what you get to do. Not sure what will happen when the new iPhone 6 comes into play.

I am now skipping story boards and all their headaches and just doing my layouts in code. This also means is a new developer was to come on board we would not be walking on top of each other when we change a layout which stinks with storyboards and version control. That developer would get to learn Masonry but it is reasonable straight forward. I still run into some odd layout issues that send me scrambling to stack overflow but in general it has been pretty smooth.

UIScrollView gave me the most fun but once I figured out how to anchor the scroll view to the main view then anchor child views of the scroll view to the scroll view it all worked out.

The error messages given by autolayout are not super helpful. Some trial and error is involved but I don't run into errors very often anymore.

Monday, July 14, 2014

When do you learn a new library?

When do you take the time to learn a new library? I decided now was as good a time as any since I was at a new job and working on a new application. In the past I have used straight JSON parsing and hand written HTTP code. This time I decide to see what RestKit had to offer for both areas and I am happy I did that.

It can be very hard to retrofit a new library into old code. The design most likely does not follow the new pattern. No one wants to start from scratch when an existing product is already working. Kind of a shame because a lot of the time doing that can really make things work a lot better and make it easier to catch odd exceptions.

Per usual I got the Android side up and running pretty quickly. I did use the GSON library, which I have used in the past, but I used it in a deeper way. I set up the objects with the correct annotations and I let the library create my objects from the HTML body of the response. Worked like a champ. I implemented loaders to pull in the data and images for everything to happen on a background thread.

Next up was the iOS version. I found a lot of RestKit information on the web so I figured I would give it a shot. Not only does it handle the HTML / JSON request / responses but it also deals with JSON to object mapping. It took a bit more work to get that going though. You have to return object mappings instead of doing simple annotations. Once I had it figured out it worked very well. Some trial and error as I made the request over and over to the server to see what else I screwed up in the mapping. The JSON objects I am parsing go 6 levels deep. I did not write the server side so I am not in control of that aspect.

The image side was a different story at least when it comes to requesting a lot of images via queue in a background thread. There is a lot of documentation about the older .10 version of RestKit but less for the newer .20 code base. I fumbled around with things for a bit then found the SDWebImage library which did exactly what I needed in very few lines of code.

I am using CocoaPods for all my iOS work along with AppCode for the IDE. Yes, I have to switch back to Xcode from time to time as I can't find ways of doing things such as adding a Font to the project. This is not a super straight forward thing in Xcode either. I really want AppCode to do everything. I have been doing my Storyboard work in AppCode. Took a little bit of time to figure out where to drag from to get the IBOutlet connections to work. Xcode is confusing in this area too, nothing leads you down the path, you need to know to hold down the right keys and drag things and drop them on the right area. They improved this with Xcode 5 where you drop directly in the code but boy does the screen get cluttered when you try and have an iPad Storyboard open with code too.

Working with iPad Storyboards is a pain in both products. The screens are big and even though I am running the IDE on a 24" monitor there still is not enough space. I guess I need to have the IDE span both of my monitors as anytime you need to set up a segue between two screens you just don't have the space to do it. Even running the simulator on a 24" monitor for an iPad Retina at 50% leaves scrollbars in place. This outright sucks. I use GenyMotion for my Android work and I am able to easily scale that window to fit on screen.

Tuesday, June 10, 2014

Back to mobile dev

While my stint doing AngularJS work was interesting I am back into full time mobile work. Man I missed it and I am happy to be back into it.

Of course you are always surprised about how much you forget when you spend time away from something. I get to do both iOS and Android again. I started on the Android side first as I have always been more comfortable in Java than Objective C. I have the main login, logout and initial REST calls working under Android. Today I was working from home on the MacBook so I started to tackle the iOS side of things.

First I wanted to make sure I did autolayout from the start. Apple is pushing it and there are signs that Apple will release a different sized phone and maybe side by side program running on iPads. This means your code should be able to run as resolution independent as possible. Something you do almost by default on Android.

Autolayout is a bit weird but I got the login screen to work without any code for both portrait and landscape in the iPad storyboard. I started experimenting with AppCode 3.0 but ran into issues just getting my images into the xcassets area so I switched back to Xcode for this round of fun. I will switch back to AppCode once the UI is in place and I am doing gut level coding.

I had to create the various icons and launch screen images. I had large sized assets so I used Seashore for simple scaling. It annoys me that Mac OS does not bring an app to the front when you hover over it like Windows does. I wanted to DnD the images from Finder to Xcode. Luckily I am running a dual screen setup so I just moved Finder to the other screen and did it that way.

I copied over some other code and utility files I use and got the basics of the login screen in place. Now I get to decide which JSON library to use. I might just go with NSJSONSerialization this round. I have used YAJL in the past but I did that because I needed to stream things as the data was too big to hold in memory multiple times. Right now I do have that issue. I did not need to stream on the Android side, I am using GSON over there. I do like GSON parsing right into my natural object format where NSJSONSerialization just does a generic dictionary. Makes method name traversal impossible. The objects are rather deep for the JSON I am getting back so I need to find a decent way to get to the info I need. All the REST calls are done via C# and IIS so none of it is really optimized for Java or Objective C consumption but it is JSON which I find easier to deal with than XML.

I will need to all pull to refresh and navigation menu support too. Guess I need to get my head back into Objective C and review the list of CocoaPods I used in the past.

Since all the news about Swift as been in the news as of late I have started to sniff around. To me it looks like a nice step in new direction. I like they syntax having never been a big fan of [ ] []]]]]] [[[][][]]] all over in Objective C. Swift looks JavaScript like. Don't think I care for the .. vs. ... for the loop construct where on does inclusive start / end index and the other does start / end - 1. I would rather have a more distinct syntax between the two.

Sadly I don't have current access to Xcode 6 so I am not playing with that. From what I have read neither Swift nor Xcode 6 is ready for primetime meaning it is best for me to concentrate on the old Objective C via Xcode 5 and AppCode for now. Documentation is also sparse. I hope they hammer out the issues quickly as I would like to move away from Objective C sooner than later.

I have picked up a lot of info on the Android side again too. I have done JSON work there before but again I forgot a bunch of it having not messed with it in nearly a year. Good thing Google works most days.