Wednesday, 23 December 2015

There are several sorts of notifications a user can receiver in iOS, these are:

Lock screen notifications

Banner notifications

Alerts

Lock screen and banner notifications are quite compact and can only have 2 associated actions. Whereas alert notifications are larger and can have up to 4 actions. You can choose whether you want to receive banner notifications or alert notifications for an app by going to Settings > Notifications > [App name]. This article is aimed at teaching you how to schedule and cancel local notifications.

Notification Settings

In the App.delegate you can configure the settings for your notifications, e.g. what actions there will be and whether the action will take place in the background or visibly. Firstly, we need to be aware of what type of notifications we can have:

UIUserNotificationType.None: The user sees nothing when the notification is received

UIUserNotificationType.Badge: The user will see a number on the app icon that represents a number of unhandled notifications

UIUserNotificationType.Sound: The user will hear a sound when the notification is received

UIUserNotificationType.Alert: A banner notification, lock screen notification or alert notification will be displayed

Here is how the code for setting up a notification would look, a good place to do this is the App.delegate:

The UIMutableUserNoticationCategory is something you can use when scheduling a new notification to specify what actions are available to it. The context for the actions can either be Default (up to 4) or Minimal (up to 2).

Scheduling a Notification

Scheduling a notification is incredibly simple and can be done as follows:

let notification = UILocalNotification()
\\ When the notification will appear
notification.fireDate = dueDate
\\ What the notification will say
notification.alertBody = "Hello world"
\\ Links what actions the notification will have with what was
\\ specified in the App.delegate
notification.category = "BOTH"
\\ Additional info that we need when the app receives a user's
\\ interaction with the notification
var userInfo = [String: String]()
userInfo["notificationId"] = bookToSave.objectID.persistentStore?
.identifier
notification.userInfo = userInfo
UIApplication.sharedApplication()
.scheduleLocalNotification(notification)

Cancelling a notification

Often, if a user has specified a due date for something and they edit it this you will need to cancel the existing notification and reschedule it. Finding the correct notification to cancel can sometimes be challenging and this is commonly where I rely on the userInfo I have passed to the notification:

The method above is the first step, what it does is it gives you what action was pressed in the notification, along with the notification and a completion handler. You can then use the NSNotificationHandler to pass information to pass control to the view controller that will handle the actions. Here is an example of the notifications being handled in a view controller:

Tuesday, 22 December 2015

Opening up a pre-populated message composer in iOS which can be used to send an email or SMS is surprisingly easy. There is however, some issues you may encounter when testing this on a simulator where it lags and then crashes. So it is best to have a physical device available if you plan on testing this. I have also heard that having a singleton instance of your composer and showing this when required can help alleviate these issues. However, I needed to be able to send SMS/Emails based on a push notification, and on a physical device I didn't encounter these issues. Here's how I did it:

Monday, 14 December 2015

Class to represent Core Data Table

You will need to add a class to represent your core data table:

// My core data object only had the field name
// it also had relationships but I didn't need to access
// these so they are excluded.
import CoreData
@objc(Mode)
class Mode: NSManagedObject {
@NSManaged var name: String
}

Following that you will need to ensure your core data table references the class or you'll get an error, you can do this in the same place you would add columns to the table:

Performing the sort

First you must load the data, ensure that you save it as an array of your object representation of the Core Data table.

...
let modes : [Mode] = try context.executeFetchRequest(request)
as! [Mode]
// We must specify whether we want to sort in
// ascending or descending order
// $0 represents the first item, $1 represents the second
// their fields can be access as normal
appState.modes = modes.sort({$0.name.compare($1.name)
== NSComparisonResult.OrderedAscending}) as [Mode]
...

Friday, 11 December 2015

There are many situations where you may have the need to use a countdown timer. This article is aimed at helping you create one!
Firstly, you will want to add a label to your storyboard and reference it through an @IBOutlet in the relevant view controller. This will display your countdown. Following that you will need the following code:

Sometimes it can obscure the view when a user enters something in a UITextField and the keyboard stays open even after they have clicked outside the keyboard, or tapped return. The following code will help you close the keyboard when appropriate. However, first you need to set up your text field and make the appropriate view controller be its delegate, and implement UITextFieldDelegate:

Thursday, 10 December 2015

UITableView is a common way of displaying lists of information, this article will take you through the basics of setting one up.

Storyboard

Add a UITable view to your view controller in the storyboard, then select the button which looks like a venn diagram in the top right corner of your screen to display your code alongside the storyboard. Select the UITableView and hold down control while clicking and dragging towards the code, this will allow you to insert an IBOutlet into your view controller which can be used to reference the table view:

You will then want to select the tableview again, hold down control and drag up to this button:

And choose to make your view controller both the datasource and delegate.

View Controller

The next step is implementing UITableViewDataSource and UITableViewDelegate in your view controller:

Wednesday, 9 December 2015

"as!" is appropriate where you know that the underlying type of the object you are trying to cast matches what you are casting to. It will throw an error if it is not the type it expects which may help you avoid overlooking a setup issue or something similar. Whereas "as?" will try to cast it to the type, but if it is not the type it expected then it will return nil. Here's a quick code example:

// returns an object of type UIImageView?
// this can be useful in if statements, for if cast is not nil
// do something with the variable
let optionalImageView = touches.first?.view! as? UIImageView
// returns an object of type UIImageView
// will throw an error if the object is not the expected type
let optionalImageView = touches.first?.view! as! UIImageView

Monday, 7 December 2015

Hi all, this tutorial will be on using a preloaded database in Swift. There are several reasons you may want to do this, one being that you may have data that won't change that you want to be available to the user. You could load this up at runtime, but that could be slow if you have a lot of records to import. This method ensures that the application runs quickly, upon being opened for the first time... And let's be honest, the first impression counts!

Creating the database

Get the data you want into some format you can parse, e.g. XML, JSON or CSV.

Create your project, ensure that you select to use Core Data.

Copy your data file into your project

Setup your core data schema. I will assume core data familiarity in this article so if you are unfamiliar you should read this article on core data.

Write code to parse the file mentioned in step 1, and then save the data. My parser was as follows, and was located in my AppDelegate:

Basically, this new code copies the database from your project files to the directory where the databases are stored. If the copy is not performed, a new database will be created if no databases exist in the directory. Please note, if you are getting nil when unwrapping the value returned by "NSBundle.mainBundle().URLForResource("SpellingBee", withExtension: "sqlite")". Then you may need to go to your build phases and ensure all 3 sqlite files are added to the "Copy Bundle Resources" section. Good luck and happy programming!

Thursday, 3 December 2015

As with a lot of their recent products, Apple has made iCloud quite easy to setup. The following post will show you how to setup basic iCloud storage for an app:

Setting up

Go to Xcode and go to the capabilities section under your app's settings. You should set it up to look like this (most of which will automatically be done by Apple when you turn CloudKit on):

Go to your CloudKit dashboard and set up how you want your data to be stored by adding records. You can also add data to your public/private databases!

The Code

Surprisingly, there is also minimal code. Working with our previous records that we created in the CloudKit dashboard. This is the only code we require to fetch and update highscores (excuse the poor layout, I'm working with limited space):

The above code handles loading, creating and updating highscores. I have put this in its own class as I believe this avoids it complicating game logic. There were also some minor adjustments required in the GameViewController, I will only show the code I added: