Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift 3/Xcode 8-缓存读取:无法打开缓存文件;NetworkStorageDB:\u openDBReadConnections:无法打开到数据库的读取连接_Ios_Uitableview_Caching_Swift3_Nsurlcache - Fatal编程技术网

Ios Swift 3/Xcode 8-缓存读取:无法打开缓存文件;NetworkStorageDB:\u openDBReadConnections:无法打开到数据库的读取连接

Ios Swift 3/Xcode 8-缓存读取:无法打开缓存文件;NetworkStorageDB:\u openDBReadConnections:无法打开到数据库的读取连接,ios,uitableview,caching,swift3,nsurlcache,Ios,Uitableview,Caching,Swift3,Nsurlcache,我目前正在开发一个iOS应用程序,需要从几个提要中检索一些信息。使用这些数据,我创建了一个表视图来显示它们。不幸的是,有时我会出现以下错误: NetworkStorageDB:_openDBReadConnections: failed to open read connection to DB CacheRead: unable to open cache files in... 以下是调试控制台中的内容: 2016-10-27 10:59:54.490 tdr-ios-prototype

我目前正在开发一个iOS应用程序,需要从几个提要中检索一些信息。使用这些数据,我创建了一个表视图来显示它们。不幸的是,有时我会出现以下错误:

NetworkStorageDB:_openDBReadConnections: failed to open read connection to DB

CacheRead: unable to open cache files in...
以下是调试控制台中的内容:

2016-10-27 10:59:54.490 tdr-ios-prototype[5216:129128] NetworkStorageDB:_openDBReadConnections: failed to open read connection to DB @ /Users/e-novinfo/Library/Developer/CoreSimulator/Devices/1EE7579E-CEC3-4CBF-BB64-438FCDE1C61A/data/Containers/Data/Application/06427070-79E6-4534-BAFC-7EAFF79460C7/Library/Caches/com.e-novinfo.tdr-ios-prototype/Cache.db.  Error=14. Cause=unable to open database file
2016-10-27 10:59:54.491 tdr-ios-prototype[5216:129128] CacheRead: unable to open cache files in /Users/e-novinfo/Library/Developer/CoreSimulator/Devices/1EE7579E-CEC3-4CBF-BB64-438FCDE1C61A/data/Containers/Data/Application/06427070-79E6-4534-BAFC-7EAFF79460C7/Library/Caches/com.e-novinfo.tdr-ios-prototype
基本上,我只是从一个URL解析一个JSON,然后使用我扩展的
URLCache
类来检查是否有特定请求的缓存。当有大量数据时,我经常遇到这个问题,比如从YouTube检索视频或从Picasa检索图片时

我以这种方式获取数据:在相关表视图控制器的
viewdide
上,调用名为
loadMedia
的方法,该方法将使用一个类,例如PicasaWebServices(singleton)。最后一个类将通过
URLSession.shared.dataTask
到达JSON。在发出请求之前,我会检查相关请求是否有缓存,如果缓存不是太旧,我会使用它。否则,我会清理缓存。如果没有连接(通过可达性检查),则使用缓存。最后,如果有响应,则将数据放置在表视图控制器中。创建显示时,可以通过
URLSession.shared.dataTask
访问其他信息,如我需要的图像(我使用
UIImageView
扩展名来实现这一点)

我首先怀疑缓存过载,所以在我的
URLCache
扩展中添加了一些检查,但没有解决问题。可能有太多的请求
URLSession.shared.dataTask
,我不得不延迟它们,但我不知道该怎么做

只有在使用模拟器运行应用程序时,才会发生此错误。在iPhone 6上,有时,在相同的情况下,我会出现以下错误:

libc++abi.dylib: terminating with uncaught exception of type NSException
当显示Picasa的相册列表时,我试图通过点击一行转到下一个显示相册内容的视图时,经常会发生这种情况

任何帮助都将不胜感激!非常感谢

例如,以下是我的Picasa Web服务:

class PicasaWebServices {

    //MARK: Properties

    /**********************/
    /***** PROPERTIES *****/
    /**********************/

    static let sharedInstance = PicasaWebServices()

    fileprivate var googleApiKey: String = "..."
    fileprivate var picasaUsername: String = "..."

    fileprivate var reachability: Reachability?

    /****************************************/
    /****************************************/

    /****************/
    /***** INIT *****/
    /****************/

    fileprivate init() {

        self.reachability = Reachability()!

    //END init
    }

    /****************************************/
    /****************************************/

    /*****************************/
    /***** GET PICASA ALBUMS *****/
    /*****************************/

