Creating Code Snippets in Xcode

What are code snippets?

Code snippets are as the name suggests, short pieces of code that can quickly be inserted into your code file. This is done either by dragging the snippet or by typing out the completion. Code snippets are very easy to create and use and can be applied in a wide variety of situations.

We will look at how you can create & use snippets. The following example is done in a playground, but this could be done from anywhere within Xcode.

Note: The example below was performed on Xcode 11.7

How do we create code snippets?

  1. Start off by writing the code or text that you want to convert into a snippet. For example, I have a set of comments that I add at the start of every function. Write it down.
/**
 This function performs a comparison of the 2 objects
 - important: This function does not perform data validation.
 - returns: `Bool`.
 - requires: iOS 13 or later
 - Since: iOS 13
 - parameter lhsValue: This holds the value on the lhs of the operator
 - parameter rhsValue: This holds the value on the rhs of the operator
 - Example: `var answer =  venueAddress == hotelAddress`
 - author: Arun Patwardhan
 - copyright: Copyright (c) Amaranthine 2020
 - date: 14th September 2020
 - version: 1.0
 */

2. Select it.
3. From the menu bar select Editor > Create Code Snippet.

This brings up the snippet editor.
4. Give your snippet the following details.

OptionDescription
NameThis is the name of your code snippet.
PlatformThis determines whether your snippet is available only for certain platforms: say only for iOS.
AvailabilityThis determines the place where the snippet can be added.
CompletionThis is the word that we will be typing in the Xcode editor to trigger the implementation of the snippet
LanguageThis specifies the language for which the snippet will be applied.

Name: Func Documentation

Language: Swift

Platform: All

Availability: All scopes

Completion: doc

Note that the values for Name and Completion can be whatever you want.

This is how the snippet should look.

5. Now we will try to use it in the editor. Start typing the completion word in the Xcode editor.

6. Select the snippet with your name and completion.
7. Hit enter. You should see the comments you want appearing in the editor.

Placeholder

We can make our snippet above even better by using placeholders. Placeholders are pieces of text that can be replaced by the user. They also give information about what is expected in the placeholder.

We can add place holders by simply typing the hint inside placeholder brackets. Placeholder brackets are nothing but open <# and closing #>. For example:

<# some text #>

Which appears as

The user will simply click on the “some text” placeholder.

There are plenty of places in our comments where we can use placeholders. When we use the code snippet it should put comments with place holders in them.

  1. Let us change the comments in our Xcode editor first. We will edit the snippet later on. Make the changes as shown below.
/**
 <# put the description of your function here #>
 - important: <# mention some important points here #>
 - returns: `<# return type #>`.
 - requires: iOS  <#iOS Version#>  or later
 - Since: iOS  <#iOS Version#>
 - parameter <#param 1#>: This holds the value on the lhs of the operator
 - parameter <#param2#>: This holds the value on the rhs of the operator
 - Example: `<#put some example code here#>`
 - author: Arun Patwardhan
 - copyright: Copyright (c) Amaranthine 2020
 - date: <#day#>  <#month#>  <#year#>
 - version: 1.0
 */

We have made the following items into comments.

  • Description
  • OS Version
  • Return type
  • Important comments
  • Parameter 1 & 2 names
  • Sample code
  • Day, Month, & Year

Of course, there are other things we could change too. Feel free to make any other changes you can think of.

2. Let us now copy these changes to the code snippet we created. Copy the code from the Xcode editor.

To bring the snippet editor again simply click on the add object button in the upper right hand corner of Xcode.

4. Select the snippet from the list on the left and click edit.
5. Paste the code that you just copied. Your snippet editor should look like this:

6. Click on ‘Done’ once you are finished making changes. Your snippet will now be ready.

7. Try adding the snippet into your editor just like before. Simply type in the completion for your snippet.

Dragging snippets

We can use the autocompletion we saw earlier. But it is also possible for us to drag snippets.

Exporting code snippets

Once created it is possible to export/import code snippets too. All the snippets are located in the following folder.

~/Library/Developer/Xcode/UserData/CodeSnippets/

Any snippets you have created will be located there.

Any new snippets to be added will have to be added there.

Summary

Code snippets are easy to create and have several advantages:

  1. They improve the developers experience
  2. Promote consistent code
  3. Speeds up the process of writing code
  4. Encourages developers to use each others snippets and gain the first 3 advantages.

Creating and using snippets is very very easy and has a lot of benefits. So go ahead and create snippets.

Creating custom templates for iOS App Development

What are Xcode templates?

Xcode templates are basically pre-created files which we use when we create new projects or project files. So every time you go through the process of creating a new project File > New > Project > iOS > Single View App you are using the Single View App template.

While most of the templates are good enough we can easily create our own templates.

Why do we need custom templates?

The templates available out of the box are good for common situations. But we find that most of the times we end up creating a lot of file in our project. Sometime we implement common design patterns and architectures on a regular basis.

In such situations creating out own custom templates will help us save a lot of time during development.

The other advantage is that this promotes a more consistent development experience in any organisation.

Now that we know what templates are and why we may need custom templates let us look at how we can create them.

Template Types

Before we go ahead and create templates let us examine what a typical template includes.

Navigate to the following path:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/

Notice that there are 2 folders already created out here. File Templates & Project Templates. Let us browse through these folders.

File Templates

These are the templates used when a developer wishes to add a new file to an existing project. Under file templates you should see different folders in there. Each folder represents a certain category of templates. For example, User Interface is one category. Select it.

You should see multiple folders under it. The screenshot above shows the View template. As we can see the template itself is a folder with multiple files inside. The template ends with an extensions xctemplate. Let us look at those files.

  • ___FILEBASENAME___.xib
  • TemplateIcon.png
  • TemplateIcon@2x.png
  • TemplateInfo.plist

The first one is the XIB file which will be generated by this template. The ___FILEBASENAME___ placeholder will be replaced with an actual name when it is created.

The next 2 are simply images that will be used as icons for the template when we bring up the template wizard in Xcode.

The last one is the more important one. The TemplateInfo.plist. This is where we describe how the file creation process works. This is also where we configure options which will be presented to the user. We will look at this file in greater depth later on when we try to create our own templates.

Project Templates

These are the templates that are used when a developer decides to create a new project. Under project templates you should see different folders in there. Each folder represents a certain category of templates. For example, Application is one category. Select it.

I have the single view app template inside it. This is the most commonly used template when starting out with iOS App Development. You should see other familiar project templates. Feel free to examine the files in the folder. Let us have a look inside the Single View App template folder. You should see these items:

  • ContentView.swift
  • Main.storyboard
  • TemplateIcon.png
  • TemplateIcon@2x.png
  • Preview Assets.xcassets folder
  • TemplateInfo.plist

