Wednesday, May 25, 2011

Using both Xcode and AppCode on the Mac

I am not a huge fan of Xcode as I find it lacking in a number of areas. You can read my frustrations in various other posts of my blog like http://kevsaidwhat.blogspot.com/2011/04/things-i-dont-like-about-xcode-4.html. I have enjoyed using the JetBrains products in the past for my Java development. JetBrains has an Alpha release of AppCode which is free to download and use for those wishing for something other than Xcode for Objective C on the Mac. I end up using both on nearly a daily basis.

To save me typing XC = Xcode, AC = AppCode and IB = Interface Builder

If XC sucks, and it does, why can't I just switch to AC? Because AC does not have an IB replacement. It is going to fire IB up to do work in that less than optimal tool. It does this automatically for you. If I am doing a lot of IB tweaking or adding new views to my app I use XC so I am in just one tool. If I am doing heavy code development or much of anything with SVN, another area where XC truly blows, I use AC.

Where does AC shine? SVN integration is one place. Where XC can easily get lost if you want to rename a file you have flagged to add to SVN AC handles it just fine. I have had XC screw up SVN so bad I could not even get the SVN command line tools to fix things but AC looked at things and let me fix it with a mouse click.

AC flags a lot more things as warnings in your code than XC. Even if you just used it as a static code analyzer it would be worth the download. It can flag a bit too much at time especially around suspicious memory leaks, but generally it flags real issues. Using the wrong enum in a method call, odd use of objects for static access, unused imports, unused class methods, etc. It will really help you write cleaner code.

You also get real refactoring, not the half-bake attempt in XC. XC can not rename a simple enumeration value, that is plain sad. I have found one instance in AC where it did not complete the refactoring. I was using a static on a class via TheClass.STATIC_VAR but I think it would have done it if I used the longer syntax of [TheClass STATIC_VAR]. As I am learning Objective C I find myself refactoring more and more. I don't want my code to look like Objective C done by a Java coder but to look like Objective C code. I have made a number of mistakes and want to correct them. I also have found inconsistencies in my class naming that I want to clear up. Very easy to do with AC but a manual process in XC.

I did go into the system settings and turn my function keys into actual functions keys instead of dimming my screen and other things I rarely do. AC makes a lot of use of the function keys for shortcuts. Since I am used to what XC uses for shortcuts I wish there was more overlap but I switch back and forth enough it is not a huge issue.

Both AC and XC fire up and shut down quickly enough it is not a big deal to switch between them. I am thinking of dumping IB usage and just creating the layouts in code. Since IB can not help you much when switching between portrait and landscape, an area I want to be friendly in, it is getting to be more of a pain than anything else. I also mistakenly thought I could lay things out in landscape and copy the coordinates into my code to move the controls around but that turned out to be a waste of time making the tool even less usable. Even Apple must have found this all too hard as their calendar app still does not support landscape mode. By default the code generated by XC always tells the OS it is portrait only. Scum. UITables with other controls above and below them must be dealt with in code so IB is not very useful for iOS apps and I will not miss the day I never fire it up again.

I will use XC for memory leak detection, Organizer for screen shots and the like and a few other reasons but the more time I spend in AC the less I even thing of firing up XC to do anything. I would be nice if JetBrains could completely replace XC and IB but that would take a lot of development effort and for now I am very happy to have something to use instead of XC that is much more developer friendly. Nice going JetBrains!

AC is alpha, I have had it crash a couple of times. XC crashed on me more than once too. I have not had it ruin any code or lose anything in SVN. XC does get lost in SVN which is not acceptable for a 4.x product. AC is using the very solid code base from their other language products and it shows. I am not associated to JetBrains in any manner. I have written a free plug-in for IntelliJ for verification of MigLayouts but I don't make any money from that product. Give AC a shot if you get a chance and let me know if I am totally off my rocker on this one.

* Update * You can run the memory leak test and other profile activities just fine from within AC. I have had it crash when I make project level changes AC, use XC then come back to AC (fully shutting each down) but it seems to recover just fine. I do wish AC had the 3 finger swipe to switch between M and H files.