    func getPicasaAlbums( _ completionHandler:@escaping ( Array< Dictionary< String, AnyObject > >?, NSError? ) -> Void ) {

        let requestURL = "http://picasaweb.google.com/data/feed/api/user/\( picasaUsername )?kind=album&access=public&prettyprint=true&thumbsize=320c&imgmax=640&fields=entry(id,title,link(@href),gphoto:id,media:group(media:thumbnail,media:description))&alt=json"

        let url = URL( string: requestURL )!
        let request = NSMutableURLRequest( url: url )

        URLCache().checkIfCacheForRequest( request )

        URLSession.shared.dataTask( with: request as URLRequest ) { data, response, error in

            if error != nil {

                completionHandler( nil, error as NSError? )
                return;

            }

            var jsonError: NSError?
            var jsonResult: AnyObject?

            do {

                jsonResult = try JSONSerialization.jsonObject( with: data!, options: [] ) as AnyObject

            } catch let error as NSError {

                jsonError = error
                jsonResult = nil

            } catch {

                fatalError()

            }

            var albums: Array< Dictionary< String, AnyObject > > = []

            let jsonResultFeed = jsonResult![ "feed" ] as! [ String: AnyObject ]

            if let items = jsonResultFeed[ "entry" ] as? [ [ String: AnyObject ] ] {

                for item in items {

                    albums.append( item )

                //END for item in items
                }

            //END if let items = jsonResultFeed[ "entry" ] as? [ [ String: AnyObject ] ]
            }

            completionHandler( albums, jsonError );

        //END let dataTask = urlSession.dataTaskWithURL( url, completionHandler: { ( data, response, error ) -> Void in
        }.resume()

    //END getPicasaAlbums
    }

    /****************************************/
    /****************************************/

    /************************************/
    /***** GET PICASA ALBUM CONTENT *****/
    /************************************/

    func getPicasaAlbumContent( _ requestURL: String, completionHandler:@escaping ( Array<Dictionary<String, AnyObject>>?, NSError? ) -> Void ) {

        let url = URL( string: requestURL )!
        let request = NSMutableURLRequest( url: url )

        URLCache().checkIfCacheForRequest( request )

        URLSession.shared.dataTask( with: request as URLRequest ) { data, response, error in

            if error != nil {

                completionHandler( nil, error as NSError? )
                return;

            }

            var jsonError: NSError?
            var jsonResult: AnyObject?

            do {

                jsonResult = try JSONSerialization.jsonObject( with: data!, options: [] ) as AnyObject

            } catch let error as NSError {

                jsonError = error
                jsonResult = nil

            } catch {

                fatalError()

            }

            var photos: Array< Dictionary< String, AnyObject > > = []

            let jsonResultFeed = jsonResult![ "feed" ] as! [ String: AnyObject ]

            if let items = jsonResultFeed[ "entry" ] as? [ [ String: AnyObject ] ] {

                for item in items {

                    photos.append( item )

                //END for item in items
                }

            //END if let items = jsonResultFeed[ "entry" ] as? [ [ String: AnyObject ] ] 
            }

            completionHandler( photos, jsonError );

        //END let dataTask = urlSession.dataTaskWithURL( url, completionHandler: { ( data, response, error ) -> Void in
        }.resume()

    //END getPicasaAlbumContent
    }

//END PicasaWebServices
}
其中我调用数据(TableViewController):

更新1:

因此,经过多次检查,问题似乎来自使用URLCache扩展时的UIImageView扩展。当有许多图像要加载时,检查缓存的状态似乎有问题,并引发
CacheRead:cannot open cache files in…
错误。对于TableViewController,图像通过
cellForRowAt
功能加载。你知道我怎么处理吗

/*******************/
/***** IMPORTS *****/
/*******************/

import UIKit

/****************************************/
/****************************************/

/**********************/
/***** ERROR TYPE *****/
/**********************/

enum UrlCacheExtensionError: Error {
    case empty
    case dateError
}

/****************************************/
/****************************************/

/*****************/
/***** CLASS *****/
/*****************/

extension URLCache {

    /**********************************/
    /***** GET THE REQUEST'S DATE *****/
    /**********************************/

    /*
     * @param Dictionary headers            request's headers
     * @return NSDate
     */

    public func getRequestDate( _ headers: Dictionary< String, AnyObject > ) throws -> Date {

        var output = Date()

        guard !headers.isEmpty else {
            throw UrlCacheExtensionError.empty
        }

        if let theDate = headers[ "Date" ] as? String {

            let formatedDate = Date().formateStringToDate( theDate, format: "E, dd MMM yyyy HH:mm:ss zzz", localIdentifier: "en_US" )

            print( formatedDate )

            output = formatedDate

        }

        return output

    //END getRequestDate
    }

    /****************************************/
    /****************************************/

    /*************************************/
    /***** GET THE REQUEST'S HEADERS *****/
    /*************************************/

    /*
     * @param NSMutableURLRequest request   the request
     * @return Dictionary
     */

    public func getRequestHeaders( _ request: NSMutableURLRequest ) throws -> Dictionary<NSObject, AnyObject> {

        var headers: Dictionary<NSObject, AnyObject>

        let cacheResponse = URLCache.shared.cachedResponse( for: request as URLRequest )

        if let response = cacheResponse?.response as? HTTPURLResponse {

            headers = response.allHeaderFields as Dictionary<NSObject, AnyObject>

        } else {

            throw UrlCacheExtensionError.empty

        }

        return headers


    //END getRequestHeaders
    }

    /****************************************/
    /****************************************/