The first 2 files are the UI related files. One of the 2 will be selected based on the users choice between Storyboard and SwiftUI.

The next 2 are simply images that will be used as icons for the template when we bring up the template wizard in Xcode.

The Preview Assets folder is used with SwiftUI for previewing purposes.

Here too we have the TemplateInfo.plist file which configures the template options at the time of creation. We will explore this file in greater depth when we try to create our own project template.

How can we create them?

In this article we will look at creating 2 types of templates.

  1. File Templates
  2. Project Templates

Warning: It may be a good idea to try this out on a test computer so that you do not break anything on the computer you use everyday.

Preparation

Before we get started let us prepare the folders where we will be storing our custom templates.

  1. Navigate to the following folder.
~/Library/Developer/Xcode/Templates/

Note, you may have to create this folder.

  1. There should be 2 folders inside: File Templates, Project Templates. If these folders are not there then go ahead and create them.

We will be placing our templates in these folders.


TopicPage
Creating File templates2
Creating Project templates3

Download

You can download the templates from these links.

Note

This code has been tested on Xcode 11.3.1 on macOS Catalina 10.15.3

Creating reusable UI Components for iOS App Development

In an earlier article I had discussed how we can create our own frameworks to easily share reusable code. In this article we will take this a little further and create our own reusable UI Components.

Points to Note:

  • The reusable component we will be creating is based on UIKit. For that reason this component can only be used in iOS Apps. However, you can follow the same steps to create a reusable component for macOS using Cocoa.
  • UI Components, distributed through a framework, do not render in the project storyboard file.
  • You should be familiar with creating Embedded Binaries (your own Framework). If you aren’t then please read this article first.
  • These projects are created on Xcode 10 with Swift 4.2

Getting Started

We will complete the implementation as a 2 step process. Here is the screen that we are planning to implement.