Wednesday, May 18, 2011

Mac annoyance

I download a new program on the Mac, in this case IntellijIDEA 10.5 for my Java work, via Firefox. I am using Firefox for the very handy SQLite Manger extension. Download completes so I double click on the downloaded file and I see an "extracting window" flash on the screen for a moment then I seem to be in a state of nothing happened.

Having done this before I know the window I am looking for has appeared BEHIND the browser. Why? I was interacting with the download, shouldn't that window come to the front? Guess not and to add to this barrel of fun you can't CMD+TAB to it either. Nice usability. You get to move the browser window out of the way or iconize it to to find the exact thing you just tried to interact with so you can drag the stupid icon to the Applications folder for it to install.

This is NOT user friendly, this is total crap.

Monday, May 16, 2011

Xoom updated - so far so good

My Xoom was finally on this list of rolling updates on Saturday so I allowed it to apply the update and reboot. Even though it had plenty of battery and did not asked to be plugged in I did that anyway. Install process was painless.

You can now size some of the the home page widgets. Nice to be able to see more of the calendar at a glance. We always have a ton of things in progress with two kids.

Otherwise I did not see any big changes. I used the browser quite a bit this weekend and it never crashed but it is hard to tell if that is due to updates or just the sites I was visiting.

The USA Today app still crashes but that must be a bug on their side. Pulse ran fine. I did a lot of news reading this weekend on the device. Nice to be able to quickly catch up with the world.

Lots going on in the land of Android tablets. Many more being released soon which I hope is going to be good news. I still need to finish updating my game to the higher resolution but I have been playing the original Half-Life, Opposing Forces, Blue Shift, Portal 2 and now Half-Life 2 again. Silly way to waste time. All started with Portal 2 meaning I was on Steam again. Decided to play the old Half-Life as it has been a really long time. I forgot how stupidly ridiculous they get with jumping towards the end of the game. It really took the fun out of things when it was just a jump attempt, die, reload process. When I got near Xen I stopped and played Opposing Forces and then Blue Shift. I had not played them before so it was fun. More puzzles in each with Blue Shift being really short.

I have played Half-Life 2, Episode 1 and Episode 2 but I don't think I ever played Lost Coast. Guess I will find out as I play them in order. Of course it was a massive upgrade in graphics from the original. Plus you don't slide around when you hit the A and D keys. That really stinks in the original. You can go up and down a ladder without fear of instant death which is good and you can jump up on pretty much any box which seemed to be a downfall of the first one.

On the coding side of things I am doing a home page with 6 buttons on the iPhone. Portrait will be 2x3 and landscape will be 3x2. Turns out Interface Builder is of no help in this area at all. You can make two different layouts but they are unknown to each other in the code. That is flat out stupid. On the Android you put your layouts in named directories and the OS chooses the right one for you. Under iOS you have to do it all manually and you have to double all your IBOutlet connections and switch layouts in code. I may just go the way of one layout and manually adjust the CGRect frame objects if they rotate the display. I can do the second layout in IB to get the proper rectangle numbers.

Everything is so manual under iOS. I really comes across and and old SDK reused for a device. I know folks out there hate automatic garbage collection too but really people it the computer / compiler helping you out instead of you battling everything. ASM coders hated C, C coders hate Basic and C++, C++ coders hate Java and C#. I have used all of them, I don't miss the "fun" of ASM, 27 pages of 6502 code for a 2.5k program. C was great but code was hard to share even with your own projects. C++ was wonderful but the syntax was wanky and memory management was never a walk on the beach. Java was initially slower but VM updates made it very usable and overall development speed greatly improved. C# improved on various aspects of Java and missed out on other areas in strange ways. Objective C is just something to code in, no real love or total hate, but does seem stuck a few decades back and really does not help you take full advantage of the device I run it on.

Wednesday, May 11, 2011

Things I learned while debugging memory leaks in Xcode

It has been one heck of a day. I started doing memory leak testing yesterday on our iOS application. I am not done with the full application but I have just knocked off a large chunk of coding around database access and field editing so I wanted to make sure all of that was clean before I moved on to the next step and forgot how all of this code worked together. Of course I had some memory leaks and they needed to be fixed.

