Compile errors during migration from Swift 2 to Swift 3

anel
4 min readAug 4, 2017

Warnings part

I would like to share the compiler errors that I found and fixed during the migration.

Original code : OC.

Xcode Conversion: XC (when Xcode automatically converts the code from swift 2 to swift 3)

// OC Swift 2
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle(.Destructive, title: “Remove”) { [weak self] action, indexPath in
//XC
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle(rawValue: Int)!, title: “Remove”) { [weak self] action, indexPath in
//Swift 3
let deleteAction = UITableViewRowAction(style: .destructive, title: “Remove”) { [weak self] action, indexPath in

Error: Cannot convert value of type ‘’ to specified type ‘’

[String : (Format<T>, NSCache<_, _>, DiskCache)] → [String : (Format<T>, NSCache, DiskCache)]

//Swift 2
var formats : [String : (Format<T>, NSCache, DiskCache)] = [:]
//XC
var formats : [String : (Format<T>, NSCache, DiskCache)] = [:] as! [String : (Format<T>, NSCache, DiskCache)]
//Swift 3
var formats : [String : (Format<T>, NSCache<AnyObject, AnyObject>, DiskCache)] = [:]

Error: Use of local variable ‘cgImage’ before its declaration

//Swift 2
let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(size.width), Int(size.height), CGImageGetBitsPerComponent(CGImage), 0, CGImageGetColorSpace(CGImage), CGImageAlphaInfo.PremultipliedLast.rawValue)!
//Swift 3
let ctx: CGContext = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: self.cgImage.bitsPerComponent, bytesPerRow: 0, space: self.cgImage.colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!

Error: Type of expression is ambiguous without more context

//Swift 2
static var fgSessions = [String : NSURLSession]()
//XC
static var fgSessions = [String : Foundation.URLSession]()
//Swift 3
static var fgSessions : [String : Foundation.URLSession] = [:]

Error: Extraneous argument label ‘result:’ in call

Swift 3 decided to prohibit argument labels for function types.

Solution: delete all labels in function types

//Swift 2
dispatch_async_main { handler(result: SignupResponse(email : info.email, success: true, errorCode: nil, errorDescription: nil) ) }
//Swift 3
dispatch_async_main { handler(SignupResponse(email : info.email, success: true, errorCode: nil, errorDescription: nil) ) }

Error: ‘init’ is unavailable: use ‘withMemoryRebound(to:capacity:_)’ to temporarily view memory as another layout-compatible type.

//XC
let bytesPointer = UnsafeMutablePointer<UInt8>(valuePointer)
//Swift 3
let bytesPointer = UnsafeMutablePointer<UInt8>(OpaquePointer(valuePointer))

Error: Cannot assign value of type ‘NSDate’ to type ‘Date?’

//Swift 2
bylineView.dateLabel.date = date
//XC
bylineView.dateLabel.date = date as! NSDate
//Swift 3
bylineView.dateLabel.date = date

Error: Call can throw, but it is not marked with ‘try’ and the error is not handled

//Swift 2
let json = JSON(data: sampleNS.data(using: String.Encoding.utf8.rawValue)!)
//Swift 3
do {
let json = try JSON(data: sampleNS.data(using: String.Encoding.utf8.rawValue)!)
dummy = DailyChallenge(json: json)
}catch _ {}

Error: Passing non-escaping parameter ‘action’ to function expecting an @escaping closure

Reference: https://swiftunboxed.com/lang/closures-escaping-noescape-swift3/

//Swift 2
func addRow(_ title : String, icon : UIImage?, action : ()->Void ){
...let hlite = HighlightedAction(view: rowView, handler: action)
}
//Swift 3
func addRow(_ title : String, icon : UIImage?, action : @escaping ()->Void ){
...let hlite = HighlightedAction(view: rowView, handler: action)
}

Error: Argument labels ‘(_:)’ do not match any available overloads

//Swift 2
numFollowersLabel.text = numberFormatter.string(from: NSNumber(vendor!.memberCnt))! + “ Followers”
//Swift 3
numFollowersLabel.text = numberFormatter.string(from: NSNumber(value: vendor!.memberCnt))! + “ Followers”

Error: Initializer for conditional binding must have Optional type, not ‘String’

Optional binding only works when the result of the right side of the expression is an optional. If the result of the right side is not an optional, you can not use this optional binding.

//Swift 2
if let path = self.path{
return path.lowercased().range(of: “jpeg”) != nil ||
path.lowercased().range(of: “jpg”) != nil ||
path.lowercased().range(of: “gif”) != nil ||
path.lowercased().range(of: “png”) != nil
}
else {return false}
}
//Swift 3
return path.lowercased().range(of: "jpeg") != nil || path.lowercased().range(of: "jpg") != nil || path.lowercased().range(of: "gif") != nil || path.lowercased().range(of: "png") != nil

