Yearly Archives: 2017

How to create infinite loops in Objective-C and C

Infinite loops can be useful to execute some code until an exit signal is given. For example, a command line menu could be waiting forever until the user makes a valid choice. There are other approaches of course, but in case you need to know the syntax, here it is for all three loops.

Infinite for loop

// infinite for loop
for (;;) {
    // repeat this forever

Infinite while loop

// infinite while loop
while (TRUE) {
    // repeat forever

Infinite do-while loop

// infinite do-while loop
do {
    // repeat forever
} while (TRUE);

To use the latter variations in C, replace the TRUE condition with 1.

How to add a macOS target to your iOS App

To write cross-platform applications, it can be beneficial to have a single project with several target architectures. For example, we may want a macOS App inside a project that started out as iOS, and vice versa. Or we may want a different version of our app, perhaps a free one with less features, and an expensive one with more, based on the same code.

That’s where Xcode Targets come in. A Target is something that defines several build settings about an app so that when we press that popular button in Xcode, it knows what to do so we can see the built app in full colour. Trust me, there’s a lot going on under the hood – if you’ve ever tried to compile from the command line, you know how super helpful that button is. But I digress…

In this example I’ll show you how we can add a macOS Target to an iOS App’s Project. This will allow us to run and build either an iOS or a macOS version from common code.

Let’s begin. I’m using Xcode 8.3.3 for this by the way.

Adding the Target

In a standard Xcode Project for iOS, we already have a single target. Click on the blue project bar and select it from the list next to the File Inspector. It’s the one with the yellow icon:

Continue reading

How to resize a UITextView dynamically with Auto Layout

Resizing a UITextView (or a UIScrollView) dynamically on the fly isn’t easy – or so it seems at first. Should we move or squish the UIView? Should we create a new frame for the enclosing view and animate that? But no, those things worked fine in the days before Auto Layout. Nowadays we have the excellent UIStackView in which our text view may be embedded – so what are we to do?

Turns out the easiest way would be to change one of the constraints we have given our outermost stack view programmatically.

In my example I have a stack view that fills the screen, and inside it I have a text view for the user to read text, and a text field underneath it for text input. When the keyboard comes up, I’d like the text field to slide up and the text view to get smaller, and as soon as the user taps return I’d like everything to go back to where it was. Oh, and I’d like for this to work in portrait and landscape, and on all iPad sizes as well. Like in the animation above. Without going insane.

Here’s how we do that. Continue reading

How to keep a UITextView scrolled to the bottom

UITextViews are ideal for displaying large amounts of scrollable text on a small screen, or a portion of the screen. They’re also great for continuously adding text to them, which naturally appears at the bottom. However, doing so does not scroll the text upwards so that the user can see the latest addition by default.

To accomplish this, many sources suggest to add use the contentOffset property. While this works if another component (like a keyboard) may come into vision, it does not help to steady keep all the text in our text view at the bottom at all times. However, another method from the UITextView class can help us there: scrollRangeToVisible.

To use it, we need to define an NSRange struct and define the portion of the text content that we’d like to display. We don’t need to find out what the height of our text view is for this, it is indeed enough to simply specify the last line of our text content. The following code nippet will do that:

- (void)positionTextView {
    // scroll to the bottom of the content
    NSRange lastLine = NSMakeRange(self.textView.text.length - 1, 1);
    [self.textView scrollRangeToVisible:lastLine];

Call this whenever text is added to the text view, or changes to the text view arise from constraint changes, and your last line of text will always be scrolled to the bottom.

How to determine the height of the keyboard in iOS

Keyboards in iOS can have various sizes. Not only can a keyboard be presented in portrait or landscape, on various devices with a plethora of screen sizes, and users may have QuickType enabled or disabled. Too many variables for hard coding.

Lucky for us, we can check all kinds of properties about a keyboard by dissecting the dictionary that is passed with the notifications mentioned in my previous post. If you recall, we can check when a keyboard appears or disappears using an observer. Let’s take a look at that notification when the keyboard is presented, and we can extract the height like this:

- (CGFloat)grabKeyboardHeight:(NSNotification *)notification {
    // grab keyboard size
    NSDictionary *userInfo = notification.userInfo;
    NSValue *keyFrame = [userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardFrame = keyFrame.CGRectValue;
    CGFloat height = keyboardFrame.size.height;
    return height;

The keyboard’s width can be determined in much the same way. The dictionary holds many other interesting goodies, for example how long it takes iOS to animate it onto the screen:

- (NSTimeInterval)grabAnimationDuration:(NSNotification *)notification {
    // find out how long the keyboard animation lasts
    NSDictionary *userInfo = notification.userInfo;
    NSTimeInterval duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey]doubleValue];
    return duration;

Apple has the full list if interesting objects for us to play with:

How to detect when the keyboard appears and disappears in iOS

To detect when the keyboard from a UITextField is being brought up (and goes away again), the UITextField Delegate Protocol won’t help us. Instead we need to listen to two notifications, namely UIKeyBoardWillShow and UIKeyboardWillHide.

We could setup the observers in viewDidLoad, like this for example:

- (void)viewDidLoad {
    [super viewDidLoad];
    // setup keyboard observers
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardCameUp:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWentAway:) name:UIKeyboardWillHideNotification object:nil];

These observers will call a method in our class (using @selector). Mine are called keyboardCameUp and keyboardWentAway:

- (void)keyboardCameUp:(NSNotification *)notification {
    NSLog(@"Keyboard came up!");

- (void)keyboardWentAway:(NSNotification *)notification {
    NSLog(@"Keyboard went away!");

The notification can be used to detect some properties of the keyboard, for example its height and width.