【问题标题】:Convert NSAttributedString to RTFD and back in Swift将 NSAttributedString 转换为 RTFD 并返回 Swift
【发布时间】:2020-05-25 02:42:49
【问题描述】:

我有一个 NSAttributedString,其中包含文本和图像以及与之关联的属性。我正在尝试将 NSAttributedString 转换为 RTFD,以便它可以上传到 Cloud Firestore,然后可以从 RTFD 转换回 NSAttributedString。

我目前正在使用这些扩展从 NSAttributedString 转换为 RTFD 并返回,但它们返回 nil。

extension NSAttributedString {
    var attributedString2rtfd: String? {
        do {
            let rtfdData = try self.data(from: NSRange(location: 0, length: self.length), documentAttributes:[.documentType: NSAttributedString.DocumentType.rtfd])
            return String.init(data: rtfdData, encoding: String.Encoding.utf8)
        } catch {
            print("error:", error)
            return nil
        }
    }
}
extension String {
    var rtfd2AttributedString: NSAttributedString? {
        do {
            guard let data = data(using: String.Encoding.utf8) else {
                return nil
            }
            return try NSAttributedString(data: data,
                                          options: [.documentType: NSAttributedString.DocumentType.rtfd,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
}

当我将所有“rtfd”替换为“rtf”并且属性字符串中只有文本时,这些扩展名有效。但是,当我在属性字符串中包含图像并使用带有“rtfd”的扩展名时,如上所示,它们都返回 nil。我在这里做错了什么?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    希望这会对你有所帮助,它适用于我使用 fileWrapper。

    保存数据:

    let directoryURL = appDelegate.directoryPathURL //Directory URL path, folder should be named as "name.rtfd"
        
    let details = textView.attributedText 
    let documentAttributes = [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtfd]
    let fileWrapper = try? details.fileWrapper(from: NSMakeRange(0, details.length), documentAttributes: documentAttributes)
    do {
        try fileWrapper?.write(to: directoryURL!, options: .atomic, originalContentsURL: nil)
        print("saved")
    } catch {
        print(error)
    }
        
    

    获取数据-

    let rtfdDirectoryURL = appDelegate.directoryPathURL //Directory URL path, folder should be named as "name.rtfd"
    
    let options = [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtfd]
    do {
        let attributedString = try NSAttributedString(url: rtfdDirectoryURL!, options: options, documentAttributes: nil)
        textView.attributedText = attributedString
    } catch {
        print("\(error.localizedDescription)")
    }
    

    【讨论】:

      【解决方案2】:

      几天前我遇到了同样的问题。我通过在代码的编码和解码部分删除 String.Encoding.utf8 来解决它。如果将 utf8 编码的 rtfd 数据保存到一个文件中,然后用任何 utf8 兼容的文本编辑器打开它,你可以看出无论你是否使用 utf8 对其进行编码,文本都是不可读的,这意味着它无论如何都不是 utf8 编码的.因此,swift 无法使用 utf8 解码从中读取。

      经过一番搜索,我还注意到当人们将 NSAttributedString 转换为 rtf、rtfd、HTML 和纯格式数据时,他们不使用 String.Encoding.utf8 选项。

      因此,我的解决方案是这样的。并且在我的环境中进行了测试。

      extension NSAttributedString {
          
          func rtf() throws -> Data {
              try data(.rtf)
          }
          
          func rtfd() throws -> Data {
              try data(.rtfd)
          }
          
          func html() throws -> Data {
              try data(.html)
          }
          
          func plain() throws -> Data {
              try data(.plain)
          }
          
          func data(_ documentType: NSAttributedString.DocumentType) throws -> Data {
              return try data(from: .init(location: 0, length: length),
                              documentAttributes: [.documentType: documentType])
          }
      }
      
          func saveDocumentToFile(_ document: NSAttributedString,
                                  documentType: NSAttributedString.DocumentType) {
              guard document.length > 0 else { return }
              
              
              do {
                  if let fileURL = ... {
                      switch documentType {
                      case .rtf:
                          try document.rtf().write(to: fileURL)
                      case .html:
                          try document.html().write(to: fileURL)
                      case .rtfd:
                          try document.rtfd().write(to: fileURL)
                      default:
                          try document.plain().write(to: fileURL)
                      }
                      
                  }
              } catch {
                  print("Error when save document to file: \(error.localizedDescription)")
              }
          }
      
          func loadDocumentFromFile(_ documentType: NSAttributedString.DocumentType) -> NSAttributedString? {
              let fileURL = ...
              if fileURL != nil, FileManager().fileExists(atPath: fileURL!.path) {
                  do {
                      let fileData = try Data(contentsOf: fileURL!)
                      let contentString = try NSAttributedString(data: fileData,
                                                                 options: [.documentType: documentType],
                                                                 documentAttributes: nil)
                      if contentString.length > 0 {
                          return contentString
                      }
                  } catch {
                      print("Error when loading: \(error.localizedDescription)")
                  }
              }
              return nil
          }
          
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-15
        • 2015-11-24
        • 2020-09-24
        • 2018-01-21
        相关资源
        最近更新 更多