How to Switch Your Apps from Objective-C to Swift

We are aware that there are two major programming languages in iOS app development; Objective-C and Swift. Although Swift came much later in comparison to Objective-C (in 2014), but it outshined its counterpart to become the favorite of iOS developers.

This is mainly because of the fact that it offers a wide range of advantage such as writing fewer codes, less maintenance of apps, acceleration in app development process, few bugs and crashes, strong from security point of view and much more.

So, if you have been working on Objective-C, it is the appropriate time to migrate over to Swift. Many of the popular iOS apps like Yahoo, LinkedIn, Lyft, Weather etc. have already travelled from Objective-C to Swift successfully and so now it’s your turn.

Read also: Swift Vs. Objective-C: Let’s Find Out Who the Winner is

So, How to Begin With the Conversion

One of the important points that needs to be kept in mind is ensuring the use of the latest Objective-C code. With the help of a modern Objective-C converter, Xcode allows you to implement the appropriate enum macros, change the id to instancetype wherever it is possible. It also helps to update the latest @property syntax.

The iOS app developers need to take some care here as the converter will not represent the semantics of the code. But it will help you in detecting and employing the mechanics of potential changes. Thus, it is advisable to check everything manually and then go for the alterations.

If you are employing the modern Objective-C converter, then follow the following steps:

Edit → Convert → To Modern Objective-C Syntax.

Convert One Class at a Time

You need to remember that you cannot convert all your codes at once from Objective-C to Swift but rather you have to choose one class at a time. Some classes are written in Swift while others in Objective-C and you get a hybrid target once the Swift file gets added to Objective-C app target.

Swift cannot have subclasses and so you can opt for two files namely a header file, which is .h and contains @interface section and a .m file that contains @implementation section. You don’t have to develop a header file as the .m file imports the .h file if it wants to refer to a class.

Developing a Bridging Header

Xcode offers an opportunity to develop a bridging head once you have added an Objective-C file to Swift target or vice versa. You would probably come across a message as

bridging header

In fact, it is the .h file that has got its default name from the target and it can be changed. But in order to make the change, you have to also alter the target’s Objective-C Bridging Header. Plus, if you #import the Objective-C .h file in bridging header, it becomes visible to Swift.

Performing the Nil Checks

In the Objective-C programming language whenever a message is sent to a nil object, you ultimately get a zero value in return. So, if you want to avoid this from taking place or get a nil value, it is imperative to opt for the nil checks as per the requirements. Normally, you get it as a generic enum-

public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible

In a usual case you get either of a two; a value of Wrapped type or a value that does not exist.

Obtaining Wrapped Value

With Swift you also get the syntactic sugar for stating the types optional. It allows you to substitute the Optional<String> with String?

You can receive the wrapped value from the elective container using two methods including Optional Chaining and Forced Wrapping. In the first case, it is used if the conditional statement obtains a value in case of its existence. In the second case, the conditional statement is not nil. If it contains a variable you would get a result without applying conditions or else it would crash.

The totally unwrapped optional in Swift is known as the String. It can be illustrated through a meaningful example:

class ExampleClass {
   var nonOptionalString: String
   var unwrappedOptionalString: String!
   var optionalString: String?

   init(string: String) {
       nonOptionalString = string
   }
}

Well, you can come across three possibilities which can arrive at this juncture.

  1. The first is that of nonoptinalString whose value will never be a zero. It should contain a variable when object is getting initialized or it will crash.
  2. The second is unwrappedOptionalString where the value of string is nil. So, if you are attempting to get across a nothing value object, the program will crash.
  3. The third is optionalString where the string remains nil but is taken as a regular optional variable.

So, when writing the Objective-C codes, better categorize your variables into two different categories; Nullable and _Nonnull type annotations. Therefore, the earlier indicated illustration would resemble something like this:

@interface ExampleClass: NSObject
@property (nonatomic, strong) NSString * _Nonnull nonOptionalString;
@property (nonatomic, strong) NSString *unwrappedOptionalString;
@property (nonatomic, strong) NSString * _Nullable optionalString;

- (instancetype)initWithString:(nonnull NSString *string);
@end

Tuples

Apart from the Optionals, Apple has also brought forward a new development language better known as the Tuples. It groups various values into one compound value and is a good tool in case you are developing a model at a place and directly is not user-friendly.

Extensions

The extensions available in the Objective-C language are combined into a single entity in Swift. It offers a new functionality to the existing class, structure and protocol and there is no need to avail the source code for extending types.

Enumerations

