Here, the result array is passed to the completion handler, which passes the data when the asynchronous operation completes.
Completion handlers are just one way to fix asynchronous code issues. Sometimes, a simple rearrangement of the code will do the trick.
Running UI-related code outside the main queue
A good programming practice is only to execute UI-related code, such as updating the user interface and handling touch events inside the main IOS queue.
The main reason is that UIKit—the library that handles iOS UI components—isn’t thread-safe.
Executing any of its functions on a background thread can introduce unexpected behavior and even cause a crash.
Here, you tell Swift to explicitly execute the myLabel.text update to the main queue.
This is a good practice to get in even when using libraries, such as Alamofire or AFNetworking, that call a completion block on the main queue because you can’t rely on this happening all the time.
Misunderstanding concurrency and multithreading
Concurrency is a programming capability that allows you to execute multiple codes simultaneously by placing them on separate threads.
Think of a thread as a separate process, each executing some part of your program in the background.
In short, concurrency is a powerful tool as it allows your apps to run faster and more efficiently.
For instance, you can assign background tasks like retrieving data from a database to another thread, so that the app doesn’t freeze on the main thread until the background task is completed.
Using concurrency and multithreading in iOS development is powerful but also dangerous if misunderstood.
One common pitfall is when two concurrent processes try to access the same resource. Here’s an example:
In this code, one queue tries to add a new item to the myArray array while the other attempts to read it.
This leads to a race condition, a situation where multiple changes are attempted on the same object, thus producing unexpected results. At worst, it could corrupt the data.
To solve this, the programmer should synchronize access to a resource via the sync method. Here’s the modified code:
In this scenario, the array manipulations are done within a serial queue, thus ensuring that only one queue can access it at any given time.
Not knowing the drawbacks of mutable objects
In programming, mutable objects are those that can be changed or modified after they’re created.
For example, they give the developers added flexibility by transforming a class from one state to another.
The problem is that mutable objects can be unpredictable during execution. This makes your code difficult to read, test, debug, and maintain.
More problematic is that mutable objects are not thread-safe, which means asynchronous processes can’t use synchronization methods to lock exclusive access to them.
This leads to the race condition problem we discussed in the concurrency section.
A good practice is to use immutable objects as much as possible, since that makes your code much safer and more manageable.
If you want to modify something in a class, creating an instance of it is better.
One exception is if you have an exceptionally large object. Creating instances of it might cause your app to slow down. In this case, it might be better to make it mutable.
In short, knowing when to use mutable and immutable objects, and using them prudently, is crucial.
Using storyboards instead of XIBs
Apple gives you multiple ways to design your app UI in XCode, the official iOS IDE. One that’s recommended for most beginners is the storyboard.
In storyboard mode, you create app screens and then connect them by dragging and dropping. It’s a visually intuitive way to assemble your app UI, which is why it’s so accessible.
However, storyboards have several disadvantages that make them unsuitable for larger projects.
One of the biggest is that storyboards are ill-equipped to handle complex navigation flows, such as multi-step forms, wizard-style interfaces, or custom transitions.
You can’t customize storyboards as much nor reuse elements. It thus forces you into a generic, non-modular design.
In those cases, the better alternative is to use XIBs or XML Interface Builders:
The issue here is that it’s not clear what the number 756 represents. Why is it a specific number, and what’s the logic behind it?
Furthermore, you don’t even know if 756 is in minutes, hours, or seconds.
As you can see, hardcoded values make your code difficult to comprehend.
Another issue is if you need to reuse that value multiple times in the code. In that situation, you would need to retype it each time, increasing the chances of making an error.
The better approach is to define the value as a constant using the define statement.
In the above code, “print(“Excellent!”)” will execute since the grade variable has a value of “A.”
The last case, default, is a catch-all when none of the options are applicable. However, sometimes, using it can lead to unexpected results.
For example, if we were to introduce a new grade level, “A+” and forgot to revise the switch statement, the program would return “Invalid grade” even if the “A+” value is legitimate.
To get around this, a good practice is to list the switch options in an enum object instead of the default keyword. That way, oversights can be identified and fixed at compile time.
Not writing secure code
Security should be a top priority during coding. Unfortunately, this might not be the case, as developers might be focused more on making their code work by whatever means necessary.
Unfortunately, insecure code can introduce vulnerabilities that hackers can exploit.
Skilled in React Native, iOS and backend, Toni has a demonstrated knowledge of the information technology and services industry, with plenty of hands-on experience to back it up. He’s also an experienced Cloud engineer in Amazon Web Services (AWS), passionate about leveraging cloud technologies to improve the agility and efficiency of businesses.
One of Toni’s most special traits is his talent for online shopping. In fact, our delivery guy is convinced that ‘Toni Vujević’ is a pseudonym for all DECODErs.