Daniel Jørgensen – djoer16
Mikkel Schmøde – mschm16

Table of contents

  • 1 Introduction
  • 2 Methods
    • 2.1 Brainstorm
    • 2.2 Conceptual design
    • 2.3 Simple prototyping
    • 2.4 Evaluation
    • 2.5 User stories
    • 2.6 Implementation
      • 2.6.2 The classes contains
    • 2.7 Evaluation 2.0
  • 3 Results
    • 3.1 Brainstorm
    • 3.2 Conceptual design
    • 3.3 Simple prototyping
    • 3.4 Evaluation
    • 3.5 User stories
    • 3.6 Implementation
    • 3.7 Evaluation 2.0
  • 4 Discussion & conclusion
    • 4.1 What’s next
  • 5 Inspiration sources & bitbucket

1 Introduction

Imagine an interactive version of testing your eyes – that is how iYi came to be.

The name iYi is a pronoun play on the word eye.

iYi tries to be a gamification of many of the various eye tests that is used today. The main focus lies with the classic eye test, that one may get at their doctor, its also called a snellen chart. But outside of that any eye test that can be gamified is fair game for iYi. The base premise for each of the games is to look at your phone, and then choose the correct answer, based on what you see. You will be able to choose your answer either with movement of the phone, or with touch. You will be granted points based on your performance, while each correct answer will increase the difficulty. Something to preface is that iYi does not aim to replace real eye tests, but take a different approach to potentially create awareness for ones eyesight. iYi does however try to replica the real tests parameters as much as possible. For the classic eye test(snellen chart), that means the same font is used, and each difficulty level is making the text smaller, just as it would be on a snellen chart at the doctors.

In order to produce iYi it is clear that one must be able to understand the basics of xCode, and Swift. Be able to understand working with a few of the kits such as, UiKit and CoreMotion, while being able to reproduce these various eye tests in iYi.

Therefore that is also the main focus of the group, to understand the basics of above mentioned technologies, and fields.

So to sum it all up. The group aims to bring at least one of the common eye test to the iOS platform, in an intuitive app, that allows for gamified versions of the tests. Which in turn could raise awareness surrounding your eyesight, which could prompt you to take a real eye test.

2 Methods

2.1 Brainstorm

Before the emerging of iYi, the group started out with a brainstorm. This brainstorm was focused around the ideation creation of an app that would use at least one of the many sensors that exists in current apple products. One thing that felt more natural when talking about an app that has a focus around sensors, was that it had some sort of game element over it. Not that is had to be a game, but more in the sense of it drawing inspiration from games.

2.2 Conceptual design

After the seeds of the idea that would come to be iYi had been planted, the next logical step was research a bit. This was done so that the group would have knowledge of the various resolutions that iPhones, and such use. While also searching for similar idea minded apps in the google play store and the App store. All of this was used to create some initial design ideas for how the various views could end up looking.

2.3 Simple prototyping

The creation of the first prototype, was just focused around getting to know xCode, and swift better. So messing around with the various options of xCode, and the creation of the multiple views.

2.4 Evaluation

This evaluation took place after the first presentation of the project(portfolio part 1). It became clear that a few changes needed to happen, as well as the need to focus the scope of the project a bit, in order to create a decent, but working prototype.

2.5 User stories

A tool that the group used was user stories. This was used in order to get a better grasp on what was needed of the program, for it to be useful for the user. The simple prototype was showed to family and friends, while letting them know what the base idea was. That feedback was then used to create the user stories.

2.6 Implementation

The logo used for iYi, as well as the final design mockups are homemade in adobe illustrator.

There is an assets folder, which contains all images and sounds used in the app.

Frameworks used: AVKit, UIKit and CoreMotion.

Main.storyboard is also used to show the linking between the various views, in terms of layout, and the layout itself.

Each view has their own viewcontroller. They are called ViewController<insert name>.swift.

There is 5 views:

ViewControllerMenu.swift, ViewControllerPlay.swift, ViewControllerHowToPlay.swift, ViewControllerDone.swift, and ViewControllerHighscore.swift.



The first screen the user is presented. Here they can get to all the other views, except Done.


This a view with static text, that explains how to play the game/do the tests.


This view shows the current highest score on the device, you can also reset it(delete all local data). The current highscore is saved


This view is the snellen chart, where you are present with 3x of 3 random letters. One in the middle of the screen, as the challenge, and two at the bottom left and bottom right respectively. These 2 are the answer options. 1 of them(random) will be the same as the middle one, and therefore the correct choice, while the other one is different. The letters used all come from an array called letters, containing all the letters from A – Z.

2.6.2 The classes contains