Creating the Reusable Framework

  1. Open Xcode and create a new Framework project.
    Screen Shot 2018-09-06 at 1.21.04 PM
  2. Name the project “UIVIdentityCard”.
    Screen Shot 2018-09-06 at 1.23.05 PM
  3. Save the project in any folder.
  4. Create a new Swift file File > New > File > Swift.
  5. Name the file “GenderType.swift”. This is where we will declare the enum that holds the Gender type that we are creating.
  6. Add the following code to the file.
     
    import Foundation 
    /** Possible scores that can be given. 
    *values* 
    `Male` 
    
    `Female` 
    
    `NotSpecified` 
    
    *functions* 
    `func toString() -> String` 
    Used to get the `String` version of the value 
    
    - Author: Arun Patwardhan 
    - Version: 1.0 
    */ 
    public enum GenderType 
    {      
         case Male      
         case Female      
         case NotSpecified 
    } 
    
    /** This extension adds the Enum to String converions capability 
    - Author: Arun Patwardhan 
    - Version: 1.1 
    */ 
    extension GenderType 
    {      
         /** This function converts from enum value to `String`         
         - important: This function does not do validation         
         - returns: `String`.         
         - requires: iOS 11 or later         
         - Since: iOS 11         
         - author: Arun Patwardhan         
         - copyright: Copyright (c) Amaranthine 2015         
         - version: 1.0 */      
         @available(iOS, introduced: 11.0, message: "convert to String")      
         func toString() -> String      
         {           
              switch self           
              {                
                   case .Male:                     
                        return "Male"                
                   case .Female:                     
                        return "Female"                
                   case .NotSpecified:                     
                        return "Not Specified"           
              }      
         } 
    } 
  7. Create a new Swift file called “PersonDetailsModel.swift”.
  8. Add the following code to the file.
    import Foundation
    
    /**  This struct represents the data that is to be shown in the ID card  
    **Variables**  
    `personName`  
    
    `personIcon`  
    
    `personDob`  
    Date of Birth  
    
    `personAddress` 
     
    `personPhone` 
     
    `personEmail` 
     
    `personCompany`
      
    `personHeight`
      
    `personWeight`  
    
    `personGender`  
    
    **Important**  There is a variable with the name `entryCount`. This variable keeps tracks of the number of stored properties that exist. The value of this variable will be used to determine the number of rows in the table.The computed property `numberOfRows` is the property used to access the value of `entryCount`.  
    
    - Author: Arun Patwardhan  
    - Version: 1.0
    */
    public struct PersonDetailsModel
    {     
         internal var entryCount : Int = 7     
         public var personName   : String = ""     
         public var personIcon   : UIImage     
         public var personDob    : Date     
         public var personAddress: String = ""     
         public var personPhone  : String = ""     
         public var personEmail  : String = ""     
         public var personCompany: String = ""     
         public var personHeight : Double? = 0.0     
         {          
              willSet          
              {               
                   if newValue == nil & personHeight != nil               
                   {                    
                        entryCount -= 1               
                   }               
                   else if newValue != nil & personHeight == nil               
                   {                    
                        entryCount += 1               
                   }          
              }     
         }     
    
         public var personWeight : Double? = 0.0     
         {          
              willSet(newValue)          
              {               
                   if newValue == nil & personWeight != nil               
                   {                    
                        entryCount -= 1               
                   }               
                   else if newValue != nil & personWeight == nil               
                   {                    
                        entryCount += 1               
                   }          
              }     
         }     
    
         public var personGender : GenderType?     
         {          
              willSet          
              {               
                   if newValue == nil & personGender != nil               
                   {                    
                        entryCount -= 1               
                   }               
                   else if newValue != nil & personGender == nil               
                   {                    
                        entryCount += 1               
                   }          
              }     
         }     
    
         public var numberOfRows : Int     
         {          
              return entryCount     
         }     
    
         public init(withName newName : String, icon newIcon : UIImage, birthday newDob : Date, address newAddress : String, phone newPhone : String, email newEmail : String, Company newCompany : String, height newHeight : Double?, weight newWeight : Double?, andGender newGender : GenderType?)     
         {          
              personName = newName          
              personIcon = newIcon          
              personDob  = newDob          
              personAddress = newAddress          
              personPhone = newPhone          
              personEmail = newEmail          
              personCompany = newCompany  
            
              if newGender != nil          
              {               
                   entryCount += 1          
              }          
              if newWeight != nil          
              {               
                   entryCount += 1          
              }          
              if newHeight != nil          
              {               
                   entryCount += 1          
              }          
    
              personHeight = newHeight          
              personWeight = newWeight          
              personGender = newGender     
         }
    }
    
    /**     This extension adds protocol conformance for the `CustomStringConvertible` protocol.     
    
    - Author: Arun Patwardhan     
    - Version: 1.1
    */
    extension PersonDetailsModel : CustomStringConvertible
    {     
         public var description: String     
         {          
              return """               
                   NAME: \(self.personName)               
                   DATE OF BIRTH:\(self.personDob)               
                   ADDRESS: \(self.personAddress)               
                   EMAIL:\(self.personEmail)               
                   PHONE:\(self.personPhone)          
              """     
         }
    }
  9. Now we will focus out attention on the View. Create a new file File > New > File > View.
    Screen Shot 2018-09-06 at 2.18.32 PM
  10. Name the view “UIVIdentityCard.swift”.
  11. Design the view as shown in the screenshot below.
    Screen Shot 2018-09-07 at 12.22.49 PM
  12. Create the corresponding“UIVIdentityCard.swift” file.
  13. Make the IBOutlet & IBAction connections for the different UI elements.
  14. Add the following code. This is how your file should look after its completed.
    /**     The UIVIdentityCard class     
    **Functions**     
    `public func load(data newPerson : PersonDetailsModel)`     
    Used to load the data for the view.     
    
    - Author: Arun Patwardhan     
    - Version: 1.0
    */
    @IBDesignableopen class UIVIdentityCard: UIView, UITableViewDelegate, UITableViewDataSource
    {     
         //IBOutlets --------------------------------------------------     
         @IBOutlet public weak var personIcon : UIImageView!     
         @IBOutlet public weak var personName : UILabel!     
         @IBOutlet public weak var personDetails : UITableView! 
    
         //Variables --------------------------------------------------     
         public var localTableData : PersonDetailsModel!     
         let nibName : String = "UIVIdentityCard"     
         var view: UIView!     
         let cellIdentifier : String = "IDCard"     
         //Functions --------------------------------------------------     
         /**     This function does the initial setup of the view. There are multiple things happening in this file.     
         1) The first thing that we do is to load the Nib file using the `nibName` we saved above. The UNIb object contains all the elements we have within the Nib file. The UINib object loads the object graph in memory but does not unarchive them. To unarchive them and get the ibjects loaded completely for use we have to instatiate the object and get the arry of top level objects. We are however interested in the first object that is there in the array which is of type `UIView`. The reference to this view is assigned to our local `view` variable.     
         2) Next we specify the bounds of our view     
         3) Finally we add this view as a subview     
    
         - important: This function does not do validation     
         - requires: iOS 11 or later, the varibale that contains the name of the nib file.     
         - Since: iOS 11     
         - author: Arun Patwardhan     
         - copyright: Copyright (c) Amaranthine 2015     
         - version: 1.0     
         */     
         @available(iOS, introduced: 11.0, message: "setup view")     
         func setup()     
         {          
              //1)          
              self.view = UINib(nibName: self.nibName, bundle: Bundle(for: type(of: self))).instantiate(withOwner: self, options: nil)[0] as! UIView          
         
              //2)          
              self.view.frame = bounds          
              
              //3)          
              self.addSubview(self.view)     
         }     
    
         public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int     
         {          
              if let count = localTableData?.entryCount          
              {               
                   return count - 2          
              }          
              return 0     
         }     
    
         public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&amp;gt; UITableViewCell     
         {          
              var cell : UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)          
    
              if nil == cell          
              {               
                   cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier)          
              }          
    
              switch indexPath.row          
              {               
                   case 0:                    
                        let formatter = DateFormatter()                    
                        formatter.dateStyle = .medium                         
                        cell?.textLabel?.text = "Birthday\t: "+ formatter.string(from: (localTableData?.personDob)!)      
    
                   case 1:                    
                        cell?.textLabel?.text = "Email\t: " + localTableData.personEmail               
    
                   case 2:                    
                        cell?.textLabel?.text = "Phone\t: " + localTableData.personPhone               
    
                   case 3:                    
                        cell?.textLabel?.text = "Address\t: " + localTableData.personAddress               
    
                   case 4:                    cell?.textLabel?.text = "Company\t: " + localTableData.personCompany               
    
                   case 5:                    
                        cell?.textLabel?.text = "Gender\t: " + \(localTableData.personGender?.toString())!               
    
                   case 6:                    
                        cell?.textLabel?.text = "Height\t: \((localTableData.personHeight)!)"               
    
                   case 7:                    
                        cell?.textLabel?.text = "Weight\t: \((localTableData.personWeight)!)"               
                   default:                    
                        print("error")          
              }          
    
              cell?.textLabel?.font = UIFont.boldSystemFont(ofSize: 12.0)          
              cell?.textLabel?.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)          
              return cell!     
         }     
    
         //Inits --------------------------------------------------                    
         override public init(frame: CGRect)     
         {          
              super.init(frame: frame)          
              self.setup()     
         }     
         
         required public init?(coder aDecoder: NSCoder)     
         {          
              super.init(coder: aDecoder)          
              self.setup()     
         }     
    
         override open func layoutSubviews()     
         {          
         super.layoutSubviews()     
         }
    }
    
    /**     This extension adds the function to load data     
    - Author: Arun Patwardhan     
    - Version: 1.1
    */
    extension UIVIdentityCard
    {     
         /**          
         This function loads the data for the view          
         - important: This function does not do validation          
         - parameter newPerson: This is the object representing the person whose information will be displayed on the screen.          
         - requires: iOS 11 or later          
         - Since: iOS 11          
         - author: Arun Patwardhan          
         - copyright: Copyright (c) Amaranthine 2015          
         - version: 1.0     
         */    
         @available(iOS, introduced: 11.0, message: "load data")     
         public func load(data newPerson : PersonDetailsModel)     
         {          
              self.localTableData = newPerson          
              self.personIcon.image = localTableData.personIcon          
              self.personName.text = localTableData.personName          
              self.personDetails.reloadData()     
         }
    }
  15. Add the placeholder image for the image view.
  16. Select any of the simulators from the list.
  17. Press ⌘ + B to build the project.
  18. From the Project navigator select the Framework file.
    Screen Shot 2018-09-07 at 12.29.44 PM
  19. Control click and select “Show in Finder”.
  20. Copy the framework to the “Desktop”.

We are done creating the reusable framework. We will not shift our focus towards testing this framework.

Using the Framework in a project

