What I Learnt Building 6 Real Estate iPhone Apps

I’ve built the following real estate related apps over the last few months. All of them are Singapore centric except for the rental yield calculator and the mortgage calculator.

  1. Progressive Payment Calculator 
  2. SG Stamp Duty Calculator
  3. Loan Affordability Calculator
  4. Property Tax Calculator
  5. Rental Yield Calculator
  6. Mortgage Calculator

Takeaways

  • When dealing with currency operations, just bite the bullet and use NSDecimalNumber. You’ll save yourself a lot of grief further down the road
  • Always try to use NSNumberFormatter for converting from NSNumber to NSString or the other way round. Don’t do things like self.label.text = @”$0.00″. Instead, do self.label.text = [self.formatter stringFromNumber:self.number] where self.formatter is a NSNumberFormatter property. Here’s how I instantiate my property.
    - (NSNumberFormatter *)formatter {
        if (!_formatter) {
            _formatter = [[NSNumberFormatter alloc] init];
            _formatter.numberStyle = NSNumberFormatterCurrencyStyle;
            _formatter.locale = [NSLocale currentLocale];
            _formatter.generatesDecimalNumbers = YES;
            [_formatter setLenient:YES];
        }
        return _formatter;
    }
  • If you’re dealing with percentages and you find yourself having to multiply/divide 100 at certain parts of your code, there’s a good chance you’re doing it wrong. Use NSNumberFormatterPercentStyle for NSNumberFormatter. Always work with the decimal form of your percent before formatting it for display at the final step.
  • Always test your app by changing the default region to another country which doesn’t have $ as it’s currency symbol. You can do so by going to Settings > General > International > Region Format. If you’re using NSNumberFormatter correctly, you should be safe.
  • Currency input sanitization can be annoying. Your sanitizer needs to handle the situations where
    • User input with currency symbol
    • User input without currency symbol

    as it was in my case. The initial input from the user doesn’t contain currency symbols. Once the formatter is applied and displayed, subsequent changes to the textfield will involve a currency symbol. It is probably worth noting that [self.formatter numberFromString:self.label.text] requires self.label.text to be in a format that contains the currency symbol otherwise it will return nil. This makes it annoying for the initial input where there isn’t a currency symbol and subsequent inputs where there is.
    My workaround for that is to enforce the currency symbol all the time. I use this little snippet to do so

Comment Scene Like Instagram

In my short stint with iOS programming thus far, I found that one of the most difficult and crucial part of the process is deciding which controller to use. Conceivably, you could use a plain UIViewController to design everything but that’s a poor man’s way of going about it. Here’s how I did the comment page for Instagram.

There are a few requirements:

  • Comment box should stick to the bottom
  • Autolayout should be used
  • UITableViewCell should resize accordingly to the amount of text required to fit the cell nicely
  • Bonus: works in landscape and portrait modes. Instagram doesn’t support landscape.

2014-04-24 12.26.36

2014-04-24 12.23.33

 

 

 

 

 

 

General process:

  • Insert a TableView into a UIViewController
  • Add a subview programmatically or via storyboard
  • Set the constraints up correctly
  • Animate the bottom constraint from the comment box to it’s superview as and when the keyboard appears

Some gotchas:

  • You can’t do this using a UITableViewController and then laying a subview into it.
    • The view will move along with the tableview as you scroll which is not the behaviour you want
  • You can’t do this using a UITableViewController and then adding the comment box in the footer
    • The footer will always be below the last cell in the tableview which is not what you want

Code: https://github.com/nychng/AutoSizeTableCell

Next Set of iOS Queries to Answer

  1. In the storyboard, which layout to work in? 3.5 or 4 inch?
  2. Do you drag the size of your view all the way to the edge of the 4 inch? How does this affect the 3.5 inch view?
  3. In a navigation controller, the Top Bar pushes down content when there’s a scroll view. It doesn’t push it down in a normal view. Why?
  4. How to manage autolayout and scroll view?
  5. Should you lazy instantiate all of your properties all the time? Including all the UILabels and UITextFields?
  6. Assuming I want the height of a view to occupy the few screen, what should the height of the UIView be in a navigation controller (with and without the status bar)
  7. In View Controller, what does Extend Edges — Under Top Bars/Under Bottom Bars/Under Opague Bars