    /**************************************************/
    /***** CHECK IF CACHE IS OLDER THAN ONE VALUE *****/
    /**************************************************/

    /*
     * @param NSDate date                   the cache date
     * @param Int time                      time to compare
     * @return Bool
     */

    public func checkIfCacheIsOlder( _ date: Date, time: Int ) throws -> Bool {

        guard date == date else {
            throw UrlCacheExtensionError.dateError
        }

        if Date().compareDatesInSeconds( date ) >= time {
            return true
        } else {
            return false
        }

    //END checkIfCacheIsOlder
    }

    /****************************************/
    /****************************************/

    /********************************************************************/
    /***** CHECK IF THE CACHE HAS BE CLEANED FOR A SPECIFIC REQUEST *****/
    /********************************************************************/

    /*
     * @param NSMutableURLRequest request   the request
     * @return Bool
     */

    @discardableResult
    public func checkIfCacheHasToBeCleanedForRequest( _ request: NSMutableURLRequest ) -> Bool {

        let reachability = Reachability()!

        if !reachability.isReachable {
            return false

        } else {

            do {

                let requestHeaders = try getRequestHeaders( request )

                do {

                    let requestDate = try getRequestDate( requestHeaders as! Dictionary<String, AnyObject> )

                    do {

                        let isCacheOlder = try checkIfCacheIsOlder( requestDate, time: 30 )

                        if isCacheOlder {

                            //Broken in 9.3 & 9.3.1
                            //NSURLCache.sharedURLCache().removeCachedResponseForRequest( request )
                            URLCache.shared.removeAllCachedResponses()

                            return true

                        } else {

                            return false
                        }

                    } catch {
                        return false
                    }

                } catch {
                    return false
                }

            } catch {
                return false
            }

        //END else
        }

    //END checkIfCacheHasToBeCleanedForRequest
    }

    /****************************************/
    /****************************************/

    /**************************/
    /***** CHECK CAPACITY *****/
    /**************************/

    public func checkCapacity() -> Void {

        if URLCache().currentMemoryUsage >= URLCache().memoryCapacity || URLCache().currentDiskUsage >= URLCache().diskCapacity {
            URLCache.shared.removeAllCachedResponses()
        }

        return

    //END checkCapacity
    }

    /****************************************/
    /****************************************/

    /*************************************/
    /***** CHECK CACHE FOR A REQUEST *****/
    /*************************************/

    /*
     * @param NSMutableURLRequest request   the request
     * @return Bool
     */

    @discardableResult
    public func checkIfCacheForRequest( _ request: NSMutableURLRequest ) -> Bool {

        let reachability = Reachability()!

        if reachability.isReachable {

            self.checkCapacity()

            let theRequest = self.checkIfCacheHasToBeCleanedForRequest( request )

            if theRequest {

                request.cachePolicy = .reloadIgnoringCacheData
                return false

            } else {
                request.cachePolicy = .returnCacheDataElseLoad
                return true
            }

        //END if reachability.isReachable
        } else {

            request.cachePolicy = .returnCacheDataDontLoad
            return false

        }

    //END checkIfCacheForRequest
    }

//END NSURLCache
}
extension UIImageView {

    /*******************************/
    /***** DOWNLOADED FROM URL *****/
    /*******************************/

    func downloadedFrom( url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit, completionHandler: @escaping( _ image: UIImage?, NSError? ) -> Void ) {

        contentMode = mode

        let request = NSMutableURLRequest( url: url )
        URLCache().checkIfCacheForRequest( request )

        URLSession.shared.dataTask( with: request as URLRequest ) { ( data, response, error ) in

        //URLSession.shared.dataTask( with: url ) { ( data, response, error ) in

            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix( "image" ),
                let data = data, error == nil,
                let image = UIImage( data: data )
                else { return }

            completionHandler( image as UIImage, nil )

        //END URLSession.shared.dataTask
        }.resume()

    //END downloadedFrom
    }

    /****************************************/
    /****************************************/

    /********************************/
    /***** DOWNLOADED FROM LINK *****/
    /********************************/

    func downloadedFrom( link: String, contentMode mode: UIViewContentMode = .scaleAspectFit ) {

        guard let url = URL( string: link ) else { return }

        self.downloadedFrom( url: url, contentMode: mode, completionHandler: { ( image, error ) -> Void in

            if image != nil {

                DispatchQueue.main.async( execute: {
                    self.image = image
                } )

            //END if posts != nil
            }

        //END self.downloadedFrom( url: url, contentMode: mode, completionHandler: { ( image, error ) -> Void in
        } )

    //END downloadedFrom
    }

//END UIImageViewExtension
}
func loadMedia() {

    PicasaWebServices.sharedInstance.getPicasaAlbums( { ( albums, error ) -> Void in

        if albums != nil {

            self.media?.removeAll()

            self.media = albums

            DispatchQueue.main.async( execute: {
                self.tableView.reloadData()
            } )

        //END if albums != nil
        }

    //END PicasaWebServices.sharedInstance.getPicasaAlbums
    } )

}