Let us now test the framework we created. We will do this by incorporating the code in our iOS App.

  1. Create a new project. Call it “IdentityCardTest”.
    Screen Shot 2018-09-07 at 12.33.52 PM
    Screen Shot 2018-09-07 at 12.33.49 PM
  2. Save the file in a folder of your choice.
  3. Select the Project file and Embed the Framework into your project. 
    Screen Shot 2018-09-07 at 12.36.14 PM
  4. Add an image to your project, this will be the image that will be displayed in your custom view.
  5. Switch to the Main.storyboard file. Drag a UIView into the ViewControllers view.
  6. Set its identity to the UIVIdentityCard in the identity inspector. Also set its module to UIVIdentityCard.
    Screen Shot 2018-09-07 at 12.38.11 PM
  7. Create an IBOutlet for this custom view.
  8. Switch to the ViewController.swift file. Import the UIVIdentityCard framework at the top of the file.
    Screen Shot 2018-09-07 at 12.41.13 PM
  9. Add the following code to the file. We will be creating test data and displaying it on the screen using the Custom view we just designed.
    //Functions --------------------------------------------------
    /**
        This function prepares and loads the data that is to be shown in the custom view
    
    
        - important: This function does not do validation
        - requires: iOS 11 or later, the UIVIdentityCard framework.
        - Since: iOS 11
        - author: Arun Patwardhan
        - copyright: Copyright (c) Amaranthine 2015
        - version: 1.0
    */
    @available(iOS, introduced: 11.0, message: "prepares data to be shown on the ID card")
    func prepareIDCard()
    {
         let displayData : PersonDetailsModel = PersonDetailsModel(withName: "Arun Patwardhan", icon: UIImage(named: "iconHolder.png")!, birthday: Date(timeIntervalSince1970: 44_97_12_000), address: "Mumbai, Maharashtra, India", phone: "91-22-26486461", email: "arun@amaranthine.co.in", Company: "Amaranthine", height: 5.11, weight: nil, andGender: GenderType.Male)
    
         myIDCard.load(data: displayData)
    }
  10. Your completed ViewController.swift should look like this.
    Screen Shot 2018-09-07 at 12.44.32 PM
  11. Run the project. See if the view loads the way we wish.

Link to Sample Code

https://github.com/AmaranthineTech/ReusuableUIFramework

Video

Creating Reusable UI

Migrating to Swift from Objective-C

This article explores some of the advantages and challenges faced by developers while migrating to Swift from Objective-C.

1. Do we want to migrate?

Before you start the migration process remove the old adage:

If it isn’t broken, don’t fix it!

Start by identifying the reasons why you wish to migrate. Here are some possible reasons why.

  • The code is old and not updated for a very long time. You now wish to add new features.
  • The frameworks/libraries you are using in your project have upgraded to modern Swift and no longer support your old Objective-C syntax. *You may still want to just update to modern Objective-C, but this would be a good time to jump onto swift.
  • You see potential for improvement in code size/speed/performance by using new Swift features not available in Objective-C. For example: Generic Programming.
  • The developers who developed the app in Objective-C have left and the new employees are proficient at Swift. *Again not a strong reason, but a valid reason if there is no other alternative. Asking people to sit down and learn Objective-C may not be practical, especially if they don’t have a background in C Programming.
  • The app is due for a performance, stability, & bug fix update. This is a good time to consider migration to Swift.

Factors to keep in mind before considering migration.

  • The cost of migration. This is the cost of keeping a certain number of developers occupied in migrating the code. The cost is in terms of time as well as money.
  • Potential risks. Any change to the code increases the risk of bugs. The chances of introducing limits on backward compatibility also increase.
  • Benefits gained. An assessment needs to be done as to whether there are any benefits of migrating to Swift. The Return on Investment needs to be figured out.
  • Compatibility with 3rd Party or in house libraries that you might use.

After having thought through all this you are ready for the next step: “Prepare to Migrate”

2. Preparing to Migrate

This is where you actually begin to work on the migration of the App.

  1. As a first step perform a full code review of the app.
  2. The next step is a major decision. Should you rebuild your entire app from scratch or do a piece by piece migration. We will explore the advantages a little later in the article.
  3. Look for Swift versions of 3rd frameworks/libraries you use. This is not strictly required, however, this is a good time to check for new APIs.
  4. Identify parts of the project to migrate. This is to be done if it is a piecemeal migration. This marks you as ready for the next step: “Starting the Migration”.

3. Starting the Migration

Once you have everything in place you are ready to begin.

Migrations happen class by class. Select an Objective-C class to migrate and start working on converting it to Swift.

If you have any pure C functions then you can either choose to make them work with Swift or rewrite them in Swift.

While migrating pay special attention to your code. Here are some conversions that you can make.

  • See if you can make it simpler by using Generic Programming instead of usingVoid *
  • Replace the use of NSError * with exceptions.
  • Use extensions to give types new capabilities.
  • Consider creating your own Data structures. You may use Swift Arrays, Dictionaries if you wish. But this might be a good time to improve performance by building your own data structures.
  • Embrace closures and protocols a lot more.
  • Make extensive use of the @available attribute to describe your changes and mark availability
  • Start incorporating Swift Markup to make the comments from your Objective-C code more readable.
  • Enums pulled in from Objective-C can be made more powerful in Swift by adding methods which work with enums as a part of the enum itself.
  • Use property observers to make code more reactive. In some situations this might be easier than setting observers.

Migration Steps

Here are some general steps you can follow. The steps below are for both a full app conversion or a piece meal conversion.

Note: The steps mentioned below are sample steps and not necessarily the only way to achieve this.
  1. If its a full app conversion then create a new project. Else duplicate the existing project.
  2. Start by looking for the frameworks you need and importing them in the necessary Swift files.
  3. Identify class(es) that you have in your Objective-C project. Start by creating empty versions of those in your Swift project. It is very likely that you may not need all the classes as you might be optimising or reworking your App’s architecture. Also it is possible that you may need new classes.
  4. Next identify data structures used in the class. Either convert them to their swift equivalents or explore other options.
  5. Migrate the functions directly associated with the data structures.
  6. Migrate the variables used in the Objective-C class.
  7. Lastly migrate the remaining functions to Swift.
  8. Do this till you have converted all the classes that you wish to convert.

One point left to talk about is testing. Thoroughly test you app after each step you complete. If you are using XCTests, migrate a single Unit test at a time. Corresponding to the changes that you have made above.

5. Things to watch out for

There are many things to keep in mind while migrating your code.

  • In a mixed language project (Swift and Objective-C) Swift only features won’t be supported. So Generic Programming cannot be implemented.
  • Blind copying of the code from Objective-C to Swift may not result in the best output. Try to examine each line for potential optimisation opportunities.
  • Watch out for OS version compatibility. You may have to choose your Swift version accordingly.

6. Full Conversion versus Part by Part Conversion

Full Conversion

PROS:

  • The advantage of building the app from scratch is that your overall development time is less as different parts of the app can be refactored at development time.
  • You also have the advantage of adopting new development approaches or architectures such as Model View View Model (MVVM) or Test Driven Development (TDD).
  • You are in a better position to take advantage of all the Swift features as there won’t be any challenges with compatibility.
  • The advantages of Swift viz: Speed, Safety, and compact code are more easily achieved
  • If you want to support older versions of iOS then having a pure Swift and pure Objective-C version helps.

