All posts by Jay Versluis

About Jay Versluis

Jay is the founder of Pinkstone Pictures and WP Hosting. He has been developing iOS Apps since 2011, several of which have made it to the App Store. In his spare time he likes to develop WordPress plugins and drawing on tablet devices. He blogs about his coding journey here and at http://wpguru.co.uk.

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.





How to read keyboard input in C

We can use the scanf() function to get user input in C. Here’s a quick implementation of scanf():

#include <stdio.h>

char input[100];
char *output = "Thank you for your message!";

int main(int argc, const char * argv[]) {
    
    // ask user for some input
    puts("Tell me something nice:");
    
    // grab input from keyboard via scanf()
    // don't use gets() for this, apparently it's totally evil
    scanf("%s", input);
    
    // say goodbye
    printf("%s\n\n", output);
    
    return 0;
}

scanf() will wait for the user to press Enter before giving its returned value back to our app. We must define a variable to hold its output. We can even define multiple variables, each of which will be populated with whatever is being typed in until Enter is pressed. Consider this:

 char input1[100], input2[100], input3[100];
 scanf("%s, %s, %s", input1, input2, input3);

Here we wait for three string items to be added (numbers entered will be interpreted as strings). To grab a numeric value from the keyboard, we cam use %d like so (d as in decimal, variable defined as int):

 int number;
 scanf("%d", &number);

Note the ampersand in front of our variable, without which scanf would populate a pointer. We can also mix and match keyboard input like this:

 char string[100];
 int number;
 scanf("%s, %d", string, &number);

Demo Project

You’ll find a quick demo project on GitHub, which also serves as a template on how to setup Xcode to open Terminal and allow for keyboard input when the project is run.