Home Schedule Syllabus Resources

Lecture 4 - Custom Keyboards

Originally, we were going to do this lecture from last semester, adapted to Swift. Unfortunately, Apple has made this method of building user interfaces--manually, through code--a bit more difficult to accomplish. Therefore, we'll release the lecture sometime later in the semester as a tidbit. Instead, we'll be following an online tutorial to learn how to build custom keyboards, one of the new featuers in iOS 8.

How to Make a Custom Keyboard

A well written and comprehensive tutorial on how to build custom keyboards can be found here. The example done in the tutorial makes a fully functional Morse code keyboard.

UIViews

UIView is one of the most important classes in all of iOS development. Your users will very likely be interacting with a large hierarchy of views. We have talked a bit about views before, but now we really want to dive into the specifics.

So, what is a view? We think the Big Nerd Ranch Guide to iOS Programming explains it very well:

A few examples of UIView subclasses are UILabel and UIButton which you are all familiar with from making interfaces. Each one of these views know how to draw themselves to their superview. For example, the buttons we have been using draw an internal label and know how to handle tap events. The super-most view is the application's window, which is an instance of UIWindow which is a subclass of UIView.

There are three main structs you should know about when dealing with views, CGPoint, CGSize, and CGRect. CG stands for CoreGraphics, the main graphics library used in iOS applications. These structs are declared in C (which, believe it or not, is usable in Swift despite this fact) as follows:

// CG-structs that deal with UIViews
// C code--NOT VALID SWIFT (actually it might be)
struct CGPoint {
  CGFloat x;
  CGFloat y;
};
typedef struct CGPoint CGPoint;

struct CGSize {
  CGFloat width;
  CGFloat height;
};
typedef struct CGSize CGSize;

struct CGRect {
  CGPoint origin;
  CGSize size;
};
typedef struct CGRect CGRect;

Structs are actually a C type which allows us to put multiple values into a single object-like structure (thus, struct) to make it easier to pass around. Structs are NOT pointers, but you do access their internal variables using dot syntax. Every UIView has two rectangles that define it's position on the screen, a frame and it's bounds. This is frequently one of the most confusing parts of iOS development, so we will do our best to explain it well.

First, let's talk about CGRect. This is just a simple definition of a geometric rectangle. It contains two main pieces: the origin, and the size. The origin of a CGRect points to the top-left corner of the view. The size is a width and height which extends down and to the right from the origin. The image below shows how how the origin relates to the width and height of the view.

A view's bounds is a rectangle relative to itself. If the view is not translated (which by default, it is not), a view's bounds rectangle will always have an origin of (0,0). This is because relative to itself, the top left corner of any view is always the zero point. The size will just be the view's full width and height.

A view's frame is a rectangle relative to that view's superview. A view's frame will have an origin corresponding to the offset of that view's top-left corner from it's superview's top-left corner. In the picture below, the blue subview is at location (50, 150) in the light gray view. This means that it's frame has an origin at that point. The frame's width and height is the same as it is for the bounds.

If a view fills the entire window, that view's frame and bounds will be the same. Remember that the super-most view is the application's window which fills the full available screen.

Notice how views live in a hierarchy. Every view can have a collection of subviews, which can also have their own subviews, etc. As your applications become more and more complicated with many levels of this hierarchy, remembering the difference between frame and bounds will be crucial to ensuring your views are arranged properly.

fdsahkjlfdsa

Today's app, fdsahkjlfdsa, can be downloaded here.

NSArray

Arrays of UIButton's, represented by the Swift type [UIButton], don't work yet. The workaround is to use a plain old NSArray, which is an old class from Objective-C. This section will be filled in soon with implementation details on NSArray.