Mastering SwiftUI Development by Building Pomodoro Tracker — Step 3: All Swift’s Fundamental
Now that you have Swift’s Playground ready to be use, you can start jumping right away into the world of Swift. Mind you that, for any new programming language learner, you will have to tackle syntaxes first. All the fundamental construct that make up the bigger application, must be fully understood, before we begin developing any application.
But here is the trick: eventhough this is your first journey, you will still have to have your final application in mind. All the variable names, the application logic or modules that you use as the “hello world” must be structured in the way that what you develop is the final application.
Now that we are developing a Pomodora tracker, that’s what we are going to be use in the process of mastering Swift’s syntaxes. Great, let’s go!
Comment, variable, constant and data type
Let’s start with the initialization part of our application
Have a look: it’s somewhat C/C++, right? Or, to be exact, it’s Objective-C… minus semicolon.
A little explanations:
- To use comment, use /* */ for multiple lines or // for single line
- No semicolon! Yeah, finally! In this regard, Swift is Python. And that’s one of the thing I really love about Python: no semicolon. It looks so neat!
- But differ with Python, to declare identifier there are two options here: var, if it is variable that the value can be change later. Or using let, if it’s constant, meaning you can change its value after being declared.
- If the variable/constant type is not specifically stated, Swift will determine it using its values. So, username is string, because its given value of string. Meanwhile iteration is definitely integer because I specifically state it that way using Int keyword.
- If you run it using Playground, you need to have import UIKit for the first line of your code. Because we need to specifically told Swift compiler what will be the library that we use
Function
Function is the simples modularization technique in a software development. Here, first we call Swift function to get the current time and then we turn it to function for easy call. Finally, we call our function.
A little explanations:
- In line 1, we call localizedString which is a method within DateFormatter class to format Date value.
- Within the call to localizedString we can see all of the argument passed: from, dateStyle and timeStyle. If you are Python dev, you will recognize these as, “Owh, this is optional named parameters. So I can simply passed this in any order”. Nope, it’s not. It’s actually required parameter and you can’t reorder it. You can’t passed dateStyle first before from. Swift won’t let you. It may seems complicated, but don’t worry XCode/Playground will make passing the argument in correct order easy, sleek even!
- In line 5, well, we replacingOccurences within current_time of “.” with “:”. Neat eh?
- Now, in line 8, we declare our function getCurrentTime without parameter that return String value. As a Python developer, it kinda irk me to have curly braces to denote block of code. But, well, as Swift/Objective-C don’t treat indentation specially, they don’t have the means to start-end of a code block. Hence, they need to have curly braces { } to mark it.
You can read more about Function here.
Struct: A Rethinking of Class in OOP Paradigm
As an early adopter in Java (starting to code Java in 1997 is early adopter, right? Yep, that’s me. Java still 1.1 back then), it strikes me that Swift promote Struct better than Class. This is strange for me, because in my opinion Object Oriented Paradigm is the one paradigm that shapes software development industry since the end of 90s up until today. Sure there come Aspect Oriented Programming or Functional Programming, but no paradigm greatly affect software programming industry bigger than what OOP does. And OOP rely solely on three fundamental Class aspects: Encapsulation, Inheritance and Polymorphism.
But the way Swift promote Struct (which basically in the old days, just a custom data type consisting only with variables, no functions/methods) make me think that I may not need to construct my programming solution as pure classes design using all of its three fundamental aspects above. In Swift however, Struct may contain functions/methods: but it can’t have inheritance (yaiks!). So this means, only Encapsulation remains. I will not have to think about Inheritance and Polymorphism anymore.
Is that good? Well, maybe. See, if you are working on a modern software framework (UIKit, PyQt, Swing, etc..) chances are that you will not need to create your own complex hierarchy of classes. Those are already beeing done by that framework. You will simply focus on your solution for the problem at hand.
In my experience, your class become terminal class: class that will not going to be the parent class of any future class. Nor a child of any class. I always did this actually! In my thinking, “I may later restructure my class, so all the behaviour (functions/methods) and attributes (variables/fields) of a class that I work on will be the most complete one. If I later want to create parent class, I will extract several behaviours/attributes to new class”. This rarely happen though.
Even further, I still remember when I work solely using Java, I ended up creating only a singleton for my solutions (class with only one instance that being accessed using .getInstance()). Not thinking about Inheritance and Polymorphism. Lesson learned? Maybe what I mostly need is just a — in Swift paradigm — a struct! Owh well.. okay.
Swift will also create somewhat default “constructor” or let’s say initalizer method. So you can simply declare struct with all of its fields and .. voila, you can call its “constructor” to initialize those fields.
Swift promote struct to be the “faster class”: every instance of struct is distinct. It’s just a usual variable. There is no self when you access struct variable. This is actually what I always do in Singleton! I simply create class atrributes. Woa!
So, to summarize: Swift’s struct is actually a singleton class without Inheritance and self variable. Now, let’s see struct in practice below.
For those with keen eyes, “What about those mutating keyword?” Here here, in Swift perspective, you can only change the value of struct variables if value of this struct is defined as variabel/var, not val (constant). And swift will not know in advance whether you are going to create a var or a val. Hence, to let struct function change value of its variable member, you will need to specifically define method that will change variable using mutataing keyword.
I have one grudge though: the way struct implicitly create initializer method with full parameters for its variables kinda annoy me. This make this line of code become necessary:
var tomato: Tomato = Tomato(name: “Composing Fundamental Swift Articles”, state: true, start_time: Date(), finish_time: Date(), elapsed_time: 0)
What if I need to have 10 struct fields? Those neet to be part of initializer and if you add/remove fields, you need to change all of the caller! Yaiks!
Class Version of The Same Struct
Have a look at this code: a substitute of struct version above, but using class instead
Notice several things from above:
- There is an init() function but without func and no return value. This is constructor in term of OOP. With this, I can easily instantiate classTomato object (line 28) using simpler call (and more logical way).
- But, because there are fields that not get initialized in its call, I need to tell Swift that those value maybe nil. So, for finish_time and elapsed_time I need to mark that as optional variables using question mark: variables that may have value of nil.
- And because of that too, in line 23 when I calculate elapsed_time using finish_time (which is optional) I need to either unwrapped it using ?? to let Swift give value of non nil to elapsed_time, should finish_time is nill or force unwrapped it using exclamation mark to force Swift using that value because I am confidence it’s not nil.
Got to say, how Swift carefully treat nil value is striking for me: in Python, well, it’s up to you to treat or not treat nil/None value. So, your code may crash if you don’t plan carefully for nil value.
Control Flow
Dat switch verbosity! Woa. Have a look at this official Swift guide about control flow: for loop, while, if, if .. range is okay. Good one. But dat switch verbosity.. just woa! I think it need its own article later. But for now, the following mandatory control flow is good enough:
Conclusion
As a veteran developer, I am beginning to appreciate Swift fundamental syntaxes. It really is the marriage between Python and Objective-C. The one with struct vs class will need a more thorough explanation, but for now I think the notion that Swift prefer struct over class is a good starting point for your journey. As for the switch clause.. that thing really need its own study case! Awesome!
In the next article, we are going to start our software development journey with Swift UI, but for now… au revoir!