Like everyone I got the point where I was thinking the tool that checks for leaks had a bug. It always seems that way when you look at your perfect code and can't figure out for the life of you why it has a problem. In the end I was able to fix all leaks, the tool was correct.

While searching the web for leak reasons I ran across a better way of doing some things especially temporary string formatting. I was using:

NSString *cmd = [[[NSString alloc] initWithFormat :@"drop table if exists %@", [table tableName]] autorelease];


But the better way to do it with much less typing and bracket clutter is:

NSString *cmd = [NSString stringWithFormat :@"drop table if exists %@", [table tableName]];


The first version is allocating memory, which you must free, using a method on the object while the second version is using a static method to create a string that it owned by something else so you don't have to release it. Probably just marked as autorelease but you don't care about the internals.

I cleaned up all the areas in the code using the first format but one. For some reason in that one place I got a memory leak if I did not use the alloc and release myself. I commented the code so I will not try and "fix" it at some later point.

Next I made a sad rookie mistake that is understandable coming from a Java background. In some of my classes in the dealloc method I called [super dealloc] first. Big no no. Of course in Java you don't have destructors so you almost always call super first because you are constructing. Calling [super dealloc] must be the last thing you do as it cleans up your object and all of its pointers. You are unwinding your construction. I was sitting there watching the program hit my dealloc call and looking at the retainCount (I know, this is not to be trusted) having a value of 1 and not understanding why it was flagged as leaking as I left the dealloc call and wondering why my release calls would crash things. A mistake I am not likely to make again.

With a much better understanding of memory allocation and having read a number of web sites talking about who allocs and who cleans up I revisited the code and found a few places where method names were misleading or the object creating the values was not cleaning them up. I reorganized it all so allocation and clean up happen in same class if at all possible and method names don't look like Java but look like Objective C. There were not many of them but now they are starting to stand out to me.

I missed cleaning up two of my four editing view controllers too. There I was putting nice clean up code in one of them but not all of them which happens when you are writing massive chunks of code in short order in a new language.

Things are looking really good right now. I have run the program and beat on it pretty hard in both the Profile mode and with extra Run Malloc settings enabled. Running totally clean under both. All the databases are in place and my memory mapped databases are working as expected.

I installed Xcode 4.0.2 and so far have not had another kernel panic. Still steamed you have to download such a huge pile bytes overnight for each Apple Xcode update.

Monday, May 9, 2011

Another Xcode release - what fun

In a short time frame Apple has gone Xcode 4.0 -> 4.0.1 -> 4.0.2 with each being over 4g of download so that puts me over 12g of download since they don't have incremental builds. I am guessing since we are only incrementing the second dot of the release that there are VERY minor changes but I have to leave a machine on overnight to get the latest each time.What a massive waste of bandwidth.

I have my first kernel fault today. When the screen first scrolled into view I thought it was a virus. Did not look like an official screen to me. So I looked up the wording on Google and found that it was in fact the real Apple BOOD or Black Overlay Of Death. I rebooted and sent the report off to Apple. Some semaphore corruption. The only thing running was Xcode and I was just holding down the Up arrow key to scroll through some code. I normally only have Xcode, Firefox and the SQLite extension for Firefox running but I had not even fired up Firefox yet today.

Massive update of code today as previously I did not have all the tables configured so I was saving the text the user picked to the DB instead of the code. Everything has been converted and I cleaned up a lot of calls to be more generic. I still have a little work to do before I can move on to the MRU interface. I still have tables as getting them and other controls to show on one View seems to be a huge PITA. I know you have to through out using the UITableViewController as it wants the whole screen. I think I just need to put IB and do it all by hand.

I attempted to refactor an element of an enum but Xcode could not handle it so I had to do it by hand. Another area where it is sorely lacking on features.

Getting to be a lot of code, 72 objects, 400k of source code, for just a couple of screens. There are 16 database files so far and I know of at least 4 others I need to deal with. Once I got some helper objects in place those have been pretty easy to define and add.