Error: Contextual type ‘CFArray’ cannot be used with array literal

Implicit casting to bridged types has been removed. In this case, we will need to add explicit casting to make it work.

//Swift 2
let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(),colors: [UIColor(hex: “F8A147”).cgColor, UIColor(hex: “FD4C19”).cgColor],locations: [0.0, 1.0])
//Swift 3
let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(),
colors: [UIColor(hex: “F8A147”).cgColor, UIColor(hex: “FD4C19”).cgColor] as CFArray,
locations: [0.0, 1.0])

Error: Default argument value of type ‘CountableClosedRange<Int>’ cannot be converted to type ‘Range<Int>’

//Swift 2
static func randomInt(_ range: Range<Int> = 1...10) -> Int {…}
//Swift 3
static func randomInt(_ range: Range<Int> = 1..<10) -> Int {…}

Error: Type ‘String.Index’ (aka ‘String.CharacterView.Index’) has no member ‘index’

//Swift 2
let restOfString = substringFromIndex(range.startIndex.advancedBy(skip))
//Swift 3
let restOfString = self.substring(from: self.index(range.lowerBound, offsetBy: skip))

Error: Nil is not compatible with expected argument type ‘UnsafePointer<CGAffineTransform>’

//Swift 2
let path: CGMutablePath = CGMutablePath()
CGPathMoveToPoint(path, nil, 0, height/2)
CGPathAddLineToPoint(path, nil, frame.width, height/2)
//Swift 3
let path: CGMutablePath = CGMutablePath()
path.move(to: CGPoint(x:0, y: height/2))
path.addLine(to: CGPoint(x:frame.width, y: height/2))

Error: ‘CGContextSetLineDash’ is unavailable: Use setLineDash(self:phase:lengths:)

//Swift 2
CGContextSetLineDash(context, 0, pattern, pattern.count)
//Swift 3
context?.setLineDash(phase: 0, lengths: pattern)

Error: Value of type ‘String’ has no member ‘stringByRemovingPercentEncoding’

// XC
let urlDecodedStr = sessionStr.stringByRemovingPercentEncoding
//Swift 3
let urlDecodedStr = sessionStr.removingPercentEncoding

Error: Cannot convert value of type ‘String.Encoding’ to expected argument type ‘UInt’

//Swift 2
let string = NSString(data: download.receivedData!, encoding: String.Encoding.utf8)
//Swift 3
let string = NSString(data: download.receivedData!, encoding: String.Encoding.utf8.rawValue)

Error: Cannot convert value of type ‘ObjCBool’ to expected argument type ‘Bool’

//Swift 2
var isDirectory = ObjCBool(false)
if !FileManager.default.fileExists(atPath: dirURL.path, isDirectory: &isDirectory) {...}if !isDirectory { return nil }//Swift 3
var isDirectory = ObjCBool(false)
if !FileManager.default.fileExists(atPath: dirURL.path, isDirectory: &isDirectory) {...}if !isDirectory.boolValue { return nil }

Error: ‘NSMutableDictionary!’ is not convertible to ‘[AnyHashable : Any]!’; did you mean to use ‘as!’ to force downcast?

//Swift 2
tracker.send(builder.build() as [NSObject : AnyObject])
//XC
tracker.send(builder.build() as! [AnyHashable: Any])
//Swift 3
guard let build = (builder.build() as NSDictionary) as? [AnyHashable : Any] else {return}
tracker.send(build)

Error: Value of type ‘Error’ has no member ‘code’

//XC
let error = Error()
error.code
//Swift 3
let error = Error()
error._code

Error: Cannot invoke initializer for type ‘UInt32’ with an argument list of type ‘(SecTrustResultType)’

//Swift 2
var secresult = SecTrustResultType(kSecTrustResultInvalid)
...
if secresult == UInt32(kSecTrustResultProceed) || secresult == UInt32(kSecTrustResultUnspecified) {...}
--------------------------------------------------------------------//XC
var secresult = SecTrustResultType.invalid
...
if secresult == UInt32(SecTrustResultType.proceed) || secresult == UInt32(SecTrustResultType.unspecified) {...}--------------------------------------------------------------------//Swift 3
var secresult = SecTrustResultType.invalid
...
if secresult.rawValue == UInt32(SecTrustResultType.proceed.rawValue) || secresult.rawValue == UInt32(SecTrustResultType.unspecified.rawValue) {...}

--

--