【问题标题】:native zlib inflate/deflate for swift3 on iOSiOS 上 swift3 的原生 zlib 膨胀/放气
【发布时间】:2016-09-22 20:14:27
【问题描述】:

我希望能够对 Swift3 数据结构进行充气/放气。我找到了GzipSwift,但尚不清楚我如何将其提供给我的 iOS 应用程序。我尝试过的天真的事情包括:

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

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

我发现了一些其他代码,但它似乎过时并且与 Swift2 相关。

【问题讨论】:

    标签: ios swift swift3 zlib swift-data


    【解决方案1】:

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

    好的

    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 项目,然后选择您的目标

    • 5a) 在构建阶段 -> 将二进制文件与库链接,添加 libz.tbd
    • 5b) 在 Build Settings -> Swift Compiler - Search Paths 中,以非递归方式将 $(PROJECT_DIR)/Swiftzlib 添加到导入路径
    • 5c) 在 Build Settings -> Other Linker Flags 中,添加 -lz 作为标志

    6) 在 Xcode 中选择您的项目(可能不是必需的,但我已经在我的项目中完成了它并且可以正常工作)

    • 6a) 在 Build Settings -> Swift Compiler - Search Paths 中,以非递归方式将 $(PROJECT_DIR)/Swiftzlib 添加到导入路径

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

    8) 清理、构建和运行!

    【讨论】:

    • 哇!感谢您的详细回复。明天我会试一试,希望届时能接受答案。
    • 可悲的是,我仍然收到“没有这样的模块 Swiftzlib”错误:(
    • 确保指向库的路径正确,这一点很关键。
    • 知道了!我的误解是什么构成了“项目的顶级目录”。事实上,也许这里会出现一个灯泡... XCode 倾向于将项目中的所有 .swift 源文件放在与它上面的目录同名的目录中。这是因为它代表了项目的内在模块吗?
    • 您可以将模块放置在项目文件结构中的任何位置,您只需要在导入部分选择正确的路径。至于你的第二个问题......我不确定。 Xcode 会这样做,即使对于 obj-c 项目也是如此,因此它可能只是文件结构。如果文件位于相同的命名空间(如您的项目名称中),我很确定它们都可以被编译器看到,而无需导入它们。您永远不会在应用程序中将 AppName 作为模块导入。
    【解决方案2】:

    Swift 5 使用压缩实现。

    我花了几天时间才意识到我必须删除压缩数据的前 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, $0.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
    }
    

    【讨论】:

    • @The_Androctonus size 是缓冲区的分配大小,即保留要使用的字节数。如果您不知道解压缩时需要多少字节,通常会使用一个大数字。
    • 我花了几天时间才找到同样的东西......谢谢你的回答。
    • 我本来想把头发弄出来的!谢谢@vauxhall!
    • 你救了我的命!几天后,我终于遇到了这个答案。我想知道为什么?
    【解决方案3】:

    我在以下位置维护了一个围绕 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 标头。

    【讨论】:

    • 请在此处添加链接中的详细信息。
    猜你喜欢
    • 2021-03-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 2014-07-25
    相关资源
    最近更新 更多