CONS:

  • Of course this means that your development time is large.
  • There is a potential for writing duplicate code in Swift especially if it is being reused in Objective-C projects. You may end up with 2 code bases for the same feature.

Part Conversion

PROS:

  • The advantage of migrating parts of your app is that you can split the migration over a larger period and use your resources on other projects.
  • In terms of cost this is less expensive and more resource friendly
  • The potential for duplicate code is reduced

CONS:

  • But on the flip side every time you take a new part to migrate you will have to make changes to the Swift code written earlier. This increases the development time and may affect the quality of the app in the long run.
  • You cannot take advantages of all the Swift features.
  • There is a chance that once the migration is complete the App may have to undergo an overhaul to take advantage of the Swift features & improve on Speed, Safety & Size.

This article just talks about some of the advantages and challenges with Migration to Swift. There are multiple approaches available and you will have to pick and choose the approach based on your needs or situation. I had written an article some time back about choosing between Swift & Objective-C, you can have a look at that too. Here is an article, for your reference, written by Apple on Migrating to Swift. Good luck & Happy Programming! Do feel free to share your experience migrating to Swift.

 

Using Swift Package Manager

About Swift Package Manager

The Swift Package Manager is the tool used to build Applications and Libraries. it streamlines the process of managing multiple Modules & Packages. Before we go ahead and learn to use Swift Package Manager we need to get familiar with some basic terminology.

Modules

Modules are used to specify a namespace and used to control access to that particular piece of code. Everything in Swift is organised as a module. An entire app can fit into a module or an app can be made using multiple modules. The fact that we can build modules using other modules means that reusing code becomes a lot easier. So, when we make an iOS App with Xcode and Swift. The entire app is considered a single module.

Targets

Targets are the end product that we want to make. So an app for iOS is a separate target. A library is a target. An app for macOS is a separate target. You can have many targets. Some can be for testing purposes only.

Packages

Packages group the necessary source files together. A package can contain more than one target. Normally one would create a package for a family of products. For example: you want to make a photo editing app that runs on macOS & iOS. You would create one package for it. That package would have 2 targets: an iOS App & a macOS App.

Products

This is a categorisation of your packages. There are 2 types of products. Executables or Libraries. A library contains the module which can be reused elsewhere. Executables are application that run & may make use of other modules.

Dependencies

Dependencies are the modules or the pieces of code that are required to make the different targets within the package. These are normally provided as URLs.

End Products

*NOTE: Before you get started you must be familiar with Setting up Swift on Linux. If you haven’t done that then please go through the updated article: UPDATE: Swift on Linux. This also makes use of Swift Package Manager.

Example

So let us get started with an example. We are going to learn how to create:

  • a library package called ErrorTypes
  • a library package, called MathOperations, that uses the ErrorTypes library package
  • an executable package called Calc that makes use of the MathOperations package.

We will see how to create all three elements. Also I have uploaded the ErrorTypes & MathOperations packages to the http://www.github.com repository to demonstrate the use of dependencies. You can also create your own local git repositories if you wish.

To illustrate the folder hierarchy: I have created a folder called “Developer” in my Ubuntu linux home folder. Within that I have created a folder called “SPMDEMO“. All the paths that I will be using will be with reference to these folders. You should see a structure like this:

/home/admin/Developer/SPMDEMO/ErrorTypes
/home/admin/Developer/SPMDEMO/MathOperations
/home/admin/Developer/SPMDEMO/Calc

You are free to follow this exercise using your own folder locations. Just modify the paths accordingly.

swift package init
swift package init --type executable
swift build

If you need help with the commands run:

swift package --help
swift --help

