How to write an iOS app without knowing Swift

Writing an iOS Application Without Knowing Swift

One year ago, I didn't know anything about Swift, but I decided to learn this language in order to complete a test assignment for an internship. Now I can proudly call myself a Junior iOS developer at Doubletapp. But first things first.

Writing an iOS Application Without Knowing Swift


Polina Skalkina


Polina Skalkina

Writing an iOS Application Without Knowing Swift

July 2020

After the end of my first year at the university, I, floating on a cloud after passing my end-of-term exams, applied for an internship at Doubletapp for the position of an Apple development intern. I knew almost nothing about Swift and mobile development, but I really wanted to try my hand at it. Back then I was thinking, "what if I will be able to complete my test assignment with the knowledge that I have right now"? YouTube, Stackoverflow and advice from my friend who worked with mobiles devices at Yandex were used.

In this article, I, now a junior iOS developer, will analyze the code that I wrote without having any idea about the Swift programming language. I do not claim to be an expert, however, the material can help those who want to start in iOS development, make their first application or – like me – complete a test assignment. Let's go!

At the bottom of the article I will share the materials that helped me a lot, so read to the end!

My Results

The gist of the test assignment was to create a simple note taking app. Three screens were required to be completed: an overlay for all notes, a view screen and a screen for creating/editing notes. This is what my application looked like when I submitted it for review:

Warning! Disturbing content. The source code can be found here:


At the very beginning, I did not know how to create a project using Xcode, how to launch it, and in general what a mobile application was. Many videos from YouTube helped me, where everything was described in detail. All of them are in the public domain.

In a course from Yandex, the MVC (Model View Controller) design pattern was proposed, which they called (and it really turned out to be) the simplest and most convenient. In general, this template in its most primitive sense is suitable for creating small applications, like mine. I recommend reading about it and using it at the initial stages of working with mobile applications.

And now to the tools used


To begin with, I would like to tell about the things that, it seems to me, were brilliant solutions at that time.

UINavigationController – navigation panel

In almost all of the applications, we have the need to switch between screens. I have found two ways of managing this (they must be the ones most frequently described in the articles I have studied), using present and UINavigationController. In general, these two are fundamentally different and this is how they look like.

1 – push, 2 – present

They have a technical difference among them. The first one – UINavigationController – is a container controller that puts other controllers inside itself and creates a convenient navigation stack, allows to build a competent hierarchy of view controllers with screen replacement, makes it possible to return to a specific previous vc. The second one – present – is simply a method for layering controllers on top of each other, not an organized system.

Let's see what the UINavigationController looks like. This is a class that inherits from UIViewController. In order to use it, we have to create an instance of this class and install a root vc to it – a controller, which will be located at the bottom of the stack.

I did this using IB (Interface Builder). Here, as a root I have selected a tablet with                

One of the main advantages of UINavigationController is the presence of an automatic customizable header menu. With the use of it, I can move from the root to creating or viewing a note and back.

By the way, initially I tried to do everything with the help of present, but I could not adequately build a hierarchy of controllers. I have chosen to rewrite everything using NavVC, when the work was coming to an end, and this decision turned out to be a success.


I stumbled upon another obstacle – I needed to transfer data from controller to controller. I found a seemingly good way – Segue. This is also one of the ways of switching between controllers, but this one can also transmit data.

But the problem with using it is that we may forget to transmit something, or try to use data that does not exist, or something else similar to this... Using Segue, when we transmit some, for example, variables, we can only use them after assigning them to some fields of the destination controller.

A delegate is a protocol, a set of instructions that the class implementing this protocol undertakes to execute. At first, I couldn't figure out how delegates work for a very long time, so I'll show you an example.

I have a screen for creating/editing notes, which I can access to from the overlay of all notes. I need to have the data transferred to the database each time I click the "Save" button. I initially made a save method in the edit controller. But a good friend of mine, to whom I showed my test assignment prior to sending it to Doubletapp, told me that it would be cool if I used delegates. He also proposed to transfer the saving section to the root view controller.

