data缓存 swift_swift 图片转data data转图片 - CSDN
精华内容
参与话题
  • 可以直接把模型数组归档转成data,完美解决大量数据缓存的问题
  • Swift清除APP缓存和WebView缓存

    千次阅读 2018-12-11 18:38:34
    import Foundation import WebKit class ClearCacheManage { class func sizeOfAllCache() -> String { let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirector...
    import Foundation
    import WebKit
    
    class ClearCacheManage {
        
        class func sizeOfAllCache() -> String {
            let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
            let fileArr = FileManager.default.subpaths(atPath: cachePath!)
            var size: Double = 0
            for file in fileArr! {
                let path = (cachePath! as NSString).appending("/\(file)")
                let floder = try! FileManager.default.attributesOfItem(atPath: path)
                for (abc, bcd) in floder {
                    if abc == FileAttributeKey.size {
                        size += (bcd as AnyObject).doubleValue
                    }
                }
            }
            let cache = size / 1024 / 1024
            return String(format: "%.1fM", cache)
        }
        
        class func clearAllCache() {
            let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
            let fileArr = FileManager.default.subpaths(atPath: cachePath!)
            for file in fileArr! {
                let path = (cachePath! as NSString).appending("/\(file)")
                if FileManager.default.fileExists(atPath: path) {
                    do {
                        try FileManager.default.removeItem(atPath: path)
                    } catch {}
                }
            }
        }
        
        
        class func clearBrowserCache() {
            let dataStore = WKWebsiteDataStore.default()
            dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), completionHandler: { (records) in
                for record in records{
                    WKWebsiteDataStore.default().removeData(ofTypes: record.dataTypes, for: [record], completionHandler: {
                        print("清除成功\(record)")
                    })
                }
            })
        }
        
        class func sizeOfBrowserCache() -> String {
            return ""
        }
        
    }
    
    
    展开全文
  • 直接上代码 func clearCache() { if #available(iOS 9.0, *) { let websiteDataTypes = NSSet(array: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache]) let date = NSDat...

    直接上代码

    func clearCache() {
            if #available(iOS 9.0, *) {
                let websiteDataTypes = NSSet(array: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
                let date = NSDate(timeIntervalSince1970: 0)
                WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes as! Set<String>, modifiedSince: date as Date, completionHandler:{ })
            } else {
                var libraryPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, false).first!
                libraryPath += "/Cookies"
                
                do {
                    try FileManager.default.removeItem(atPath: libraryPath)
                } catch {
                    print("error")
                }
                URLCache.shared.removeAllCachedResponses()
            }
        }

     

    展开全文
  • 使应用程序感觉快速和响应不仅仅是调整其UI的呈现方式,或者提高其操作和算法的执行速度 - 它通常与有效管理数据和...本周 - 让我们来看看缓存在这种情况下如何成为一个非常强大的工具,如何在Swift中构建一个高效优...

    使应用程序感觉快速和响应不仅仅是调整其UI的呈现方式,或者提高其操作和算法的执行速度 - 它通常与有效管理数据和避免不必要的工作同样重要。

    这种不必要工作的一个非常常见的来源是我们最终多次重新加载完全相同的数据。它可能是加载同一模型的重复副本的多个功能,或者每次重新显示在屏幕上时重新加载视图的数据。

    本周 - 让我们来看看缓存在这种情况下如何成为一个非常强大的工具,如何在Swift中构建一个高效优雅的缓存API,以及策略性地缓存各种值和对象如何对整体产生重大影响应用程序的性能。

    同时小编这里有些书籍和面试资料哦(点击下载

    系统的一部分

    缓存是最初可能看起来比实际更简单的任务之一。我们不仅要有效地存储和加载值,还需要决定何时驱逐条目以保持低内存,使陈旧数据无效等等。

    值得庆幸的是,Apple已经通过内置NSCache类为我们解决了许多这些问题。然而,使用它确实有一些警告,因为它仍然是Apple自己的平台上的Objective-C类 - 这意味着它只能存储类实例,并且它只与NSObject基于键的键兼容:

    // To be able to use strings as caching keys, we have to use
    // NSString here, since NSCache is only compatible with keys
    // that are subclasses of NSObject:
    let cache = NSCache<NSString, MyClass>()
    

    但是,通过编写一个瘦的包装器NSCache,我们可以创建一个更灵活的Swift缓存API - 它使我们能够存储结构和其他值类型,并允许我们使用任何Hashable键类型 - 而不需要我们重写所有底层逻辑权力NSCache。所以,让我们这样做。

    这一切都始于宣言

    我们要做的第一件事是声明我们的新缓存类型。让我们调用它Cache,并使其成为任何Hashable键类型和任何值类型的泛型。然后我们将为它提供一个NSCache属性,该属性将存储EntryWrappedKey类型键入的实例:

    final class Cache<Key: Hashable, Value> {
        private let wrapped = NSCache<WrappedKey, Entry>()
    }
    

    我们的WrappedKey类型将像它的名字所暗示的那样,包含我们面向公众的Key价值观,以使它们NSCache兼容。为了实现这一点,让我们继承NSObject和实施hash以及isEqual-因为这就是Objective-C的使用来确定两个实例是否相等:

    private extension Cache {
        final class WrappedKey: NSObject {
            let key: Key
    
            init(_ key: Key) { self.key = key }
    
            override var hash: Int { return key.hashValue }
    
            override func isEqual(_ object: Any?) -> Bool {
                guard let value = object as? WrappedKey else {
                    return false
                }
    
                return value.key == key
            }
        }
    }
    

    当涉及到我们的Entry类型时,唯一的要求是它需要是一个类(它不需要子类NSObject),这意味着我们可以简单地使它存储一个Value实例:

    private extension Cache {
        final class Entry {
            let value: Value
    
            init(value: Value) {
                self.value = value
            }
        }
    }
    

    有了上述内容,我们现在准备提供Cache一组初始API。让我们从三个方法开始 - 一个用于为给定键插入值,一个用于检索值,另一个用于删除现有值:

    final class Cache<Key: Hashable, Value> {
        private let wrapped = NSCache<WrappedKey, Entry>()
    
        func insert(_ value: Value, forKey key: Key) {
            let entry = Entry(value: value)
            wrapped.setObject(entry, forKey: WrappedKey(key))
        }
    
        func value(forKey key: Key) -> Value? {
            let entry = wrapped.object(forKey: WrappedKey(key))
            return entry?.value
        }
    
        func removeValue(forKey key: Key) {
            wrapped.removeObject(forKey: WrappedKey(key))
        }
    }
    

    由于缓存本质上只是一个专门的键值存储,它是下*标的*理想用例- 所以我们也可以通过这种方式检索和插入值:

    extension Cache {
        subscript(key: Key) -> Value? {
            get { return value(forKey: key) }
            set {
                guard let value = newValue else {
                    // If nil was assigned using our subscript,
                    // then we remove any value for that key:
                    removeValue(forKey: key)
                    return
                }
    
                insert(value, forKey: key)
            }
        }
    }
    

    随着最初的功能集实现 - 让我们的新东西Cache旋转!假设我们正在开发一个用于阅读文章的应用程序,并且我们正在使用它ArticleLoader来加载Article模型。通过使用我们的新缓存来存储我们加载的文章,以及在加载新文章之前检查任何以前缓存的文章 - 我们可以确保我们只加载每篇文章一次,如下所示:

    class ArticleLoader {
        typealias Handler = (Result<Article, Error>) -> Void
    
        private let cache = Cache<Article.ID, Article>()
    
        func loadArticle(withID id: Article.ID,
                         then handler: @escaping Handler) {
            if let cached = cache[id] {
                return handler(.success(cached))
            }
    
            performLoading { [weak self] result in
                let article = try? result.get()
                article.map { self?.cache[id] = $0 }
                handler(result)
            }
        }
    }
    

    优化上述加载代码的另一种方法是避免在我们要加载的文章已经加载时发出重复请求。要了解有关这种技术的更多信息,请查看“避免Swift中的竞争条件”

    以上看起来似乎不会对我们的应用程序的性能产生很大的影响,但它确实可以使我们的应用程序看起来更快,因为当用户将导航回已经加载的文章时 - 它现在会立即出现在那里。如果我们还将上述内容与用户可能打开的预取文章(例如用户最喜欢的类别中的最新文章)结合起来,那么我们真的可以让我们的应用程序使用起来更加愉快。

    避免过时的数据

    是什么让NSCache一个更适合相比,雨燕标准库(如找到的集合缓存值Dictionary)是当系统内存不足,它会自动驱逐对象-这反过来又使我们的应用程序本身留在记忆更长时间。

    但是,我们可能希望添加一些我们自己的缓存失效条件,否则我们可能最终会保留过时的数据。虽然能够重用我们已经加载的数据当然是一件好事,但向用户显示过时的数据绝对不是。

    缓解该问题的一种方法是通过在一定时间间隔之后删除它们来限制我们的缓存条目的生存期。为此,我们首先expirationDate在我们的Entry类中添加一个属性,以便能够跟踪每个条目的剩余生命周期:

    final class Entry {
        let value: Value
        let expirationDate: Date
    
        init(value: Value, expirationDate: Date) {
            self.value = value
            self.expirationDate = expirationDate
        }
    }
    

    接下来,我们需要一种方法Cache来获取当前日期,以确定给定条目是否仍然有效。虽然我们可以Date()在需要时调用内联,但这会使单元测试变得非常困难 - 所以让我们将生成Date函数作为初始化程序的一部分。我们还将添加一个entryLifetime属性,默认值为12小时:

    final class Cache<Key: Hashable, Value> {
        private let wrapped = NSCache<WrappedKey, Entry>()
        private let dateProvider: () -> Date
        private let entryLifetime: TimeInterval
    
        init(dateProvider: @escaping () -> Date = Date.init,
             entryLifetime: TimeInterval = 12 * 60 * 60) {
            self.dateProvider = dateProvider
            self.entryLifetime = entryLifetime
        }
    
        ...
    }
    

    要了解有关上述依赖注入的更多信息,请查看“使用函数进行简单Swift依赖注入”

    有了上述内容,现在让我们更新插入和检索值的方法,以获取当前日期和指定的值entryLifetime

    func insert(_ value: Value, forKey key: Key) {
        let date = dateProvider().addingTimeInterval(entryLifetime)
        let entry = Entry(value: value, expirationDate: date)
        wrapped.setObject(entry, forKey: WrappedKey(key))
    }
    
    func value(forKey key: Key) -> Value? {
        guard let entry = wrapped.object(forKey: WrappedKey(key)) else {
            return nil
        }
    
        guard dateProvider() < entry.expirationDate else {
            // Discard values that have expired
            removeValue(forKey: key)
            return nil
        }
    
        return entry.value
    }
    

    虽然准确地使过时条目无效可以说是实现任何类型的缓存最困难的部分 - 通过将上述类型的到期日期与特定于模型的逻辑相结合,可以根据某些事件删除值(例如,如果用户删除文章),我们最常见的是避免重复工作和无效数据。

    持久缓存

    到目前为止,我们只是在内存中缓存值,这意味着只要我们的应用程序终止,该数据就会消失。虽然这可能是我们真正想要的,但有时也可以将缓存值保持在磁盘上非常有价值,并且还可以解锁使用我们应用程序的新方法 - 例如在启动应用程序时仍然可以访问通过网络下载的数据离线时。

    因为我们可能只想选择性地在磁盘上保留特定的缓存 - 让它成为一个完全可选的功能。首先,我们将更新Entry以存储Key与之关联的内容,以便我们能够直接保留每个条目,并能够删除未使用的密钥:

    final class Entry {
        let key: Key
        let value: Value
        let expirationDate: Date
    
        init(key: Key, value: Value, expirationDate: Date) {
            self.key = key
            self.value = value
            self.expirationDate = expirationDate
        }
    }
    

    接下来,我们需要一种方法来跟踪缓存包含条目的键,因为NSCache不会公开该信息。为此我们将添加一个专用KeyTracker类型,它将成为我们底层的*委托*NSCache,以便在删除条目时得到通知:

    private extension Cache {
        final class KeyTracker: NSObject, NSCacheDelegate {
            var keys = Set<Key>()
    
            func cache(_ cache: NSCache<AnyObject, AnyObject>,
                       willEvictObject object: Any) {
                guard let entry = object as? Entry else {
                    return
                }
    
                keys.remove(entry.key)
            }
        }
    }
    

    我们将KeyTracker初始化时设置Cache- 我们还将设置最大条目数,这将有助于我们避免将太多数据写入磁盘 - 如下所示:

    final class Cache<Key: Hashable, Value> {
        private let wrapped = NSCache<WrappedKey, Entry>()
        private let dateProvider: () -> Date
        private let entryLifetime: TimeInterval
        private let keyTracker = KeyTracker()
    
        init(dateProvider: @escaping () -> Date = Date.init,
             entryLifetime: TimeInterval = 12 * 60 * 60,
             maximumEntryCount: Int = 50) {
            self.dateProvider = dateProvider
            self.entryLifetime = entryLifetime
            wrapped.countLimit = maximumEntryCount
            wrapped.delegate = keyTracker
        }
    
        ...
    }
    

    由于我们KeyTracker已经在从缓存中删除条目时收到通知,因此完成其集成所需要做的就是在添加密钥时通知它,我们将在insert方法中执行此操作:

    func insert(_ value: Value, forKey key: Key) {
        ...
        keyTracker.keys.insert(key)
    }
    

    为了能够实际持久化缓存的内容,我们首先需要序列化它。就像我们利用如何NSCache在系统之上构建我们自己的缓存API一样,让Codable我们使用任何兼容格式(例如JSON)来编码和解码我们的缓存。

    我们首先要使我们的Entry类型符合Codable- 但我们不希望要求所有缓存条目都是可编码的 - 所以让我们使用*条件一致性*来只采用Codable具有可编码键和值的条目,如下所示:

    extension Cache.Entry: Codable where Key: Codable, Value: Codable {}
    

    在编码和解码过程中,我们将检索和插入条目,因此为了避免重复我们之前insertvalue方法中的代码- 让我们将处理Entry实例的所有逻辑移动到两个新的私有实用程序方法中:

    private extension Cache {
        func entry(forKey key: Key) -> Entry? {
            guard let entry = wrapped.object(forKey: WrappedKey(key)) else {
                return nil
            }
    
            guard dateProvider() < entry.expirationDate else {
                removeValue(forKey: key)
                return nil
            }
    
            return entry
        }
    
        func insert(_ entry: Entry) {
            wrapped.setObject(entry, forKey: WrappedKey(entry.key))
            keyTracker.keys.insert(entry.key)
        }
    }
    

    最后一个难题是使Cache自己Codable处于我们之前使用的相同条件下 - 通过使用上述两种实用方法,我们现在可以非常轻松地对所有条目进行编码和解码:

    extension Cache: Codable where Key: Codable, Value: Codable {
        convenience init(from decoder: Decoder) throws {
            self.init()
    
            let container = try decoder.singleValueContainer()
            let entries = try container.decode([Entry].self)
            entries.forEach(insert)
        }
    
        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            try container.encode(keyTracker.keys.compactMap(entry))
        }
    }
    

    有了上述内容,我们现在可以将Cache包含Codable键和值的任何内容保存到磁盘 - 只需将其编码到Data,然后将该数据写入应用程序专用临时目录中的文件,如下所示:

    extension Cache where Key: Codable, Value: Codable {
        func saveToDisk(
            as name: String,
            at folderURL: URL = FileManager.default.temporaryDirectory
        ) throws {
            let fileURL = folderURL.appendingPathComponent(name + ".cache")
            let data = try JSONEncoder().encode(self)
            try data.write(to: fileURL)
        }
    }
    

    就这样,我们已经建立了一个高度动态高速缓存这是完全斯威夫特兼容-与支持基于时间的无效,在磁盘上的持久性,并在其上所包含的条目数量的限制-所有通过利用系统API,如NSCacheCodable以避免重新发明轮子

    结论
    策略性地部署缓存以避免不得不多次重新加载相同的数据会对应用程序的性能产生巨大的积极影响。毕竟,即使我们可以优化我们在应用程序中加载数据的方式,但根本不需要加载数据总是会更快 - 而缓存可能是实现这一目标的好方法。

    但是,在向数据加载管道添加缓存时需要记住多项事项 - 例如,不要将陈旧数据保留太长时间,在应用程序环境发生变化时(例如当用户更改其首选语言环境时)使缓存条目无效,并确保已正确清除已删除的项目。

    部署缓存时要考虑的另一件事是要缓存的数据以及在何处执行此操作。虽然我们在本文中已经看过NSCache基于基于方法的方法,但是还有其他多种路径可以被探索,例如使用另一个系统API URLCache- 来在网络层中执行我们的缓存。在接下来的文章中,我们将仔细研究它以及其他类型的缓存。

    你怎么看?你通常如何使用斯威夫特缓存,和你喜欢NSCache,URLCache或完全定制的解决方案?请通过加我们的交流群 点击此处进交流群 ,来一起交流或者发布您的问题,意见或反馈。

    谢谢阅读~点个赞再走呗!?

    原文地址 https://www.swiftbysundell.com/posts/caching-in-swift

    展开全文
  • 对Alamofire与Cache的封装实现对网络数据的缓存,可以存储JSON、String、Data,接口简单明了. 封装Alamofire下载,使用更方便. 如有问题,欢迎提出,不足之处,欢迎纠正,欢迎star ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨...
    • AlamofireCache的封装实现对网络数据的缓存,可以存储JSON、String、Data,接口简单明了.
    • 封装Alamofire下载,使用更方便.
    • 如有问题,欢迎提出,不足之处,欢迎纠正,欢迎star ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
    • Github: https://github.com/MQZHot/DaisyNet
      缓存.gif

    下载.gif

    1. 请求+缓存

    • 缓存数据只需要调用.cache(true),不调用或者.cache(false)则不缓存
    • 调用responseCacheAndString可以先读取缓存数据,再读取网络数据
    • 通过isCacheData属性可以区分缓存数据还是网络数据
    DaisyNet.request(url, params: params).cache(true).responseCacheAndJson { value in
        switch value.result {
        case .success(let json):
            if value.isCacheData {
                print("我是缓存的")
            } else {
                print("我是网络的")
            }
        case .failure(let error):
            print(error)
        }
    }
    • 你也可以分别读取缓存数据和网络数据,如下代码
    • 调用cacheJson方法获取缓存数据,调用responseJson获取网络数据
    DaisyNet.request(url, params: params).cache(true).cacheJson { json in
            print("我是缓存的")
        }.responseJson { response in
        print("我是网络的")
    }
    • 如果你不需要缓存,可以直接调用responseJson方法
    DaisyNet.request(url).responseString { response in
        switch response {
        case .success(let value): print(value)
        case .failure(let error): print(error)
        }
    }
    • 同理,如果你要缓存Data或者String,与JSON是相似的
    /// 先读取缓存,再读取网络数据
    DaisyNet.request(url).cache(true).responseCacheAndString { value in }
    DaisyNet.request(url).cache(true).responseCacheAndData { value in }
    /// 分别获取缓存和网络数据
    DaisyNet.request(url).cache(true).cacheString { string in
            print("我是缓存的")
        }.responseString { response in
        print("我是网络的")
    }
    • 取消请求
    DaisyNet.cancel(url, params: params)
    • 清除缓存
    /// 清除所有缓存
    func removeAllCache(completion: @escaping (Bool)->())
    /// 根据url和params清除缓存
    func removeObjectCache(_ url: String, params: [String: Any]? = nil, completion: @escaping (Bool)->())

    2. 下载

    思路:
    • 1.下载中的任务,用url作为key添加到DownloadManager单例中
    • 2.取消任务、删除任务以及下载失败时,将下载任务从单例中删除,保证- DownloadManager单例的downloadTasks中是正在下载的
    • 3.暂停下载,保存已经下载的data到plist文件
    DaisyNet.download(url).downloadProgress { progress in
            /// 下载进度
        }.response { response in
        /// 下载完成
    }
    • 如果正在下载中退出当前界面,再次进入时可以通过以下方法获取下载进度,并改变UI
    DaisyNet.downloadProgress(url) {
            print($0)
        }?.response(completion: { _ in
        print("下载完成")
    })
    • 获取下载状态
    DaisyNet.downloadStatus(url)
    • 获取下载百分比
    DaisyNet.downloadPercent(url)
    • 获取下载完成后文件所在位置
    DDaisyNet.downloadFilePath(url)
    • 删除某个下载
    DaisyNet.downloadDelete(url)
    • 取消某个下载
    DaisyNet.downloadCancel(url)
    展开全文
  • swift写了一个本地缓存

    千次阅读 2016-12-23 14:27:26
    // CacheFunc.swift // // Created by CJW on 16/12/18. // Copyright © 2016年 onight. All rights reserved. // import Foundation import UIKit class CacheFunc: NSObject {
  • IOS swift 清理缓存

    2020-09-04 10:19:41
    //清理缓存工具类 class CleanUpCacheUtils: NSObject { //清理所有缓存 class func clearAllCache() { let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.caches...
  • 每次加载WebView内容,如果图片可以缓存的话,速度就会非常快。默认情况下,WebView自己来加载图片,缓存的策略也是自己定的。如想要自己缓存的话,那么可以使用URLSessionDataDelegate来截获HTTP访问,如果访问的是...
  • Moya 在Swift开发中起着重要的网络交互作用,但是还有不如之处,比如网络不可用时,返回的 Response 为 nil,这时还得去解析相应的 Error Codable 可以帮助我们快速的解析数据,但是一旦声明的属性类型与json中的不...
  • 看完本文您将能够实现下面效果 Jietu20200415-123827@2x.jpg Jietu20200415-123726.gif 看完本文您将掌握的技能 掌握测试API方法 掌握从服务器获取JSON或文本 ...API(Application Programmin...
  • Core Data 学习:Core Data Stack(Swift)

    千次阅读 2016-06-01 23:15:50
    Core Data是苹果官方提供的一套框架,用来解决对象生命周期管理、对象关系图管理和持久化等方面相关的问题。Core Data是模型层的技术,Core Data帮助你构建代表程序状态的模型层。Core Data也是一种持久化技术,它...
  • Swift之沙盒与数据存储

    千次阅读 2015-01-14 16:37:03
    应用沙盒结构分析 1、应用程序包:包含了所有的资源文件和可执行文件 2、Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录 ...3、tmp:保存应用运行时所需要的临时数据,使用...
  • wang luo import Foundation import UIKit ...public typealias SwiftClosure = ((_ data:Data? , _ progressValue:Float, _ error: Error?) -> Void) class LJSessionRequestManager: NSObject{ /**
  • iOS开发之swift版异步加载网络图片  与SDWebImage异步加载网络图片的功能相似,只是代码比较简单,功能没有SD的完善与强大,支持缺省添加图片,支持本地缓存。  异步加载图片的核心代码如下:  func ...
  • swift3.0 简单的网络图片缓存原理

    千次阅读 2017-07-16 11:37:59
    图片缓存原理原理是,如内存没图片,去磁盘找,若磁盘也没有,则根据url去下载,然后缓存到内存和磁盘中,简单易用 缓存的目录结构如下图:  //存储图片的文件夹  var  ljFilePath:String = NSHomeDirectory() +...
  • iOS本地缓存数据方式有五种

    千次阅读 2016-08-19 17:36:42
    iOS本地缓存数据方式有五种: 1.直接写文件方式:可以存储的对象有NSString、NSArray、NSDictionary、NSData、NSNumber,数据全部存放在一个属性列表文件(*.plist文件)中。 2.NSUserDefaults(偏好设置),...
  • GET & POST 的对比 源码: https://github.com/SpongeBob-GitHub/Get-Post.git 1. URL - GET 所有的参数都包含在 URL 中 1. 如果需要添加参数,脚本后面使用 `?...4. 在 get 方法中,ur
  •   也可以直接删除document 下的cache 文件夹 http://mft.iteye.com/admin/blogs/2394856   import Foundation import WebKit func removeWebData() { if #available(iOS 9.0, *... let websiteDataT...
1 2 3 4 5 ... 20
收藏数 4,611
精华内容 1,844
关键字:

data缓存 swift