Creating a Package

  1. First let us start off by creating the ErrorTypes package.
    mkdir ErrorTypes
  2. Navigate to the folder and create the package:
  3. cd ErrorTypes
    swift package init
    

    By default init will create a library package type.

  4. Navigate to the folder containing the source files:
    cd ./Sources/ErrorTypes/
  5. Open the ErrorTypes.swift file and write the following code
    public enum ErrorCodes : Error
    {
         case FileNotFound(String)
         case DivideByZero(String)
         case UnknownError(String)
    }
    
    public struct MathConstants
    {
         static let pi : Float = 3.14159
         static let e  : Float = 2.68791
    }
    

    Feel free to add some code of your own. The above is just an example.

  6. Run the command to build to make sure that there aren’t any issues. You shouldn’t have any as there are no dependencies of any kind. Its a simple straightforward piece of code.
    swift build
  7. If everything is fine check your code into a git repository. This can be local or on the web. Remember that we will need the URL to this repository.
  8. Navigate back to the SPMDEMO folder.
    cd ~/Developer/SPMDEMO/
  9. Create a folder called MathOperations.
    mkdir MathOperations
  10. Navigate to the newly created folder and run the command to create a library package.
    cd MathOperations
    swift package init
    
  11. Navigate to the sources folder:
    cd ./Sources/MathOperations/
  12. Open the MathOperations.swift file and write the following code.
    import ErrorTypes
    
    public struct MathOperations
    {
         public static func add(Number num1 : Int, with num2 : Int) -> Int
         {
              return num1 + num2
         }
    
         public static func mult(Number num1 : Int, with num2 : Int) -> Int
         {
              return num1 * num2
         }
    
         public static func div(Number num1 : Int, by num2 : Int) throws -> Int
         {
              guard num2 > 0
              else
              {
              throw ErrorCodes.DivideByZero("You are dividing by zero. The second argument is incorrect.")
              }
    
              return num1 / num2
         }
    
         public static func sub(_ num1 : Int, from num2 : Int) -> Int
         {
              return num2 - num1
         }
    }
    
  13. Before we build we need to modify the Packages.swift file to indicate there is a dependency.
    Notice that in the MathOperations.swift file we are importing a module called ErrorTypes. We just created it. But just because we created it doesn’t mean it will be added automatically. We need to pull that module into our own

    Also notice that I have provided access specifiers “public” everywhere. This ensures that the code written in one module is accessible in the other.

    Navigate to the MathOperations parent folder.

    cd ~/Developer/SPMDEMO/MathOperations/
  14. Open the Packages.swift file and make the changes as shown below:
    // swift-tools-version:4.0
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(name: "MathOperations",
         products: [
              // Products define the executables and libraries produced by a package, and make them visible to other packages.
              .library(name: "MathOperations", targets: ["MathOperations"]),
         ],
    
         dependencies: [
              // Dependencies declare other packages that this package depends on.
              .package(url:"https://github.com/AmaranthineTech/ErrorTypes.git", from:"1.0.0"),
         ],
    
         targets: [
              // Targets are the basic building blocks of a package. A target can define a module or a test suite.
              // Targets can depend on other targets in this package, and on products in packages which this package depends on.
              .target(name: "MathOperations", dependencies: ["ErrorTypes"]),
              .testTarget(name: "MathOperationsTests", dependencies:   ["MathOperations"]),]
    )
    
  15. Once these changes are made save the file and run the command
    swift build

    If you typed everything correctly then you should see the source code for the ErrorTypes module being pulled in and the build being successful.Here are some common mistakes:
    – Forgetting to write the import ErrorTypes statement
    – Error in the URL
    – The from tag not matching the tag in the repository
    – Access specifiers are incorrect or missing
    – Not mentioning the dependencies in the target

  16. Just like with the ErrorTypes module create a git repository for the MathOperations module.
  17. Now let us make the Calc executable that will use the MathOperations library. First navigate back to the SPMDEMO folder and create a folder called Calc.
    cd ~/Developer/SPMDEMO/
    mkdir Calc
    
  18. This time we are going to create an executable package. Run the command:
    swift package init --type executable

    This also creates a similar folder structure as in the case of the library.

  19. Navigate to the folder containing the main.swift file.
    cd ./Sources/Calc/
  20. Modify the main.swift file as shown below:
    import MathOperations
    
    //testing addition
    var result : Int = MathOperations.add(Number: 33, with: 29)
    print("Result of adding 33 with 29 is: \(result)")
    
    //testing multiplication
    result = MathOperations.mult(Number: 33, with: 29)
    print("Result of multiplying 33 with 29 is: \(result)")
    
    //testing division
    do
    {
         result = try MathOperations.div(Number: 33, by: 0)
         print("Result of dividing 33 by 29 is: \(result)")
    }
    catch let error
    {
         print("ERROR: \(error)")
    }
    
    //testing subtraction
    result = MathOperations.sub(3, from: 29)print("Result of subtracting 3 from 29 is: \(result)")
    
  21. Navigate back to the main Calc folder.
    cd ~/Developer/SPMDEMO/Calc/
  22. Modify the Packages.swift file as shown below:
    // swift-tools-version:4.0
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(name: "Calc",
    dependencies: [
         // Dependencies declare other packages that this package depends on.
         .package(url: "https://github.com/AmaranthineTech/MathOperations.git", from: "1.0.1"),
    ],
    targets: [
         // Targets are the basic building blocks of a package. A target can define a module or a test suite.
         // Targets can depend on other targets in this package, and on products in packages which this package depends on.
         .target(name: "Calc", dependencies: ["MathOperations"]),
    ]
    )
    
  23. Save the file and run the build command:
    swift build
  24. Like before you should see both the MathOperationsErrorType module being pulled in. We are ready to run the executable. Navigate to the debug folder which contains the executable. Make sure you are in the main Calc folder when you run this command.
    cd ./build/debug/
  25. You should see an executable file called Calc. Run it.
    ./Calc
  26. If everything went okay then you should see the output on the console.

As you can see it is pretty straightforward to develop Applications written in Swift on Linux.

Adding System Modules

In the previous example we saw how to import our own custom made modules. However, there are some modules provided by the system which offers functionality we may wish to use. For example if we wanted to use the random number generator in our application we would need to use the random() method. This is in the glib module.

  1. Quickly create a package called SystemLibs. This is an executable.
  2. Write the following code in the main.swift.
    #if os(Linux)
    import Glibc
    #else
    import Darwin.C
    #endif
    extension Int
    {
         func toString() -> String
         {
              return "\(self)"
         }
    }
    
    var luckyNumber : Int = Int(random())
    
    var luckyNumberStr : String = luckyNumber.toString()
    
    print("The lucky number is \(luckyNumberStr)")
    
  3. Build the code and run the executable.

Adding system modules is direct and simple. The glibc module contains aspects of the standard library. The condition check is to make sure that we are importing the correct module based on the system that we are developing the application on.

Handling Sub-dependencies

As we saw in the earlier example, sub dependencies are handled automatically. So when our Calc application marked the MathOperations module as a dependency it was pulled during the build. However, the MathOperations module itself marked ErrorTypes module as a dependency. We did not have to modify the Packages.swift file belonging to Calc to indicate that ErrorTypes module also needs to be pulled. This was handled automatically by Swift Package Manager.

Conclusion

In this article we have seen:

  • How to create a library package
  • How to create a library package that depends on another library package
  • How to create an executable that depends on a library package
  • How to import the system Glibc module into our executables.

The Swift Package Manager simplifies many aspects of the development process for us. Many of the things we have discussed also work on macOS. Going forward reusing code and planning for the same should be done keeping Swift Package Manager in mind.

Adding formatted text to Swift in Xcode

Formatting in Playgrounds and Xcode projects is achieved using Markups in comments. The following article describes some of the things that you can do. Note that there are many more ways of acheiving some of the effects shown here.

The idea behind markups is to make your code more readable whether you are using Playgrounds or Xcode.

If you can only see the commented code in playgrounds and not the rendered markup then click on Editor > Show Rendered Markup to view the rendering. You can use this option to toggle back and forth.

Formatting in Playgrounds

Plain Text

There are different kinds of text you can place in a Playground. Let us look at the code below to see what all is achieved.

//: # Documentation
//: ## Contents
//: * Text Description
//: * Documentation for Functions
//: * Documentation for Types
//: * Formatting Text
//:  - Code
//:  - Italics
//:  - Bold
//: * Inserting Items
//: * Links
//: * Assets
//: * Callouts

The comments here are in the format //:.

Rendered Output

This is how the rendered output looks.

Line 1 shows how to render a Title Text. This is achieved using the # before the text.
Line 2 shows how to get a lower sized text by using ## instead of #. We can achieve more levels if we wish.

For multi line text with bullets use the *, +, – symbols. This is seen on lines 7-13.

It is also possible to create numbered lists too. Simply type the numbered list & it renders accordingly.

//: * Inserting Items
//: 1. Links
//: 2. Assets
//: 3. Callouts

This renders as:

Screen Shot 2017-11-08 at 11.25.27 AM

Playground Pages

It is possible to have multiple pages in Playgrounds. This way we can create a more readable experience that makes the code structured, compartmentalised and easier to understand.

To do that open a playground and then simply add a playground by clicking File > New > Playground Page.

To move from one page to the next simply write the comment.

//: [Next Topic](@next)

This will automatically place a link to jump to the next page.

Similarly you can add a link to move to the previous page.

//: [Previous](@previous)

Code block

We can even show a code block in the text. It is formatted in a different manner to tell the user that it is a code block.

