Tuesday, August 11, 2015

Swift Conversion

I decided this week that it was time to prepare my paid app for iOS 9.  I have been collecting a long list of enhancements that I have been wanting to add and since this was the first app I ever released I also have a long list of internal enhancements I want to add.

The app was written in Objective-C and uses two storyboards, one for the iPhone and the other for the iPad.  It has about 70 classes and was written before auto-layout and flat UI design existed.  I have been doing my best to make incremental changes to the UI so it looks fresh, but I feel the code base has now become so tangled that it's time to rethink the whole design.  So in conjunction with upgrading it to iOS 9, I also decided to switch it to Swift 2.0.

I decided to start with converting the AppDelegate class.  But after working on that one class for four hours I realized this is not going to be a small task.

First of all, for this app, the AppDelegate has a lot of responsibilities.  It ensures the correct storyboard is loaded and configured properly, it stands up the app's CoreData stack, and it listens for local notifications when they occur.

With all these different concerns it's no wonder that I quickly ran into issues that were tough to fix.

For the most part I was able to resolve each issue with a quick Google search.  But I found switching contexts to do the search was slowing my progress.  So my intent with this post is to consolidate each of the issues along with their fixes so I will have one place to find the answer.  This will be a living document, so as I run across issues with this conversion I intend to update this post.

My plan is to keep each issue succinct by just listing the error, the code that the error was on and the fix.  I don't intend to give an explanation as to why it fixed it.

I'm hoping this will be a short post in the end, but given my experience so far I'm not holding my breath.

So here goes:

Downcast from X? to X only unwraps optionals did you mean to use !

original code:

if let vc = window?.rootViewController

Fix:

if let vc = window?.rootViewController as UIViewController!

How to see computed type of a variable?

let visibleVC = navVC.visibleViewController

Option-Click over visibleVC

Cannot subscript a value of type [NSObject:AnyObject]? with an index of type String (or NSObject or NSString)

  override func handleUserActivity(userInfo: [NSObject : AnyObject]?) {
    if let version = userInfo[kHandoffVersionKey] as! String {

Fix:

  override func handleUserActivity(userInfo: [NSObject : AnyObject]?) {
    if let version = userInfo?[kHandoffVersionKeyas? String {

Could not find member CalendarUnitMonth
Use of unresolved identifier 'NSCalendarUnitDay'

Original code:

     let myCalendar = NSCalendar.currentCalendar()  
     let components = myCalendar.components(NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond, fromDate:startDateTemplate)  
     let currentDateComponents = myCalendar.components(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay, fromDate:currentDate)  

Fix:
            
     let myCalendar = NSCalendar.currentCalendar()
     let units: NSCalendarUnit = [ NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day]
     let components = myCalendar.components(units, fromDate: NSDate())

Expected ',' separator

Original code (where objects is a NSArray):

for object:MyObject in objects {

Fix:

  
for object:AnyObject? in objects {
     if let object = object as? MyObject


Method 'shouldPerformSegueWithIdentifier(_:sender:') with Objective-C selector 'shouldPerformSegueWithIdentifier:sender:' conflicts with method 'shouldPerformSegueWithIdentifier(_:sender:)' from superclass UIViewController with the same Objective-C selector

Original code was this:


    func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject) -> Bool {

Fix:

    override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {

This problem is the error message is confusing.  Basically the fix is to make the "sender" type be "AnyObject?" instead of "AnyObject"

My hope is this format will help me as I go through this conversion and others who might be heading down the same path.

As always, let me know if you have questions or comments.

No comments:

Post a Comment