5 One-liners to Polish Your iOS App

In developing iOS apps from day to day, I have come across some helpful single-lines of code. Here are five “one-liners” which I have found quite useful.

5. UIScrollView scrollsToTop

scrollView.scrollsToTop = NO;

The scrollsToTop property defaults to YES on UIScrollview and its UITableView subclass. Now this is the natural and desired behavior, but lets say that you have a scrollview inside a scrollview or a tableview with a scrollview inside one of its cells. A problem arises. When your user tries to tap on the status bar to scroll a vertical scrollview to the top, it is unclear which scrollview should be scrolled to the top. This problem even exists if you have a vertical scrollview with a horizontal scrollview inside it. By configuring this scrollsToTop property and setting it to NO, you help the system determine which scrollview it should scroll to the top. This might seem like a small feature, but it’s a convenient behavior which users expect.

4. UIScrollView alwaysBounceVertical

scrollView.alwaysBounceVertical = YES;

The alwaysBounceVertical property is great to enable in your UIScrollViews. This property is enabled by default in UITableViews. Essentially it will allow the bouncing of the content, even if the content size is less than the frame of your scrollview. It will still keep the scroll indicators hidden if your content size is less than your frame. There is also a corresponding alwaysBounceHorizontal which works in a similar manner. Bouncing makes content feel more active and playful. Users like to casually flick their scrollviews and for most cases I think this provides a better user experience.

3. UIView exclusiveTouch

button.exclusiveTouch = YES;

I have found this property on UIView most useful on UIButtons. By setting exclusiveTouch to YES, you avoid issues in your app where a user could trigger two or more target actions simultaneously. The user has to create the perfect storm by pressing both buttons simultaneously, but I have crashed several popular apps using this trick.

Here is some code that could be problematic if you only wanted to allow one button to a fire at a time.

– (IBAction)buttonOnePressed:(id)sender {

    self.buttonTwo.enabled = NO;
    NSLog(@”button one pressed”);
}
– (IBAction)buttonTwoPressed:(id)sender {

    self.buttonOne.enabled = NO;
    NSLog(@”button two pressed”);
}

If both buttons are skillfully pressed at the same time, both of these statements will be logged. By using the exclusiveTouch property you can avoid this unpredictable and almost random behavior. Once a touch event is registered on the exclusiveTouch enabled view all other touches to views in the same window are blocked.

2.  CALayer animationKeys

BOOL animating = view.layer.animationKeys.count > 0;

Here is a single line which can be convenient when using UIViewAnimation or more direct Core Animation. By checking the number of animationKeys on the CALayer which backs your UIViews you can determine if the view is animating. In order to access this property you need to add and import the <QuartzCore/QuartzCore.h> framework.

I have even added this line as a category on UIView, but be careful naming the method because you do not want to conflict with the isAnimating property on UIActivityIndicatorView and UIImageView. It is useful to check this value when trying to stop a user from triggering an animation on the same view while one is already in progress. Rather than disabling parts of your UI, it might be easier to simply return early from your animation method  if the animation is already in progress.

1. NSMutableArray arrayWithCapacity

NSMutableArray *array = [NSMutableArrayarrayWithCapacity:10];

This is simple line which will make your code faster and less memory intensive. If you are creating a dynamic collection such as an array, dictionary, or a set, you should always try and specify a capacity when known. If you just use the +(id)array initializer the system could have to resize your collection if you add more items than it has initialized space for.

There is a caveat however. If you use this initializer specifying a large capacity and end up not using all of that space, you risk wasting allocated space. Now this might seem like a minimal performance enhancement, but imagine if you were creating hundreds of these dynamic collections when doing something like parsing data.

Leave a Reply

Your email address will not be published. Required fields are marked *