To do this, we create a delegate protocol, through which we can communicate with the root vc, where the save method is located. Basically, we can create it in a file with an edit controller:

protocol EditNoteViewControllerDelegate: AnyObject {
    func save(note: Note)

Then, we create a delegate variable, also in the edit controller, using which we will be able to address the functionality that the protocol provides:

weak var delegate: EditNoteViewControllerDelegate?

Now we go to the class where we will have the save function. We create an edit view controller for pushing to the NC stack, assigning the value of the delegate field:

let editViewController = EditViewController(note: nil)
editViewController.delegate = self
self.navigationController?.pushViewController(editViewController, animated: true)

And now, to use such a delegate, we implement the delegate protocol with the save function in our root controller:

extension ViewController: EditNoteViewControllerDelegate {
    func save(note: Note) {
        try! realm.write {
            realm.add(note, update: .modified)
        items = items!.sorted(byKeyPath: "dateTime", ascending: false)

Now we can safely use the save function directly from the note edit controller

It is advantageous to use such delegates because of convenient data transfer in the MVC template, absence of code duplication (after all, if a code expansion occurs, the save method can be called not only from the EditViewController) and separation of responsibility when, for example, we want to transfer data from the listener class of user actions to the handler class of these actions.

It is important to mention that the method of data transmission via Segue is not bad at all. It's just that delegates were more suitable specifically for performing my task.

Let's move on.


Speaking of the interface, I was praised for several things that I still see quite worthy. I won't go into the details of their implementation, they were made based on a certain UI and UX experience. Test assignment at the "pending for review" stage is a small project, but a project nonetheless, this is why I wanted to make it look as impressive as possible.

The lack of text overlap with the keyboard and the creation of a placeholder for the TextView using UITextViewDelegate (this method has been blatantly written off, but we will omit this detail) were highlighted among the interface advantages.


All good things come to an end at some point. Now I want to move on to the dark side of this test assignment.

Force cast and force unwrap

When studying Swift, you will definitely encounter casts and unwrapping values. If you haven't encountered them yet, then be sure to read this!

So you are trying to cast, for example, a UIViewController to a UINavigationController. You are sure that the cast will be successful and you write:

(someViewController as! UINavigationController).doSth()

You are rather proud of yourself, just as I was when I wrote this force cast. However, after launching the app, an error in runtime occurs. When it comes to casts, the programmer must become an extremely doubtful being, because the casts themselves are really unpredictable.

You are rather proud of yourself, just as I was when I wrote this force cast. However, after launching the app, an error in runtime occurs. When it comes to casts, the programmer must become an extremely doubtful being, because the casts themselves are really unpredictable.

My use of force casts and force unwraps was one of my mistakes.

In general, the type conversion mechanism returns the cast result if successful and nil if the cast did not occur (this is if we use "as?" instead of "as!"). Along with this, unpacking allows to make a 100% non-optional value from an optional one.

Especially for people like me, Swift developers have come up with tools for checking nil values. I was confused about them at first, so I want to elaborate to you on how they work.

Here they are, from L to R:

1. A clean check for nil. If the value is not nil, the operation continues. If the value IS nil – nothing happens. In the example below, if there is nil in someObj, the function will not be executed. And vice versa.


2. Protection against a nil case. This syntax is used if we want to replace a variable with a default value when a nil case happens.

nonOptionalVar = optionalVar ?? defaultValue

3. A check for nil with the further use of a value if the result was not nil. You can also specify what exactly should be done if the nil still returns.

func do(optionalVar: Int?) -> Int
	if let internalVar = optionalVar {
		internalVar += 1
		return internalVar
	} else {
		return 0

4. The strictest check is a defender against the nil-case, which also allows the code to be executed in the case of a nil value, as a rule, some kind of terminating one (for example, return). Used to avoid unnecessary nesting, the resulting non-nil variable can be used further.

guard let newVar = optionalVar else { return }
newVar += 1

Well, here you go. This is a quick guide list to nils and everything related to them.

Scattered layout system

Let's finally figure out what is the difference between a storyboard and a xib file. After all, this question torments all novice iOS developers.

It is worth explaining, to begin with, what is the difference between UIView and UIViewController.

  1. A UIView is an object that manages the contents of a rectangular area of the screen. Roughly speaking, this is the area of representation of some other objects (text, images, etc.).
  2. UIViewController is a class that is responsible for the logic of controlling elements on a single screen. This controller has its own UIView, which is the screen itself.

Now let's go back to the layout files.

  1. .storyboard is a file, which can contain several controllers and trace the connection between them.
  2. .xib is a file containing user interface elements, that is, one or more UIViews. In order to present a file on the screen, a code that initializes this file and uploads it to the shared system needs to be written.

Theoretically, you can use both of these files (both xib and storyboard), but definitely not at the same time, as I did in the test assignment. Let's analyze the pros and cons of each of the methods.

A picture

From this, we can conclude that in small applications, you can use a storyboard. But this doesn't work in our case, because the storyboard uses Segue for transitions. I used NC, which means that it was much more convenient to use the system on xib files.


This is something that I did not understand at the beginning of the first year of the university. I've heard before that there are some principles, and they should be adhered to, but I didn't understand why. This point rather refers not to writing an application for iOS, but to the general philosophy and programming paradigm.

There are three main principles of OOP: encapsulation, polymorphism, and inheritance. We will not be talking about them in detail, because this topic is too broad for an article such as this one. I would better advise you to read this article if you have not yet encountered the principles of OOP:

Speaking of how OOP should be done, I recommend you this article, that also touches upon the principles of SOLID:

Speaking of SOLID, I figured out that my test assignment work did not follow the principle of Single Responsibility – the first "solid" principle. This was due to requests to the database being in the root view controller

One more thing

During the internship, I got acquainted with reactive programming. Awesome thing, to be honest. If you have worked with it in other programming languages, then it will be a plus for you if you understand how it works in Swift and if you manage to implement something using it during your test assignment. But if you don't know what it is yet and have never tried it, you should not try to wedge RxSwift into your test project and spend a huge amount of time studying it.


This was the first test assignment in my life. The first experience in creating a product from scratch (although it is still far from a real product). Now, of course, I can do a lot more things than a few months ago. This internship has provided me with a big volume of knowledge and experience.

It is very interesting to learn some things at the uni, and then immediately apply them in practice, at work.

Of course, now I want to know even more. More about design, about some slightly less applicable and slightly more philosophical things. In addition to working on large projects in Doubletapp, I want to try to do something of my own, using my existing knowledge, and publish it in the AppStore.

I got very hooked on the development for iOS. Among the abundance of languages and technologies that are shoved into us at the university, Swift seemed to me very pleasant and suitable for what I am working at right now. Xcode is, of course, laggy, but this is a whole different story :)

I hope this article will be useful for those who are venturing in iOS development and for those who are completing test projects for companies of all kinds at this moment. Don't make my mistakes and good luck at the job interviews!

Well, I have to go now! Derived Data needs to be cleaned.

Useful links that I promised to share:

1. – getting to know swift from zeroest zero.

2. – a course from the Yandex Academy. Not that I understood everything the first time, but I recalled many things from this course in the process of watching other training videos and articles, and each time I was like, "Oh! I UNDERSTAND NOW". A good theoretical basis.

3. – this person, as it seemed to me, explains the theory very intelligently and seasons it with practical aspects.

4. – here it is shown well how to connect the UINavigationController to an application.

5. – a short but informative article on reactive programming

6. – a full course on RxSwift. Very cool, very detailed and practically useful. However, as far as I remember, it is rather outdated and does not quite work with the current version of XCode. Older versions can be found on the Apple website. The course is not free.

Discuss article on social media

Similar news

step 1: choose service

mobile development

web development

machine learning



technical requirenment