Chapter 22
Pulling It Together
Time to weave all the components into a unified app.
This chapter weaves the components we’ve created into a nice, unified app and user experience.
To recap, we have created the following things:
- An infinite scrollview subclass of UIScrollview
- An Astrological Sign Provider that stores data about the various signs
- A Stars background that has 8 different layers of scrolling content
- A great looking radial menu with complex animations and a nice interaction mechanism that uses long presses
- An info panel that links to the C4 site
Now, to bring COSMOS to life, we need to address the following:
- Add the menu, background and info panel to the app
- Link the menu to the background via a selection action and the background’s
goto
method - Link the menu to the info panel via an info action
- Add a couple of ambient audio files that will provide background music for the app
So, let’s get to it.
The Main View Controller
Most of the work we’re going to be doing is centered around the main WorkSpace
. Although we’ll have to tweak a couple of classes, it’s the main workspace’s setup()
where we will be creating objects and linking them together.
First, if you’ve been using the main view controller to launch or test any of the work you’ve been doing, now’s the time to clean it up and change the background color to COSMOSbkgd
.
It should look like this:
let COSMOSprpl = C4Color(red:0.565, green: 0.075, blue: 0.996, alpha: 1.0)
let COSMOSblue = C4Color(red: 0.094, green: 0.271, blue: 1.0, alpha: 1.0)
let COSMOSbkgd = C4Color(red: 0.078, green: 0.118, blue: 0.306, alpha: 1.0)
class ViewController: C4CanvasController {
override func setup() {
canvas.backgroundColor = COSMOSbkgd
}
}
Stars
Adding the stars background is dead-easy, just create a copy of Stars
and add it to the canvas, like this:
class ViewController: C4CanvasController {
let stars = Stars()
override func setup() {
canvas.backgroundColor = COSMOSbkgd
canvas.add(stars.canvas) }
}
Done. Run it and you’ll be able to scroll through the COSMOS.
Menu
Adding the menu is pretty easy too. Just follow the same steps as above, and add the menu after you’ve added the background.
class ViewController: C4CanvasController {
let stars = Stars()
let menu = Menu()
override func setup() {
canvas.backgroundColor = COSMOSbkgd
canvas.add(stars.canvas)
menu.canvas.center = canvas.center
canvas.add(menu.canvas)
}
}
The Menu’s Frame (Explained)
We want the behaviour of the menu to be like this: The menu should open only when the user presses on it, i.e. not anywhere else on the screen. This is why we make the canvas small (i.e. 80x80). Since the frame is this small the interaction with the menu’s canvas is limited only to this 80x80 view.
Simple.
Info Panel
This step’s a cinch. Create another variable for the info panel, then instantiate it in setup()
and add it to the main view controller’s canvas after you’ve added the menu.
Then, go into InfoPanel.swift
and add the following line to it’s setup()
self.canvas.opacity = 0.0
Since the opacity is
0.0
the canvas automatically will not receive touches, so adding it over top of the menu is okay at this point and will not prevent the user from touching the menu
Your main WorkSpace
should look like this:
class WorkSpace: C4CanvasController {
let stars = Stars()
let menu = Menu()
let info = InfoPanel()
override func setup() {
canvas.backgroundColor = COSMOSbkgd
canvas.add(stars.canvas)
menu.canvas.center = canvas.center
canvas.add(menu.canvas)
canvas.add(info.canvas)
}
}
Connect the Menu & Background
To connect the menu and background we’re going to use a nice little trick: we’ll add a special type of action to the menu and link that with the background’s goto(:)
method.
Go into Menu.Swift
and at the very top of the file, above the class declaration, add the following line:
typealias SelectionAction = (selection: Int) -> Void
This is a type alias through which we’ll be able to assign a method from another class. The selection action is essentially the action to which we want to send the menu’s current selection.
Create a variable to hold reference to a selection action:
var selectionAction : SelectionAction?
Navigate down to createGesture()
and in the case .Cancelled
block add the following:
if let sa = self.selectionAction where self.menuSelector.currentSelection >= 0 {
sa(selection: self.menuSelector.currentSelection)
}
Since we sometimes set the current selection to -1, we need the additional
where
statement
Now, we have to add the following method to Stars()
:
func goto(selection: Int) {
let target = canvas.width * Double(gapBetweenSigns) * Double(selection)
let anim = C4ViewAnimation(duration: 3.0) { () -> Void in
self.bigStars.contentOffset = CGPoint(x: CGFloat(target),y: 0)
}
anim.curve = .EaseOut
anim.addCompletionObserver { () -> Void in
self.signLines.revealCurrentSignLines()
}
anim.animate()
signLines.currentIndex = selection
}
This method conforms to the same parameters as the SelectionAction
type alias we just created. It also takes an integer and figures out a target and animates to that point in its scrollview.
Finally, go to the main view controller, and add the following line:
menu.selectionAction = background.goto
Your main view controller should look like this:
class ViewController: C4CanvasController {
var background : ParallaxBackground?
var menu : Menu?
var info : InfoPanel?
override func setup() {
canvas.backgroundColor = COSMOSbkgd
background = ParallaxBackground()
canvas.add(background?.canvas)
menu = Menu()
menu?.canvas.center = canvas.center
canvas.add(menu?.canvas)
info = InfoPanel()
canvas.add(info?.canvas)
menu?.selectionAction = background?.goto
}
}
Run it and things should work like this for you:
Link Menu and Info Panel
The process for linking the menu and info panel is almost identical to the previous step.
In Menu.Swift
and at the very top of the file, above the class declaration, add the following line:
typealias InfoAction = () -> Void
Also, in Menu.swift
add the following class variable:
var infoAction : InfoAction?
Then, scroll down to the .Cancelled
section of the menu’s gesture and add the following condition:
if let ib = self.menuSelector.infoButton {
if ib.hitTest(location, from: self.canvas),
let ia = self.infoAction {
delay(0.75) {
ia()
}
}
}
Finally, go back to the main view controller and add the following line:
menu?.infoAction = info?.show
Run it, and you should see this:
Ambient Audio
There are two files that should be included in your project. We’re going to play as soon as the application launches.
In the main view controller, create the following two class variables:
let audio1 = C4AudioPlayer("audio1.mp3")!
let audio2 = C4AudioPlayer("audio2.mp3")!
Then in setup()
, loop and play them like so:
audio1.loops = true
audio1.play()
audio2.loops = true
audio2.play()
Now things are sounding stellar.
Initial Stars Offset
We prefer the stars to start offset from any particular constellation. So, open Stars.swift
and add the following line to the end of setup()
:
bigStars.contentOffset = CGPointMake(view.frame.size.width * CGFloat(gapBetweenSigns / 2.0), 0)
The Last Touch
If you haven’t already done so, now’s the time to update a couple of simple deployment settings.
Click on the COSMOS project at the top of the project navigator in Xcode. Then under the General tab, navigate down to the Deployment Info section. Choose the following settings:
- Portrait: selected
- Upside Down: selected
- Hide Status Bar: selected
- Requires Full Screen: selected
- Landscape left: unselected
- Landscape right: unselected

AAAAAAAAND