2

In swift3 I have problem to access local files that I downloaded then unzipped.

The path contains "Optional":

  Users/name/Library/Developer/CoreSimulator/Devices/..../data/Containers/Data/Application/...
/Documents/Optional("folder-name")/Optional("file-name")

My code to create this path is:

let videoPath = fileManager!.appendingPathComponent("\(MyObj.folder)/\(MyObj.fileName)")
SpeedLog.print(videoPath.path)

The class MyObj is:

class MyObj : NSObject, NSCoding {
var fileName:String!  
var folder:String!

required convenience init?(coder decoder: NSCoder) {
    self.init()
    self.fileName = decoder.decodeObject(forKey: "fileName") as! String
    ....
}
convenience init(id:Int,fileName:String,...) {
    self.init()
    self.fileName = fileName
    ....
}
func encode(with coder: NSCoder) {
    if let fileName = fileName { coder.encode(fileName, forKey: "fileName") }
    ....
}

How to build the path without "Optional?

Ludo
  • 743
  • 1
  • 10
  • 25

1 Answers1

1

Seeing "Optional" in your string output means you're passing in an optional, a variable that might contain a value or might contain nil. If you're certain that it isn't nil when you want to use it, you can force unwrap it by adding ! to its name, which makes it no longer optional. If you do this to a variable that is nil, you'll get a runtime error. Alternatively you can unwrap using let.

var optional:String?            // optional, contains nil
print(optional)                 // 'nil'
optional = "something"          // still optional, contains "something"
print(optional)                 // 'Optional("something")'
print(optional!)                // 'something'
let nonOptional = optional!     // not optional, contains "something"
print(nonOptional)              // 'something'

There's a lot more about optionals in the Swift docs.

In the MyObj class definition you provided it looks like the fileName and folder instance variables are set up as Implicitly Unwrapped Optionals (they have an ! after their names when they are defined), which used to work fine but is now giving you this problem.

In Swift 3 Apple made changes to the way Implicitly Unwrapped Optionals work, which is the cause of your problem here. There's a full explanation in this answer, but the short version is that string interpolation no longer treats them as implicitly unwrapped.

The workaround is to manually unwrap them using !, or use a different method to build your string. You can concatenate strings and string literals using the + operator, which I think looks pretty clean:

let path = obj.folder + "/" + obj.fileName
Community
  • 1
  • 1
Robert
  • 6,660
  • 5
  • 39
  • 62
  • Thank you for the explanations. In fact MyObj is a instance of MyObj, I just renamed it in the example given. So I changed to fileManager!.appendingPathComponent("\(MyObj.folder!)/\(MyObj.fileName!)") and it works, but I do not really understand why I need to add ! as before it was working and there is already ! in the Class definition – Ludo Nov 02 '16 at 01:49
  • @Ludo Actually it looks like you did everything right but Apple changed the way Swift handles implicitly unwrapped optionals in string interpolation. I added an explanation and an alternate way of creating strings to my answer. – Robert Nov 02 '16 at 02:22