//: ### Code block
/*:
Loop to print characters
````
for char in "Arun Patwardhan"
{
    print(char)
}
*/

This is how it appears:

Screen Shot 2017-11-08 at 11.30.45 AM

Function Help

There is also some formatting that can be done for functions, types and other pieces of code written in a playground. This also appears on the quick help of the sidebar.

We will look at how to create formatted markup for playgrounds.

/*:
## This function takes temperature in Centigrade and converts it to Fahrenheit.
- important: This function does not do data validation
*/
/*:
- Note: "Please refer to Quick Help for more information."
*/
/*:
- Callout(Custom Callout): This is how you create a custom callout ` - Callout(Custom Callout):`
*/
/*:
- Example: `convert_to_fahrenheit_from(Centigrade: 32.0)`
*/

This renders as:

Formatted Markup for Functions

Formatted Markup for Functions.

We will look at formatting the comments to appear in Quick Help in the Formatting for Xcode section.

Inserting Links

The last bit is related to inserting links. We have already seen how to insert links for moving between Playground pages.

Redirecting to URL

/*:
For more articles on Programming, see [Programming articles @ arunpatwardhan.com](https://arunpatwardhan.com/category/programming/)
*/

This renders as:

Screen Shot 2017-11-09 at 11.14.24 AM

Formatting for Xcode

Function Help

As we saw in the earlier section we can create a lot of documentation for Functions. The approach is similar to the one we used in Playgrounds. We will be using callouts to provide information. We will use some callouts for Playgrounds, however, there are many more callouts available for Xcode Symbol Documentation as compared to Playground. The main difference here is the fact that the comments begin with /** instead of /*:.

“The code shown below will work in both, regular Xcode projects as well as Playgrounds.”

/**
This function takes temperature in Centigrade and converts it to Fahrenheit.
- important: This function does not do data validation
- parameter temp: This is the temperature in Centigrade. It can be a negative value too.
- returns: This is the temperature in Fahrenheit.
- requires: `temp > -273.0 && temp < 1000.0` - Note: The requirement mentioned is not enforced. - Since: iOS 11 - author: Arun Patwardhan - copyright: Copyright (c) Amaranthine 2015 - version: 1.0 */
func convert_to_fahrenheit_from(Centigrade temp : Float) -> Float
{
    return ((temp * 9.0 / 5.0) + 32.0)
}

This renders as:

Formatted Markup for Playgrounds as well as Quick Help

Formatted Markup for Playgrounds as well as Quick Help

Note that the quick help appears in the Right hand side sidebar. That too only after you select the function.

As we can see this makes the function a lot more readable. The real advantage of Quick Help comes in the fact that the documentation is now easily accessible no matter which file we are in within the project. The also helps the developer put in the right kind of information, required for proper usage of the function, in the help section.

Note that the rendered markup for Playgrounds will only appear in Playgrounds. 

Inserting Links

Just like in the previous section where we introduced links we can add links to the symbol documentation.

/**
   For more articles on Programming [Programming articles @ arunpatwardhan.com (https://arunpatwardhan.com/category/programming/)
*/
func recursiveFunction(count : inout Int)
{
   while 0 <= count
   {
      count -= 1
      recursiveFunction(count: &count)
   }
}

This renders in Quick Help as:

Screen Shot 2017-11-09 at 11.26.53 AM

Callouts supported by Playgrounds

  • Custom Callout
  • Example

Callouts supported by Symbol Documentation

  • Attention
  • Author
  • Authors
  • Bug
  • Complexity
  • Copyright
  • Date
  • Invariant
  • Precondition
  • Postcondition
  • Remark
  • Requires
  • See Also
  • Since
  • Version
  • Warning

Callouts supported by both Playgrounds & Symbol Documentation

  • Experiment
  • Important
  • Note

When to use Swift & when to use Objective-C?

Over the past few years I have received a number of questions with regards to Swift & Objective-C. Specifically related to the future of the 2. I will try to address those questions in the form of an FAQ.

Should I learn Swift or Objective-C?

This is a question that I get from developers new to iOS/macOS App Development. Ideally speaking, you should learn Swift. As that is going to become the main language for App development on Apple’s ecosystem. However, the reality is a little different. There are a large number of applications that are written in Objective-C. You are likely to encounter them at your workplace. You may also have to maintain, upgrade & improve those apps. In such a case, it makes sense to learn Objective-C too.

Can I mix Swift & Objective-C in the same project?

Yes! But remember that you should check for feature compatibility between the 2 languages. Adding Swift code to an Objective-C project may not be very beneficial as only those features that are compatible with Objective-C can be written in Swift.

Going the other way round is not a problem. You can read more about that here:Mixing Swift & Objective-C

Will Objective-C be deprecated in the future?

That is an interesting question. There is no formal announcement from Apple stating the Objective-C is going to be deprecated. However, one can expect more attention to be paid to Swift. That is where most of the newest techniques, tools & technologies are going to be available. Objective-C will keep running as it is as of now.

Can I mix Swift with other Programming Languages?

Swift can easily be mixed with Objective-C. If you wish to incorporate C++ or C code in your Swift Project then wrapping them in Objective-C code allows you to achieve this.

Apart from that Swift does support working with C code code. You can read about that here:Interacting with C APIs.

Swift does not provide interoperability support for any other languages as of now.

Which version of Swift should I use?

It is recommended that you use the latest available version of Swift. However, the actual version that you work on depends on many other factors like: compatibility with OS Versions, support & business related choices.

Why shouldn’t we just convert all our Objective-C code to Swift and keep things simple?

A very tempting proposition. However, practical realities prevent us from doing this. The process of converting from Objective-C to Swift is time consuming. Apart from having to convert the syntax, the code also needs to be optimised taking into account the new features that are available. This will mean extensive testing and quality assurance. Most companies will not invest their resources into this endeavour.

A better approach is to migrate to Swift gradually. Here are some ways to do this:

  1. If its a brand new product/app that you are creating, start it in Swift.
  2. Any new reusable code components that are being created should be done in Swift (they should be Objective-C compatible if you intend to use this code in Objective-C projects).
  3. If any part of a product is going to undergo heavy change, either due to a bug fix or a new feature. This is a good time to convert it into Swift.

A good example is how Apple is approaching the process of migrating to Swift. They are doing it component by component.

I have been developing apps in Objective-C for some time. I am able to create any reasonably complicated app now. If Objective-C hasn’t been deprecated then should I start making apps in Swift?

This is a choice that you have to make. It is recommended that new apps (at the very least) be made in Swift as that is the language that will undergo the maximum amount of changes & improvements in the future.

What do you suggest as a trainer?