ViewControllerMenu class contains the following:

2 methods:

  • viewDidLoad() : all the things within this method loads once the class is loaded
  • viewDidReceiveMemoryWarning() : is called before an out-of-memory crash. Not other crashes.


ViewControllerHowToPlay class contains the following:

1 Action(method):

  • HowToPlay(_ sender: Any) : sends the user back to the menu view.


ViewControllerHighscore class contains the following:

5 variables:

  • HighscoreLabel: UILabel! : label used to show the user the highscore
  • readString : String that will contain the highscore
  • fileName : contains the name of the file with the current score.
  • DocumentDirURL : the url of the file.
  • fileURL : Finds the url file at the url.


3 methods:

  • viewDidLoad() : all the things within this method loads once the class is loaded
  • loadHighScore() : loads the highscore, this method is within the viewDidLoad.
  • ResetHighScoreData() : resets the highscore to 0.


2 Actions(methods):

  • back(_ sender: Any) : sends the user back to the menu view.
  • ResetHighScoreButton(_ sender: Any) : resets the highscore back to zero, by calling the method(ResetHighScoreData(), and loadHighScore()).


ViewControllerPlay class contains the following:

21 variables:

  • motionManager : A variable of motionManager.
  • score : Int contains the score.
  • count : Int contains the rounds number.
  • fontSize : CGFloat : initialize the fontSize variable where 100 is the default font size, in the beginning of the game.
  • readString : used to parse data to the labels, is empty by default.
  • MainLabel: UILabel! : label used to display the letters in the middle of the screen.
  • LeftButtonLabel: UILabel! : label used to display the letters in the bottom left of the screen.
  • RightButtonLabel: UILabel!: label used to display the letters in the bottom right of the screen.
  • letters : array, contains all the letters from A – Z.
  • leftOrRight = [1, 2] : initialize an array where 1 is left, and 2 is right.
  • correct = 0 :  initialize a variable, that controls the side for the correct answer.
  • abc : initialize the string, with the correct 3 letters
  • def : initialize the string, with the wrong 3 letters.
  • audioPlayer : the sound player.
  • correctSound : correct sound.
  • wrongSound : wrong sound
  • back : back sound
  • fileName: name of the file with current score
  • DocumentDirURL : holds the url to the file
  • fileURL : hold the url, and the filename +.txt
  • writeScore = contains the score.


8 methods:

  • randLetters () : randomizes the 3 random letters.
  • setLetters() : sets the labels from the two strings, abc and def.
  • ViewChange() : changes the view to the done view from the ViewControllerDone.
  • compareHighScores() : used to compare the highscore, with the current score.
  • save() : used to save the highscore
  • load() : used to load the highscore.
  • AVAudioPlayer() : the soundplayer.
  • viewDidLoad() : everything within this method is loaded when the view is loaded.


3 actions(methods):

  • Back(_ sender: Any) : back button
  • LeftButton(_ sender: Any) : left answer button. Hold all the other methods for the logic used when button is pressed, and it hold either the wrong answer, or the right answer.
  • RightButton(_ sender: Any) : right answer button. Hold all the other methods for the logic used when button is pressed, and it hold either the wrong answer, or the right answer.


ViewControllerDone class contains the following:

8 variables:

  • ScoreLabel: UILabel! : label that tells the score.
  • back : backsound.
  • forward : forwardsound.
  • audioPlayer : the soundplayer.
  • fileName: hold currenscore name.
  • readString : initialize varaible where the data will be stored.
  • DocumentDirURL: holds the url for the file.
  • fileURL : combines the documentdirurl, and filename, into the whole path with the addition of .txt.


1 method:

  • loadScore() : loads the current score.


2 actions(methods):

  • PlayAgain(_ sender: Any) : Sends the user back to Play, with a new game session.
  • Menu(_ sender: Any) : Sends the user back to the main menu.

2.7 Evaluation 2.0

Once again the group presented the now functioning prototype to the same audience as before. A lot of feedback was gathered once again.

3 Results

3.1 Brainstorm

The result of the brainstorm was a quite a few bland ideas. One seemed to peak more interest, as presented itself with an interesting approach. That idea came to be the building block of what would become iYi.

The idea was to take the classic eye test that one usually takes at the doctor(snellen chart), and turn it into a mini game, where you would be presented with 1 line of a few random generated letters, and then 2 options would be presented with it. In order to choose your answer, you would have to tilt the phone towards the direction of the answer.

3.2 Conceptual design

The apps that was found to be somewhat based around the same idea from the app store and google play store, was: Eye Check – Sight test, and Color blindness test Ishihara.

The group studied these two apps look, to get an idea of how a design could end up looking.