Python to Objective-C: Initial Reactions

Here are some of my initial thoughts and reactions coming from a scripting (Python) background on Objective-C and iOS:

  • Overwhelming API documentation. To me this is just a case of hunkering down and mugging like a good A level student.
  • Obsolete Stackoverflow answers. With every yearly release of a new iOS version, it kinda makes an entire generation of SO answers redundant. The game changes very quickly
  • There’s quite a fair bit of plugins out there in the wild. Initially, I was rolling my own image downloader and caching mechanism only to find quite a few libraries out there doing exactly that (and better) already

Some lingering questions still on my mind which I hope to be cleared up as I go along:

  1. In a segue, when to use push and when to use modal
  2. Modification of UI elements in the storyboard or in the code
  3. Passing on values from one view controller to another. Direct assignment in the prepareForSegue method or what?
  4. How do I quickly check in XCode what methods are needed to be implemented for a new delegate or data source
  5. The difference between @class and #import
  6. strong/weak references in declaration of properties
  7. Project and folder layout hierarchy
  8. Paths and inclusion of new files

Updated with answers!

  1. The way I think about when to use push or modal segues is to use a RPG example: if you’re exploring a dungeon and you go into a room, if the room leads to more rooms, use a push segue. If the room is a dead end, use a modal segue.
  2. Where possible, reduce code bloat and use storyboard modifications. This is kind of subjective
  3. Direct assignment is fine. I think I was being overly paranoid with this question
  4. cmd + click is your friend. Then look for @required methods. This should get better with experience
  5. General rule of thumb: if you need to alloc/init something, you have to import it. @class is almost always used only in header files
  6. When in doubt, use strong
  7. I’m actually still figuring this one out
  8. If you click on a file and goto the file inspector, you can see a Location drop down that allows you to set the path. The thing that threw me off initially was that your project path directory need not match your Explorer folder path directory.

Loading Images in UICollectionViewCell: Naive to the Clever.

I’m working on an iOS app called Scenery. It pulls images from /r/earthporn via imgur’s API. It’s a simple 2 screen app that uses UICollectionViewCell to display images in a grid format. I went through a few code iterations in getting the images to display. Let’s go through them.

2014-02-05 12.19.28 2014-02-05 12.19.36

Iteration 1: The “Hello World” of downloads

NSURL *url = [NSURL URLWithString:@"https://api.imgur.com/3/gallery/r/earthporn/time/"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];

This works as expected except that it’s a synchronous request. This means the screen is blank to the user until all the images have been downloaded and displayed. In this case, each API request to imgur is returning 52 images making for a poor user experience.

Iteration 2: The Sensible Asynchronous Method

What’s obviously required here is to first load the screen and then download the images asynchronously.

        // download the image asynchronously
        NSString *imageString = [[_imgurArray objectAtIndex:indexPath.row] objectForKey:@"link"];
        NSURL *imageURL = [NSURL URLWithString:imageString];

        [self downloadImageWithURL:imageURL
                   completionBlock:^(BOOL succeeded, UIImage *image) {
            if (succeeded) {
                    imageView.image = image;
                }
            }
        }];

I’m now downloading the images asynchronously with downloadImageWithURL:. Great! Now the screen loads first and I can see the images pop up one by one as it finishes the download. However, every time I scroll down the screen and up again, the app re-downloads and re-requests the images again. Not great.