The Objective-C confines the code enumerations to the primitive types only. In case you want to map the integer enumeration value to the consequent strings for showing the result to the user or sending to the backend, an array or dictionary is required. However, Swift makes you comfortable as you don’t have to go through these complications. It is providing new enumerations with more options.

enum ExampleEnum {
    case ExOne, ExTwo, ExThree
}

It can store the associated values and you can store raw values in Swift enumeration using it similar to as Objective-C.

enum AnotherExampleEnum {
   case ExOne(String, Int)
   case ExTwo(Int)
}

Subscripts

Subscripts are basically used to get information from a group or assortment of classes’ structures or enumerations without

employing any technique. Subscripts help in regaining the values by index and as such you don’t have to store or retrieve. The elements in Array instance can be viewed as someArray (index) and for Directory instance as someDictionary [key].

Just follow the syntax:

subscript (index: Int) -> Int {
get {
//for declaring subscript value
}
set (newValue) {
//for defining values
}
}

Type Implication

When we focus on type safety for the iOS development, it usually refers to an integer which is declared with a specific type. It cannot be changed and remains fixed. The compiler decides what variable type will go on according to the given value.

For example:

var str = "One String"
// OR
var str2:String
Str2 = "Second String"

If you are trying to start by putting number values to a str2 variable, the compiler is said to show an error.

Str2 = 10 //error: Cannot put value of type 'Int' to type 'String'

Function

Swift offers an easier approach when it comes to the function syntax. Each of function comprises of a type and type contains function’s parameter types and return type. It allows you to either allocate a function to variable or pass it as a value. The app developers can also give default value to parameter.

Let’s illustrate it with example:

func stringCharacterscount (s: String) -> Int
   {
return s.characters.count
   }
func stringToInt (s: String) -> Int
   {
if let a = Int (s)
   {
return a
   }
return 0
   }
func executeSuccessor (f: String -> Int, s: String) -> Int
   {
Return f(s). successor()
   }
let f1 = stringCharacterscount
let f2 = stringToInt

executeSuccessor (f1, s: "5555") //5
executeSuccessor (f2, s: "5555") //5556

Dealing with Errors

So, when you are dealing with the errors in Objective-C you have to employ the reference to NSError variable. But if this approach is improper, you have to develop an NSError instance and write to passed variable. You have to check the error parameter and ensure that it is non-nil.

- (nonnull NSString *)exampleMethod:(nonnull NSString *)param error:(NSError **)error {
   if (!param.length) {
       *error = [NSError errorWithDomain:[NSBundle mainBundle].bundleIdentifier
                                    code:-101
                                userInfo:nil];
       return nil;
   }
   // do work
}

In case of Swift you get circulating, throwing, catching and manipulating errors that can be recovered.

Important Points to be Considered for Conversion

  1. In the first instance, you have to choose a pair of .h and .m files that needs to be migrated to the Swift Development Language. However, if you want to convert the entire project, then it is better to leave the AppDelegate class.
  2. Next, you have to find the #import “MyViewController.h” from the whole code and eliminate the Bridging Header File ([MyProject]-Bridging-Header.h).
  3. Once this is done, it’s time to substitute instances of #import “MyViewController.h” with forward class declaration: @class MyViewController. It should be done for all .h files as it helps in evading the circular references between header files.
  4. Translate a pair of Objective-C files to Swift. You can do this with the help of Finder extension that is added with Swiftify for Xcode. Apart from that, the contents of both .h and .m need to be copied into the Swift file and which you can press the key Convert the File.
  5. The .h and .m files have to be replaced from project with the converted .swift file.
  6. The next step is compiling the project and fixing errors and bugs in any. If you want to fix the error then you can take support of Editor → Fix All in Scope command available in the Xcode auto-fix suggestions. In case of repeated errors, you have to get in touch with Swiftify and report the issue there.
  7. Just there! All you have to do is create and run the project. In case, you come across any issue such as Class not Found and it crashes thereafter, then you need to search for references in the Storyboard Editor. Re-enter the name of the class in Identity Inspector, save and try once again.
  8. We kept the AppDelegate class for last and if converting the entire project you can translate now. All your files have migrated from Objective-C to Swift and so there is nothing left in the target. Now you can eliminate all files.

Conclusion

With the passage of time, Swift has righty become one of the topmost choices for the iOS app developers and with this new programming language of Apple offering several advantages over Objective-C, most developers have already chosen to convert their apps from Objective-C to Swift.

The conversion must be done very carefully without missing any step. It is also true that you need an experienced professional to do this job and so you can contact our expert iOS developers to help you out.

She is a project leader at Mindinventory having the past experience as an iOS developer who loves exploring everything that’s in trend! In her free time, she likes to delve into various project management tools and apply her findings in her projects.