[SWIFT] Add Extended Attributes to the file

Introduction

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.

Implementation example

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
  }
}

Check the operation

//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))

Console output

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.

reference

Recommended Posts

Add Extended Attributes to the file
4 Add println to the interpreter
How to add the delete function
Add a time stamp to the JAR file name in Gradle
[Xcode] How to add a README.md file
Migration file to add comment to Rails table
[Java] How to use the File class
How to delete the wrong migration file
How to delete the migration file NO FILE
How to add jar file in ScalaIDE
I wanted to add @VisibleForTesting to the method
Try changing the .erb file to .slim
[Rails 6] cocoon_ Add id and data attributes to the form to be added
Add empty data to the top of the list
Add the JDK to the TeamCity build agent container
How to add sound in the app (swift)
Double-click to open the jar file on Windows
Add classpath: to the path specified in spring.datasource.schema
Add jar file obtained from Maven to IntelliJ
[Spring Boot] How to refer to the property file
Add files to jar files
[Java] How to extract the file name from the path
JavaFX-Specify the location of the CSS file relative to the fxml file
How to debug the generated jar file in Eclipse
Completely delete the migration file that you failed to delete
I want to add a delete function to the comment function
How to correctly check the local HTML file in the browser
Add an icon to the header link using Rails fontawesome
How to add elements without specifying the length of the array
How to add the same Indexes in a nested array
Add a shadow to the Swift Button (and also the circle)
How to change the contents of the jar file without decompressing
How to change the file name with Xcode (Refactor Rename)
The migration file is duplicated
9 Corresponds to the return value
How to add ActionText function
12 Corresponds to the while statement
About the File :: Stat class
Output javadoc to word file
[Spring Boot] I want to add my own property file and get the value with env.getProperty ().
Output XML tree to file
[Rails] Add column to devise
[Rails] Delete the migration file
How to add HDD to Ubuntu
Input to the Java console
How to create a jar file or war file using the jar command
It doesn't respond to the description in .js of the packs file
Fix the file name of war to the one set in Maven
[Eclipse] I want to open the same file twice [Split editor]
Method to add the number of years and get the end of the month
I want to add the disabled option to f.radio_button depending on the condition
[JQuery] How to preview the selected image immediately + Add image posting gem
[chown] How to change the owner of a file or directory
I made a tool to output the difference of CSV file
How to get the length of an audio file in java