Transitioning from Objective-C to Swift
While I was working in the Netherlands and had to use C++ under Windows in the office, I tried to continue with my Mac programming at the time, but this became quite difficult due to the heavy workload in the office. Programming on the Mac was not motivating enough to justify all the hard work to be performed at home in the evening after normal work had ended.
This situation changed when Apple introduced the iPhone in 2007. For the first time in history, we had a real computer on a mobile phone. Thus we entered an era of mobile computing.
I started looking into Apple’s programming environment from time to time. Steve Jobs brought the Objective-C language when he returned to Apple from NexT. It came with a mature set of libraries and made life easier for at least a decade. I used it occasionally for pet projects but did not do any serious programming. I started using Apple’s new XCode development environment. It must have been the 3.0 version, which introduced the iOS Software Development Kit, thus enabling developers to develop for the iPhone.
Apple’s libraries for iOS, just like its previous libraries for MacOS, were full of classes mostly following the Model-View-Controller (MVC) paradigm. In this paradigm, different aspects of a program were categorised and separated into different object classes. Data aspects would be in Model classes, whereas Visualisation was done through View classes. A third category was the Controller classes, which controlled the flow of information through the user interface and storage, thus allowing the user to process and persist the information. By keeping these three aspects in different classes, these categories would be independent from each other and there would be very little dependency on a different category if you wanted to revise some classes. For example, if you separated all data and storage aspects from the user interface, then it would be relatively easy to replace the persistence mechanism with no impact on the user interface (e.g. using an XML repository instead of a relational database).
Apple introduced the Swift language in 2014, within XCode 6. Although it has several improvements as compared to other object-oriented language, the definitive change is in the use of protocols. Protocols are a better way of extending existing functionality, since they can be applied to classes and structures and even to basic types (thus anyone can extend the functionality of the String type in Swift). When you use protocols, inheritance no longer becomes an issue (especially taking into account that multiple inheritance is a desired feature but is difficult to implement properly, whereas using multiple protocols is no issue at all.
I discovered Swift around 2018. I must say I did not do much that could be called serious, in the beginning. One of the advantages of Swift is that it has been made Open Source so that it can be used on other platforms and operating systems as well. It can also co-exist with Objective-C and as such can be used in applications with a lot of legacy code and can also use older libraries developed with Objective-C.
One of the problems in developing iOS or MacOS applications is the difficulty of designing and implementing the user interface using the UIKit and Interface Builder. Defining the so-called “constraints” and making the user interface work properly requires a lot of work. Although this is not a Swift-related problem, it makes the overall software development process much more difficult than it should be.
Declarative Programming with SwiftUI
While developers were struggling with XCode and Interface Builder, Apple was developing a new programming framework internally. Released during the June World-Wide Developers Conference in 2019, SwiftUI took the iOS development world by storm.
SwiftUI is built using Swift and is a declarative framework, in contrast to imperative frameworks and languages. Declarative frameworks reverse the traditional logic of programming in that they are built on declarations defining the user interface, with the logic separated from the user interface. Furthermore, Apple’s new SwiftUI framework can declare User Interface elements totally programmatically, although XCode also allows the developer to use menu tools to quickly declare the interface elements. Another advantage is that the declared interface can easily be previewed, thus giving the developer an instant view of what the particular interface will look like on screen.
The declarative UI elements used in SwiftUI cover all the aspects of UI development such as buttons, frames, checkboxes etc. SwitfUI also provides collections like List, VStack (a construct that stacks UI elements vertically on screen), HStack (same as Stack, but horizontally), Grid and so on. When you use these elements in your SwiftUI code, they can be used in different devices such as iPhone, AppleWatch, iPad or Macintosh, although the internal implementation would be different on each device. A lot of the code would be shared between devices like this.
SwiftUI is more suitable for using the MVVM (Model-View-View Model) pattern, which requires an implicit mechanism for managing updates and leaving the interaction between the three elements weakly coupled.
SwiftUI inherits the object-oriented paradigm from Swift, but its main mechanism works much better with static structures (struct in Swift) rather than classes. Structures are on static memory (stack) rather than dynamic memory (heap) and as such they can not be easily revised. SwiftUI introduces the concept of state variables to solve this problem. A state variable is declared using the @State keyword and not only is it then allowed to be changed but any change then results in SwiftUI re-rendering the view(s) which are affected by this change (namely any view that was displaying anything depending on the state variable that has been changed).
An advantage of using structures instead of classes is the fact that these typically perform better than objects, which have a lot of overhead). Thus the automated updates resulting from state variable changes are often instantaneous.
Once you get used to this type of coding, you just concentrate on what should be displayed (and using which UI elements) and make sure any executed code changes the proper state variables.
Persistence Frameworks: Core Data and SwiftData
Apple provided an object persistence model named Core Data in 2005. Initially coded in Objective-C, it was later ported to Swift. The persistence mechanism used SQL databases, XML or binary format.
Using Core Data with containers of objects is quite convenient. However, the learning curve is steep and optimisation is difficult. The objects created become somewhat bloated when adapted to be used with Core Data.
One of the advantages of Core Data is that the persistence store on a device can be synchronized with stores on other devices using the CloudKit framework and Apple’s iCloud service.
Apple introduced a new persistence framework named SwiftData based on Core Data, in 2023. One of the advantages is that objects adapted for use with SwiftData are not expanded per se, but functionality is gained through macros automatically.
I have used SwiftData in a couple of projects, converting from Core Data with some ease. It is too early to say, but it looks like the use of SwiftData will make the persistence task easier.
Using Generative AI for Software Resources
I have always had a problem with the design of my iOS applications, since I did not have a designer or a team, so up to now my application designs have been quite bland and uninspiring.
I decided to try my hand at the new generative AI capabilities to improve the resources used for applications. I used ChatGPT with DALL-E 3 to generate iOS application icons and got quite usable resources.