iOS 上用于 swift3 的原生 zlib inflate/deflate

native zlib inflate/deflate for swift3 on iOS

我希望能够 inflate/deflate Swift3 数据结构。我找到了 GzipSwift,但不清楚我是如何将它提供给我的 iOS 应用程序的。我尝试过的天真的事情包括:

  1. 正在将 Data+Gzip.swift 文件复制到我自己的项目中。这然后抱怨所述文件顶部的 import zlib 。我认为这与同一来源的 zlib 目录中的模块映射文件有关。但是我不确定在我自己的项目中重新创建什么或如何重新创建它们。

  2. 从 github 克隆存储库,打开 XCode 并内置(基本上按下 运行 按钮)。然后尝试将其作为链接库或框架添加到我自己的项目中。我很确定只选择存储库的顶级目录不是我想做的,但我不知道还能尝试什么。

我在那里找到了一些其他代码,但它似乎过时并且相对于 Swift2。

我最近不得不将那个确切的库和文件添加到我的项目中,经过大量故障排除后终于让它工作了,所以让我来指导您完成这些步骤!

好的

1) 在 finder 中转到项目的顶级目录,并创建一个名为 Swiftzlib 的新文件夹或任何您想要的要导入的模块的名称。 (我们要做的是将 zlib 库添加为一个模块,因此可以将其视为导入 Foundation 或其他类似模块)。需要说明的是,这个 Swiftzlib 目录最终将作为包含 *.xcodeproj*.xcworkspace 文件的同一目录的子目录。

2) 在您创建的文件夹中,创建两个文件。

  • include.h
  • module.modulemap

3) 在您的 include.h 文件中,输入以下内容:

#include<zlib.h>

4) 在您的 module.modulemap 文件中,输入以下内容:

module Swiftzlib [system] {
    header "include.h"
    export *
}

其中 Swiftzlib 与您创建的文件夹的名称相同。

5) 打开您的 Xcode 项目,然后 select 您的目标

  • 5a) 在 Build Phases -> Link Binary with Libraries 中,添加 libz.tbd
  • 5b) 在构建设置 -> Swift 编译器 - 搜索路径中,将 $(PROJECT_DIR)/Swiftzlib 非递归添加到导入路径
  • 5c) 在 Build Settings -> Other Linker Flags 中,添加 -lz 作为标志

6) Select 你在 Xcode 中的项目(可能不是必需的,但我已经在我的项目中完成了并且它有效)

  • 6a) 在构建设置 -> Swift 编译器 - 搜索路径中,将 $(PROJECT_DIR)/Swiftzlib 非递归添加到导入路径

7) 在Data+Gzip.swfit中,将import Swiftzlib添加到文件的顶部

8) 清理、构建和 运行!

我在 Apple 的本地 libcompression 框架周围维护了一个小的 Swift 3+ 包装器:

https://github.com/mw99/DataCompression

gzip 的使用示例:

let data: Data! = "https://www.ietf.org/rfc/rfc1952.txt".data(using: .utf8)
let gzipped: Data! = data.zip()
let gunzipped: Data? = gzipped.unzip()
assert(data == gunzipped)

但是如果您只对经典的 inflate 和 deflate 感兴趣,您可以改用 .inflate().deflate() 方法。这将节省 18 个字节,因为不会添加 gzip header。

Swift 5 使用 Compression.

实现

我花了几天时间才意识到我必须删除压缩数据的前 2 个字节。 希望它能帮助到别人。

import Foundation
import Compression

func decompress(_ data: Data) -> String {
    let size = 8_000_000
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
    let result = data.subdata(in: 2 ..< data.count).withUnsafeBytes ({
        let read = compression_decode_buffer(buffer, size, [=10=].baseAddress!.bindMemory(to: UInt8.self, capacity: 1),
                                             data.count - 2, nil, COMPRESSION_ZLIB)
        return String(decoding: Data(bytes: buffer, count:read), as: UTF8.self)
    }) as String
    buffer.deallocate()
    return result
}