Converting SVProgressHUD to Swift Using Swiftify
Swift is loved by developers and is clearly the future of development in the Apple Ecosystem and maybe general purpose programming as it been Open-Sourced by Apple and developer all over the world actively contribute to it. Swift code is faster, more readable, seems natural and fun like a scripting language. Objective-C is very powerful and a large number of frameworks and many parts of the Apple Frameworks are written in Objective-C.
It is always a better option to start future proofing our Code and Frameworks by migrating to Swift, given that Swift has now attained a certain level of stability and maturity as a language as it achieved ABI Stability in Swift 5.
SVProgressHUD is a very popular library widely used by developers. It is elegant in its simplicity to use and its clean minimalistic design.
Swiftify for Xcode is a very powerful tool and converts an entire Objective-C project to Swift. I used it to convert a project and the results were very good and quick but as I had studied the project code briefly I did not have an in-depth understanding of how the code was structured or how it functioned. I realized that it would be better to convert the project one class at a time, test the converted class and then keep on repeating the process.
I would strongly recommend using Swiftify for Xcode on your own code or a code you have studied well enough and have an in-depth understanding of.
If you are converting code not written by you or code that you do not have a deep understanding of, I would recommend migrating one class at a time, testing with the existing code, and then repeating the process, as debugging the entire project later would be very difficult. It is always better to divide and conquer.
My overall approach can be graphically viewed as:
Looking at the code structure in SVProgressHUD the order in which I converted the files is as follows:-
So after having used Swiftify for Xcode, I started from scratch again, the first class I converted was SVRadialGradientLayer. This class is used for adding the gradient mask type and is called from only one place. Convert the SVRadialGradientLayer.m and add the properties and functions in SVRadialGradientLayer.h. The conversion is simple and happens in a snap. There is a single fix to be applied and can be done with just a simple Google Search. After this I removed this Objective-C class from the target, added the new Swift file and ran the project, the project compiled and ran as expected and so I moved on to the next file.
The next class to be converted was SVProgressIndefiniteAnimatedView. This class is used for showing an indefinite animated view of two types which are native design and flat design. In native design, the ProgressHud shows animated view with the and in flat design, it shows the signature UIActivityIndicatorView. I converted the code to Swift, made the properties private and added functions for setting and getting the properties.
As you may have noticed, the setter functions declaration in the code above contains the @objc keyword as the functions are being called from SVProgressHUD.m, class which hasn’t been converted till now.
Later I added properties to show and hide the activity indicator as in Objective-C implementation this class SVProgressIndefiniteAnimatedView was being cast to UIActivityIndicatorView. So I added the code to show and hide the ActivityIndicator into the class as in the extension below:
While working on this class, I also opened up the SVProgressHUD.bundle, extracted the files and added the images to the IHProgressHUD.bundle
Next, I started with SVProgressAnimatedView class which is responsible for showing the HUD with a progress indicator ring. It supports only flat style and does not support UIActivityIndicatorView.
Now comes the main class of the project which coordinates with the outside code and uses these classes to present the HUD. This class is voluminous and complex. I used the techniques mentioned earlier such as making use of setters and getters functions, placing all the class functions in a different class extension. This class uses a single instance of itself i.e. it is a self-contained Singleton class. All the class functions eventually use this Single Instance.
I also took the time to clean up the deprecated functions after the final completion. I started with the class functions and converted them all in one go. Then came the bigger instance methods, which are the meat of the library. Slowly the file got converted looking up the original source code in the assistant editor and using Swiftify. The code conversion took some time and there were a few issues for which I ran the project with the original SVProgressHUD file and the Swift version file and debugged by looking at the difference in the values at runtime.
That is the reason that in the flowchart above I do not remove the original Objective-C file until the code conversion is complete and the Swift Code is running and tested.
Now, if we want we can maintain compatibility with Objective-C by not removing the @objc prefix, and adding the @objc prefix to the functions and properties that act as an interface for our code.
After testing I removed the @objc from functions, and self, made an enhancement to the library to make it thread-safe. You can now use the library from any thread, the Single Instance is always created and assessed from the main thread.
If you used SVProgressHUD in the past you had to set the SV_APP_EXTENSIONS flag manually to determine if the framework is running in an App Extension. Now it is not handled inside the code and the end user does not have to set it for the AppExtension target.
Swiftify has been a great help and without it, the process would have been very cumbersome. The conversions are reliable and very accurate and it does most of the work for you. It is so easy to use, I had earlier used Swiftify web app only for converting small snippets of Objective-C code from StackOverflow to Swift and now I just used it convert SVProgressHUD to Swift. Moreover, Swiftify has proved to be a practical solution for Migrating to Swift.
You can check out the converted code here. Feel free to contribute by suggesting new features or improvements. Also, please suggest some other Open Source Objective-C Libraries to convert to Swift.
The major takeaway for developers converting Objective-C code to Swift would be to start with the less complex parts convert them to Swift while maintaining compatibility with the remaining Objective-C code and repeating the process over and over again until the project is fully converted to Swift.
Swiftify may not be perfect but it does save a lot of time and is quite reliable. I would recommend Swiftify for developers who are migrating Objective-C code to Swift.