Reputation: 1574
I downloaded the Xcode 8 beta and converted my syntax to Swift 3. When I did, I got the eponymous error with this code (this didn't happen before):
Swift 3:
do {
let fileAttributes = try FileManager.default().attributesOfItem(atPath: fileURL.path!) // Error here
let fileSizeNumber = fileAttributes[NSFileSize] as! NSNumber
fileSize = fileSizeNumber.longLongValue
} catch _ as NSError {
print("Filesize reading failed")
}
Swift 2:
do {
let fileAttributes = try NSFileManager.defaultManager().attributesOfItemAtPath(fileURL.path!)
let fileSizeNumber = fileAttributes[NSFileSize] as! NSNumber
fileSize = fileSizeNumber.longLongValue
} catch _ as NSError {
print("Filesize reading failed")
}
Is this a bug in Swift 3, or am I missing something?
I know there are many questions about the same error, but those don't fix my problem. I'm happy to edit for clarification.
Thanks in advance!
Upvotes: 4
Views: 11935
Reputation: 70119
I think something like this should work:
do {
let fileAttributes = try FileManager.default().attributesOfItem(atPath: file.path!)
if let fileSizeNumber = fileAttributes["NSFileSize"] as? NSNumber {
let fileSize = fileSizeNumber.int64Value
}
} catch let error as NSError {
print("Filesize reading failed: \(error.debugDescription)")
}
Since NSFileSize
was just a constant string I've replaced it by its raw value. It seems ok - but it would be better to find the official equivalent, of course (which I didn't manage to for now, so don't take this solution for granted, it's just a workaround).
Update for Xcode 8 GM:
Using FileAttributeKey.size
is better than using the hardcoded constant (thanks @rudy for the reminder). Here's an updated example:
do {
let attributes = try FileManager.default.attributesOfItem(atPath: file.path)
if let size = attributes[FileAttributeKey.size] as? NSNumber {
let fileSize = size.int64Value
print(fileSize)
}
} catch {
print(error.localizedDescription)
}
Upvotes: 7
Reputation: 51
This works on the Dictionary as returned from the call:
fileAttributes[FileAttributeKey.size.rawValue]
(Swift 3 as of XCode8 WWDC)
Upvotes: 1
Reputation: 1012
This works in Swift 3:
var fileSize: UInt64 // size in bytes
do {
let fileAttributes: NSDictionary? = try FileManager.default().attributesOfItem(atPath: fileURL.path!)
if let fileSizeNumber = fileAttributes?.fileSize() { fileSize = fileSizeNumber }
} catch let error as NSError {
print("Filesize reading failed: \(error.debugDescription)")
}
By casting the attributes into NSDictionary, many built-in methods become available including .fileSize():
.fileGroupOwnerAccountName()
.fileModificationDate()
.fileOwnerAccountName()
.filePosixPermissions()
.fileSize()
.fileSystemFileNumber()
.fileSystemNumber()
.fileType()
It's easy to discover their return data types by inspecting them with option-Click in Swift.
Upvotes: 1