On iOS, you can get the value corresponding to the attribute key FileAttributeKey for the file on the device. It contains information such as the date the file was created and modified, and the size of the file. You can get the value defined in FileAttributeKey through the method attributesOfItem (atPath :) provided by FileManager. However, you can also set your own attributes to save / retrieve additional information. As an example of the usage scene, when the file on S3 is downloaded locally, the information about the update time to the file [LastModified](https://docs.aws.amazon.com/sdkfornet1/latest/apidocs/html/P_Amazon_S3_Model_S3Object_LastModified. You can think of things like assigning a value of htm) and using it for file synchronization management from the next time onwards.
For the sake of simplicity, the information to be saved in the code below is String
. I think it's okay to target types that conform to Codable
instead of String
.
extension URL {
///Get extended attributes
func extendedAttribute(for name: String) -> String? {
let result = withUnsafeFileSystemRepresentation { fileSystemPath -> String? in
//Get the size of the extended attribute data corresponding to name
let length = getxattr(fileSystemPath, name, nil, 0, 0, 0)
guard length >= 0 else {
return nil
}
//Secure an area to store data
var data = Data(count: length)
let result = data.withUnsafeMutableBytes { [count = data.count] in
//Get extended attribute data corresponding to name
getxattr(fileSystemPath, name, $0.baseAddress, count, 0, 0)
}
guard result >= 0 else {
return nil
}
return String(data: data, encoding: .utf8)
}
return result
}
///Save extended attributes
@discardableResult
func setExtendedAttribute(value: String, for name: String) -> Bool {
guard let data = value.data(using: .utf8) else {
return false
}
let result = withUnsafeFileSystemRepresentation { fileSystemPath -> Bool in
let result = data.withUnsafeBytes {
//Save extended attribute data corresponding to name
setxattr(fileSystemPath, name, $0.baseAddress, data.count, 0, 0)
}
return result >= 0
}
return result
}
}
//The name of the extended attribute to set
let key = "com.example.extended_attribute"
//File location to set extended attributes
let url = FileManager.default.temporaryDirectory.appendingPathComponent("example_file")
//If the file does not exist, create it and add extended attributes
if !FileManager.default.fileExists(atPath: url.path) {
let data = "example_content".data(using: .utf8)!
try! data.write(to: url)
//Grant extended attributes
url.setExtendedAttribute(value: "example_value", for: key)
}
//Check if extended attributes can be obtained
print(url.extendedAttribute(for: key))
Optional("example_value")
Even if you restart the application, you can see that the value saved by setExtendedAttribute
can be obtained and the value associated with the file can be persisted.
Recommended Posts