Note that all of this action is taking place in – (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath.

Iteration 3: The Sensible Asynchronous Method with Makeshift Cache

So to deal with the multiple requests to imgur’s server each time a user scrolls up and down, I loaded all the images into a NSMutableDictionary as a sort of cache.

    if ([_cachedImages objectForKey:identifier] != nil) {
        imageView.image = [_cachedImages valueForKey:identifier];
    } else {
        // download the image asynchronously
        NSString *imageString = [[_imgurArray objectAtIndex:indexPath.row] objectForKey:@"link"];
        NSURL *imageURL = [NSURL URLWithString:imageString];

        [self downloadImageWithURL:imageURL
                   completionBlock:^(BOOL succeeded, UIImage *image) {
            if (succeeded) {
                if ([_cachedImages objectForKey:identifier] == nil) {
                    [_cachedImages setValue:image forKey:identifier];
                    imageView.image = [_cachedImages valueForKey:identifier];
                }
            }
        }];
    }

Getting there! The scroll speed is smooth and the download is asynchronous. But look, what do we have here

Screen Shot 2014-02-05 at 12.40.16 pm Screen Shot 2014-02-05 at 12.40.49 pmThe memory footprint is out of this world. On first load, the app consumes 300MB. When I load the 2nd page, it also doubles. Each subsequent page load adds roughly 200MB. As you might have guessed, it crashes once I tried running this on my iPhone.

Note: the original code was heavily inspired by this post: http://natashatherobot.com/ios-how-to-download-images-asynchronously-make-uitableview-scroll-fast/

Iteration 4: The Real Sensible Method

We’re all standing on the shoulders of giants in the software industry. Image caching and url requests are a well trodden path that have been solved by other folks much smarter than myself. A cursory search reveals a few prominent libraries:

Using SDWebImage, I managed to reduce my memory footprint by 1 order of magnitude. And it does all the asynchronous loading as well.

    NSString *imageString = [[_imgurArray objectAtIndex:indexPath.row] objectForKey:@"link"];
    [imageView setImageWithURL:[NSURL URLWithString:imageString]];
    cell.backgroundView = imageView;

Screen Shot 2014-02-05 at 12.50.19 pm

 

 

Haha! Mind blown!

Learning Objective-C

much shine. very sexy.

Been hunkering down a bit and getting up to speed with iOS. Coming from a scripting level like Python, learning Objective-C is definitely an eye opener. There are so many things that are taken for granted when you work with languages like Python, Ruby and PHP.

Initially, I started working on the Ray Wenderlich iOS tutorials but I felt I wasn’t fully understanding the tutorials properly. I will be going back to those tutorials once I’m done with this book called Objective-C Programming: The Big Nerd Ranch. The first part about C is really really vital and it builds up nicely. Previously, when I was learning Python, I stressed the importance of ‘learning by doing’ and The Big Nerd Ranch does this very well. There’s a hands on coding portion for almost every chapter. My only peeve is that I wish they included solutions in the book itself for their challenges section.

I hope to release an app every month. Let’s see how it goes!

How and Why am I Learning Objective-C

WHY

  1. Looks fun 🙂
  2. Coming from a Python background, knowing C will improve my overall knowledge of programming in general since Python abstracts a lot of the heavy lifting away.
  3. Many developers have staked their careers learning Java and C# whilst riding on the coat tails of Oracle(Sun Microsystems) and Microsoft respectively. The assumption is that these large software companies will provide them with career growth opportunities due to their monopolistic nature of their business. Do I see the same thing occurring with Apple? The answer is a resounding quite simply yes. Apple has built a formidable moat in its supply-chain process, cutting edge software, iTunes platform and above all, its brand equity. Moat = monopoly = longevity.
  4. Looking at current consumption patterns, it seems fairly obvious that the current and following generation of consumers will be born into an app generation. The iPad is omnipresent at every dinner table where there is young child. Demand will be there for many years to come.
  5. iTunes reduces the marketing and sales burden of a developer.
  6. Straight to App as a strategy. Instagram showed that this can be done.
  7. At $0.99, an app built for the masses at that price point is recession proof.

HOW

  1. Short C Tutorial – http://cocoadevcentral.com/articles/000081.php
  2. Short Objective-C Tutorial – http://www.cocoadevcentral.com/d/learn_objectivec/
  3. Books
    1. Programming Objective-C – http://www.amazon.com/Programming-Objective-C-Edition-Developers-Library/dp/0321811909/ref=sr_1_1?ie=UTF8&qid=1337053001&sr=8-1
    2. Learn C on the Mac – http://www.amazon.com/Learn-C-Mac-Series/dp/1430218096/ref=sr_1_1?s=books&ie=UTF8&qid=1337053059&sr=1-1
    3. Learn Objective-C  on the Mac – http://www.amazon.com/Learn-Objective-C-Mac-Series/dp/1430218150/ref=sr_1_2?s=books&ie=UTF8&qid=1337053059&sr=1-2
      1. This is a follow up to Learn C on the Mac
  4. Standford iOS class – http://itunes.apple.com/us/itunes-u/ipad-iphone-application-development/id473757255

UPDATES

Got this series of tutorials. Seem pretty good so far! http://www.raywenderlich.com/store/ios-apprentice