All in all that resulted in some mockups that was then turned into the first prototype.

Some of things that was finalized in this phase, was that the snellen chart test would be a series of 3 letters. These would be shown in the middle of the screen, with the options shown near each side of the screen, to imply that by tilting the screen to the left, then you would choose the left option. The focus was therefore to make the design simple and intuitive.

3.3 Simple prototyping

Based on the previous chapter some mockups was created, and they were used for the first presentation(portfolio part 1).

Some of the mockups above in the iPhone X frame.

The mockups was stitched together first in Adobe XD

Adobe XD link: https://xd.adobe.com/view/051e4e05-3575-4af8-4254-23d1a0c21590-732f/

After the presentation they were coded very simply in xCode. They were not coded with any logic, but just with the basic implementation of being able to switch views, when you click on the corresponding menu point. This was mainly done to get some extra work in on working with xCode, and to setup the future repository for iYi.

3.4 Evaluation

After the first presentation the group got some valued feedback, and made the changes accordingly. First of all a dedicated exit button, is not really used by other apps, so therefore it was removed from the design. The various test would be put under one button called: Play, instead of being separated in the main menu. When a user press play, then they would get to choose what test they would want to take/play. The whole color scheme was changed to a dark theme and feel, to be less of a strain on the eyes. The font used in the app was also changed to fit that of the snellen chart, which is: Courier Std Bold.

It was also decided that all tests and functionalities would be on hold until the snellen chart(eye test) had been fully implemented, in a working prototype, that fits the design.

3.5 User stories

A normal user story usually looks like this:

As a <role> I can <capability>, so that <receive benefit>

The feedback the group gathered from friends and family resulted in the following user stories:

  • As a user i can take any of the tests, wherever and whenever i want.
  • As a user i can take a test, and it remembers my highest score.
  • As a user i can take any of the tests without having to sit or stand in a specific way.
  • As a user i want the UI to be simple and straightforward, so that i can find anything in the app fast.
  • As a user i don’t want the phone screen to rotate, when i tilt the phone, so that i can enjoy the test.

Following the user stories, the group decided the lock the app in landscape mode, to force a design and feel that was the same throughout the whole app.

3.6 Implementation

Here are some of the important code snippets from iYi.

Below is how the random letters are generated in iYi. It contains the array letters that holds all letters from A – Z. Then in the function randLetters, a random letter from the array is chosen, and then put into a variable known as a, b, c, d, e and f. After that a,b and c is put together, while def is put together. Then at the end, which button who will be the correct one is chosen, with the randomelement on the correct variable.