Another question that I get very often. It depends on the situation. I would say learn both Swift & Objective-C. You can skip learning Objective-C if you are confident that you will not have to work with any projects written in that language.

If I am starting on a brand new project I would use Swift. But if its an Objective-C project I would stick to Objective-C.

Can Swift development only be done on macOS?

No! Swift development can also be done on Linux. However, iOS/macOS/tvOS/watchOS App Development can only be done on macOS through Xcode.

How should I migrate to Swift?

There are different approaches that one can use. It all depends on the situation and needs of your organisation. Here are some things that you can do:

  • Start development of brand new apps (from scratch) in Swift.
  • If you are creating a brand new library which will be used for future projects then go ahead with Swift.
  • If a major component of an existing app is going to be changed significantly then you can go ahead with Swift.

You can do all or some of the above. There may be other strategies too. You should also factor in the cost of migration from one language to another.

 

Creating Frameworks for iOS/OS X App Development

Creating Swift Frameworks

Creating Swift Frameworks is easy. The steps below walk you through creating a Swift Framework. The steps below have been performed on Xcode 7.3

  1. Launch Xcode.
  2. Select Create New Project. Or from the menu bar select File > New > Project
  3. From the Template chooser select the Framework & Library  Option under iOS
  4. Select Cocoa Touch Framework1
  5. Give your project a name.
  6. Make sure the language selected is Swift.
  7. Feel free to enter values of your choice for organisation name and organisation identifier.
  8. Save your project. Optionally, if you have a version control repository like Git you may save it there.
  9. In left hand side bar make sure you have selected the Project Navigator.
  10. Within the Project Navigator make sure you have selected the folder named after your project.
  11. Click on File > New > File.
  12. Make sure iOS Source is selected on the left hand side.
  13. Select the file type as Swift.IMG_3525
  14. Write down the code that you want to make available through a framework.
  15. Now this is the key point. Place the keyword public before all the elements that you want to make publicly accessible.Why do we need to do this? To understand this we need to understand the scope of different elements within a typical Swift project. IMG_3521

    Different variables/classes/functions that are declared within a module are accessible freely within the module. Swift files contain code & are themselves found within Swift modules. So a module can mean project or a framework.So, to access the variables/functions/classes from module A in module B, we have to make those elements of module A public in order to access them in module B.

    For more information, do read Apple’s Swift Documentation.

  16. The next steps depend on what your ultimate objective is. If you wish to build a framework for distribution then you need to follow a process that is similar to distributing an app. You need to get the code signing done & prepare the project for distribution.
  17. If however, you plan to release it internally, or even just test it. Then you can follow the steps below.
  18. Firstly, our objective is to make this framework run on both OS X(macOS) as well as iOS.
  19. To do that we will be adding a new target. Click on File > New > Target.
  20. Select OS X & the Frameworks & Libraries from the sidebar.
  21. Select Cocoa Touch Framework
  22. Give your framework a unique name. Something that indicates this framework is for OS X(macOS).
  23. Now, we don’t need to rewrite the code for the Mac. We can simply make the file we have written a member for the OS X Framework Target.
  24. To do that make sure that the right hand side sidebar is visible.
  25. In the left hand side sidebar make sure that you have selected the new Swift file with the code you have written in there.
  26. In the right hand side sidebar select the Document Inspector.
  27. Under Target Membership make sure that both the Targets are checked. The target for iOS should already be checked.IMG_3520
  28. Thats it. If you do not wish to make your code available for both iOS & OS X then skip steps 19 – 27.
  29. The next part is building the framework. We will be building this framework for use internally. We will first build the iOS framework.
  30. From the tool bar, make sure the target selected is for iOS. For the device you can select any device that you wish.
  31. Then click on Product > Build to build the framework. If all goes well then you should get the message Build Succeeded on your screen.
    IMG_3519
  32. To get hold of the framework, expand the product folder from the left hand side sidebar.
  33. Select the Framework you have just built. Note that it should be black in colour. If you have opted to make a framework for OS X, then you should see that framework listed too, it should be in red colour. The red colour indicates that it has not yet been built.IMG_3524
  34. Control-click on the iOS version of the framework and select Show in Finder.
  35. This will take you directly to the folder containing the framework. Copy paste it to the desktop or to any other location to easily access it when required.
  36. Repeat steps 30 – 34 to build the OS X version of the Framework. Make sure that the target selected is OS X.
  37. Once we have done that, we need to test the framework we just created.
  38. Create a dummy iOS Project for testing.
  39. From the left hand side project navigator make sure that the blue project settings file is selected.
  40. Make sure that the Target is selected within the settings screen.
  41. Under the General tab scroll down to the Embedded Binaries section.
  42. Click on the ‘+’ sign to add a framework.IMG_3523
  43. Click on Add other
  44. Navigate to the folder where you saved the Framework and select it.
  45. Click Open
  46. Select Copy Items if needed
  47. The framework should be added to your project.
  48. In the ViewController.swift file import your Framework: import CustomStack
  49. Replace CustomStack with your frameworks name.
  50. Try to write the code which uses the elements you have packaged within the framework.

Creating Mixed Frameworks (Swift & Objective-C)

The process of creating a mixed library is straightforward. Its almost the same as above with some minor differences.

  1. Follow the steps mentioned above to add your Swift Code.
  2. Add your objective-C files to the project.
  3. While adding the files make sure that the checkbox for the targets is selected appropriately. Screen Shot 2016-08-05 at 1.20.37 PM
  4. Write the code that you wish to write in Objective-C. Of course, if you are including prewritten files then you do not need to do this.
  5. To make the Objective-C code accessible in Swift you need to make the following changes:
    1. In the umbrella header of your framework add the line to import the header
      #import "<FrameworkName>/<HeaderName>.h
    2. Modify the access property located within the target membership of the Objective-C header file. IMG_3527
  6. This should make your Objective-C code accessible to the Swift files.
  7. Test the changes by accessing your Objective-C code in your Swift files within the framework.
  8. Test the changes further by embedding your mixed language framework into a project & then try to access both the Swift as well as Objective-C versions of the code in your new project.
  9. To make your Swift code accessible to Objective-C File make the following changes:
    1. Make sure that your Swift code is compatible with Objective-C. There are 2 ways of doing this. One you can make your Swift class inherit from NSObject. The second way is to use the @objc keyword before your class declaration.
    2. In the Objective-C header file add the line to add the bridging header which is auto generated. You do not need to create your own bridging header.
      #import "<FrameworkName>/<FrameworkName>-Swift.h"

      Replace the word FrameworkName with the name of your Framework.

    3. This should allow you to access your Swift code in your Objective-C header file within the same Framework Project.
  10. This way you can make a single framework which contains code written in both Swift & Objective-C.