Probably need to run it all through the memory leak tester again. I did that last week and found a few areas. A lot more going on now with DB searching in place so probably best not to let that get out of hand.

Wednesday, May 4, 2011

iTouch goes nuts, will not show a UIAlertView

I have been coding away on phase two of our application for the iPhone. Lots of SQLite work and ton of new code. I just began testing on the actual device this week. Much easier and faster to test in the simulator as you must type in a password to login in every time you run the program and that gets old on the device keyboard.

I ran the program on our month old iTouch rev 3 device and not a single UIAlertView would appear. WTF? I did a simple test app, no go. I put the same program on our original iTouch rev 2 and it worked without a hitch. It has an older iOS version as Apple discontinued iOS releases for that hardware. Could it be iOS 4.3.2? After searching the web I found nothing to indicate that is an iOS version issue.

Next thought was to test it on another device with same iOS version. I went in search of an iPhone that is provisioned but after checking iOS version not being 4.3.2 the owner suggested I do a factor reset on the iTouch and see what happens. Nothing on the iTouch but the one program I test so that was not a big deal. Post reset and everything appears to be working fine. My UIAlertViews show up.

To me this rather worrisome. Here is a device that is a couple of months old at max. Has had exactly one iOS update installed and has no extra apps, no music, no videos, etc. on it. Basically a blank slate with just the one program I run and the SQLite databases I have created. After a month of use a very standard API call is totally screwed and I get to do a full factory reset to get it back to life. Now every time something works in the simulator but not on the device I am going to factory reset the stupid thing. Not something I want to tell clients to do. Seems like iPod users just accept this as a fact of life. Apple - it just works - unless it doesn't then factory reset it!

Not that Microsoft and Windows is immune to any of this. I have a Microsoft mouse on my Win7 machine. It gets lost every time the machine goes to sleep then I wake it up. I have to unplug the mouse and plug it back in again to get it to not just jump all over the screen. Web searches show this to be a known issue with a freaking MS mouse! They had a solution of not letting the USB connection being used go to sleep but that did not solve it for me.

Today I gave up and plugged the Dell mouse I was using on the Macbook into my desktop and plugged the MS mouse into the Mac - partially for the irony of it all. Hopefully I can stop the unplug fun on the desktop and the Mac seems to accept the stupid MS mouse. I like the MS mouse better as far as hand fit goes so I will miss it on my main machine when I go back to coding on the Android side.

As far as SQLite goes it seems to work rather nicely. I have a dozen tables with some of them having 17k records. Initially loading the big tables took 26 seconds in the simulator and over 5 minutes on the device. Man you really have to run on the device to check your work! I was not wrapping my loading loop with a begin transaction / commit. After I did that the simulator went to 0.30 seconds and the device to 4.30 seconds. Still a massive time difference but 4.30 seconds is not bad for a table that only updates yearly. It is used for code to text description lookups.

I am using FMDatabase to help out with the SQLite interaction. I implemented some ideas from the Android SQLite wrapper on the iOS side. Things like keeping an over all DB schema version in the PRAGMA user_version of the database. I have helper methods in my main DBTable object to help me create the INSERT and UPDATE strings and all tables are defined by an array of column mappings. Almost all SQL instructions are generated via code. Next I need to put captured pictures into the table as blobs.

Xcode is being used as my main IDE again. JetBrain's AppCode was just not cutting it as I was in Interface Builder a lot and it doesn't provide enough info on program crashes as of yet.

Speaking of crashes, I had a memory crash and went crazy trying to find it. I finally held down ALT and got the "Run..." in the menu and set the special memory options to show decent results. Ran slow but pointed me exactly to the memory area which was nowhere near an object I was blaming. I am using a multi-colored label as my table cell view. I was releasing some memory that I should not have in its dealloc. I still don't fully understand the iOS memory model. I only saw the crash after bringing up the view where you search and pick from one of the big DB tables then you rotate the device. Guess it was doing some garbage collection at that point and the double release annoyed it.

I am slowly learning various memory debugging techniques, how to use NSZombieEnabled and how to use the memory leak detector. All of it is a bit obscure but does the job in the end.