// initialize an array of all characters of the alphabet
let letters = [        
       "A", "B", "C", "D", "E", "F", "G",
       "H", "I", "J", "K", "L", "M", "N",
       "O", "P", "Q", "R", "S", "T", "U",
       "V", "W", "X", "Y", "Z"

// This function generates the 3 random letters.
func randLetters () {
       let a = letters.randomElement()!
       let b = letters.randomElement()!
       let c = letters.randomElement()!
       abc = a + b + c // converts the 3 random letters to a string.
       let d = letters.randomElement()!
       let e = letters.randomElement()!
       let f = letters.randomElement()!
       def = d + e + f // converts the 3 random letters to a string.
       correct = leftOrRight.randomElement()! // Makes the correct either 1 or 2.

Below is how what button ends up being the correct answer is chosen. This is done by a few simple if statements. If the variable correct is 1, then the left button becomes the correct one, as it ends up holding the same values and the mainlabel, while if the variable is 2, then the right button becomes the correct one. The variable correct is set in the function randLetters, that was shown above.

// This function sets the labels from the two strings, abc and def.
   func setLetters(){
       MainLabel.text = abc // sets the mainLabel to ABC
       if correct == 1{ // If the correct is 1, the right answer will be on the left side.
           LeftButtonLabel.text = abc
           RightButtonLabel.text = def
       if correct == 2{ // If the correct is 2, the right answer will be on the right side.
           LeftButtonLabel.text = def
           RightButtonLabel.text = abc

Below is how the highscore is saved, and loaded. This is done by saving the score unto a .txt document. This document is saved locally for the unit. The directory that it is saved under can be seen in the variable DocumentDirURL. The fileURL variable appends the path to the file, which is in DocumentDirURL, with the fileName that holds the file name, and then at the end adds the filetype: .txt.

func save(name:String, Pointscore:Int) {
       // Local variables
       let fileName = name // The name of the file with the current score
       let DocumentDirURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)// The url of the file
       let fileURL = DocumentDirURL.appendingPathComponent(fileName).appendingPathExtension("txt") // The url of the file
       let writeScore = String(Pointscore) // Converts the writeScore value to a String that contains the score.
       do {
           // writes to file
           try writeScore.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8)
       catch let error as NSError{
   func load(name:String){
       let fileName = name // The name of the file with the current score
       let DocumentDirURL = try!  FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) // The url of the file
       let fileURL = DocumentDirURL.appendingPathComponent(fileName).appendingPathExtension("txt") // Finds the find at the url
       do {
           readString = try String(contentsOf: fileURL) // reads the file and saves it in the readString variable
       } catch let error as NSError {

Below is Gyro function which can be explained as follows:

First of it start with setting the interval that it need to do the measures with. Next it starts. Then it checks what orientation the phone is in, and that is then placed into 2 if statements. In those statements the rotation rate is checked – whether its higher than 3 or below -3, which means that the phone is tilted. When the if statement becomes true, then the appointed button is then activated, as if it was clicked.

func gyro() {
       motionManager.gyroUpdateInterval = 0.15 // Default value 0.15
       motionManager.startGyroUpdates(to: OperationQueue.current!) { (data, error) in
           if let myData = data{
               if (UIDevice.current.orientation == UIDeviceOrientation.landscapeRight){ // checks the orientation of the iphone
                   if myData.rotationRate.x > 3{ // Default value 3
                       let button = UIButton()
                   if myData.rotationRate.x < -3 { // Default value 3
                       let button = UIButton()
               if (UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft){ // checks the orientation of the iphone
                   if myData.rotationRate.x > 3{ // Default value 3
                       let button = UIButton()
                   if myData.rotationRate.x < -3 { // Default value 3
                       let button = UIButton()

3.7 Evaluation 2.0

The feedback gathered from the test group provided some interesting results. Some found it a bit odd, that the app was locked in landscape mode, but they did express that the layout seemed to work as intended. The game was tested on a iPhone X, and the test group found the game somewhat enjoyable, while also having some struggles as the text got very small.

So all in all, the 2.0 version fulfilled the base idea a lot better than 1.0.

Some changes were acted upon right after these tests. One such thing was to change the layout type to fit older models of iPhone. This showed a clear flaw in the program, as it was programmed upon layout pictures the group had produced. This whole process would need another iteration, which will be discussed in chapter 4.1, as  well as other interesting things that was gathered from these tests. Overall a lot of useful feedback for setting up a clear goal for what could become version 3.0.

Here is a video of the final 2.0 version in action:

4 Discussion & conclusion

Something that became clear, was that in order to get a hold on working with xCode, and swift, the scope of the project needed to be tighter. Which it did become, as only the classic eye test(snellen chart) was developed, as opposed to the suggested color blind test, that was featured in version 1.0. The design underwent quite some changes, as the group gathered more knowledge and feedback, which resulted, in some of the assumptions to be changed. Among those were that the version 1.0 had a dedicated exit button, which is not really seen on most apps these days, and therefore it felt redundant. The color scheme used, was also changed into a more dark theme, in order to be more pleasant for the eyes to stare at the screen, for longer periods of time. It also became clear that the group had failed to foresee that the layout would have to be truly dynamic if it was to work on multiple apple devices, in terms of usability, and feel.

So with respect to the groups introduction, did iYi fulfill the goals set upon it?

To some extent yes, as it ended up with a simple, but straight forward UI and feel, while bringing at least 1 common eye test to the platform – in the form of the snellen chart.

Whether or not it will bring awareness to the eyesight, or the people playing it, is hard to tell. This is mainly due to 2 factors. The first being that the sample size for testing has been small or limited, and therefore you can’t really conclude whether or not the product actually gives the desired value. It is true that the test subjects enjoyed the game, but that is not to say that they would consider going to an eye doctor, if they received a bad score. The second reason lies with the fact that most people do not at least as of yet, use games to “diagnose” themselves with things. Now that being said, it was stated that iYi did not aim to replace eye tests, but mere to turn it into a fun piece of game, with the possible side note, that it could raise awareness for people with bad eyesight.

4.1 What’s next

So what’s next, well if iYi was to have a 3rd iteration – then that would most likely feature, a slight overhaul of the way the design is brought to life, in order to secure, that it would look, and feel good on new as well as old apple devices. The color blind test, that was featured in iteration 1, would most likely make its return, as a fully playable test/game.

5 Inspiration sources & bitbucket

Bitbucket repository link: https://bitbucket.org/iosprogrammingsdu/iyi/src/master/

An appendix with all the links to places the group has gained help with creating iYi, either from copying small snippets of code, or guides to usage of certain aspects in xCode.

Leave a Reply