All Categories

Explore Beyond the Basics Swift – Part I

In this blog we will be exploring the topics Initializers in swift, Interoperability between swift and Objective C, inout and mutating keywords in swift

Initializers in Swift

Initialization is process of setting up new instance for a particular type. Any setup that need to be done before the first uses of the object can be done here. The special function, which facilitates this process, is init. A default initializer is provided and thus it is not mandatory to implement an initializer

Please note the class and struct in the code below is an example where the default initializer is used.

/* Class declaration start */
class SomeArbitraryPoint{
var xArbitrary:Int = 0;
var yArbitrary:Int = 0;
func getAnAribitararyPoint(var aPoint:SomeArbitraryPoint) -> SomeArbitraryPoint {
aPoint.xArbitrary = 3
return aPoint
}
}
/* Class declaration end */
var aPoint = SomeArbitraryPoint()
/* Struct declaration start */
struct SomeArbitraryPoint{
var xArbitrary:Int = 0;
var yArbitrary:Int = 0;
func getAnAribitararyPoint(var aPoint:SomeArbitraryPoint) -> SomeArbitraryPoint {
aPoint.xArbitrary = 3
return aPoint
}
}
/* Struct declaration start */
var aPoint = SomeArbitraryPoint()

Initializer can have parameters and you should have guessed by now what Failable Initializers represent. A Failable Initializers cane be compared to an optional initializer.

The following code is an example class that implement initializer

class SomeIntegerValueWrapper{
var value:Int?
//simple initializer
init(){
value = 10;
}
// initializer with parameter
init(value:Int){
self.value = value
}
// failable with parameter
init?(valueString:String){
//the intializer used by itself is a failable. The obvious reason being the fact that a string with "ABC" will fail to be converted to an int value
self.value = Int(valueString)
if(self.value == nil){
// retrun nil implies the initialization failed
return nil;
}
}
}

In the above example the failable initializer returns a nil if the initialization process fails.

Designated and Convenience Initializer

The designated initializers are the main initializers for a particular type. A Convenience Initializer on the other hand is an initializer that which uses a designated initializer within itself to initialize the type

All the initializer implemented in the above class SomeIntegerValueWrapper are an example of a designated initializer.

The following code we have re-written the same class with convenience initializer

class SomeIntegerValueWrapper{
var value:Int?
// convenience initializer
convenience init(){
self.init(value: 10)
}
// initializer with parameter
init(value:Int){
self.value = value
}
}

“required” keyword with initializer

By using the required keyword with an initializer for a particular type (lets say class SomeClass), we are telling the compiler that it is a mandate to implement this initializer while sub classing the type (i.e. SomeClass)

If an initializer is marked with required keyword then while sub classing
It is mandate that the initializer marked with required keyword is implemented.
Required modifier should be present with implementation of required initializer in subclass as well

The sample code below depicts required initializer implementation

class SomeClass{
required init(){
//write the implementation for SomeClass
}
}
class SomeSubClass:SomeClass{
required init(){
//write the implementation for SomeSubClass
}
}

Interoperability with Objective C

Interoperability need to be considered with two perspective. Lets discuss each of these.

  • Using Objective C implementation within Swift
  • Using Swift implementation within Objective C

The former works well and in almost all the cases the developer will be able to use Objective C with Swift without any hurdle. However the latter 100% inter operability is not possible. Let look into the aspects that one should be aware of so that interoperability in each of the above can be achieved.

  • Objective C implementation within Swift

It is the bridging header where you have to import the objective C header file that you need to expose to the swift. While you create or add an Objective C file to a swift iOS project, Xcode suggest to create a bridging header with name “<replace project name>-Bridging-Header.h” . The bridging header can be specified in the build setting tab of the iOS Project as well(i.e. a developer can manually create a bridging header and specify the same in the Swift Compiler – Code Generation section of build settings tab). You can also import the Objective C framework in the same manner by specifying it in the bridging header and thus the framework can be made available to be used in the swift class.

  • Using Swift implementation within Objective C

In this case the build tool creates the header file for us, which need to be imported in the Objective C files to expose the swift class to Objective C. Name of the header can be found at the Swift Compiler – Code Generation section of build settings tab for the property Objective-C Generated Interface Header Name. You will notice that the Objective C bridging header is required for our project to compile even if we are not trying to expose any Objective C to swift . For using the swift class we will import the Objective-C Generated Interface Header Name to our Objective C file and use the @class directive for forward declaration of the class.

  • inout , mutating keywords in swift

These keywords are those that need to be explained with value types in swift. Sounds confusing, not to worry, let me re-iterate the fact that you all might have observed with introduction of swift language. Apple is more focused and promoting the usage of value types and minimize usage of reference types.

As said most of the data type introduce with swift are value type . If the inout keyword is used with a function signature then it is the reference of the variable that which is passed to the function and any modification made to the variable inside the function affect the original variable as well on contrary to the actual value type behavior. The example code will show the above-mentioned case, which uses the inout keyword and that which does not use inout keyword.
Using inout keyword can be compared to pass by reference

var someValue:Int = 10;
func findSquare(inout value:Int){
value = value * value
}
findSquare(&someValue);
print(someValue) // 100 will be printed to console
Without the inout keyword the function can be compared to pass by value
someValue = 10;
func findSquare(var value:Int){
value = value * value
}
findSquare(someValue);
print(someValue) // 10 will be printed to console

Struct are designed keeping immutability in mind. However in all the situation this wont work and in such case explicitly mention/ marking a method mutating makes the method capable to mutate the value/members of struct instance.

The following show how mutating modifier can be used along with structs

struct SampleStruct {
var someValue:Int
// mutating modifier in a mandate here or else compile time error will be throw
mutating func changeSomeValue(value:Int){
someValue = value
}
// mutating modifier can be used to change the actual struct object instance
mutating func resetSelf(){
self = SampleStruct(someValue: 10)
}
func printValue(){
print(someValue)
}
}

As said in the comment if you want to change the value it is a mandate that mutating keyword is used and the compiler enforces the same. On additional note you might have noticed what the resetSelf function in the above example does. This function utilizes the capability of mutating keyword to change the struct instance itself.
Hope you have enjoyed reading. Watch this space The Swifty Way ! – Exploring Beyond

Keep visiting our website Acadgild for more updates on Big Data and other technologies. Click here to learn iOS App Development.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Articles

Close
Close