2014-09-21 30 views
14

Câu chuyện dài ngắn, tôi vừa cập nhật lên Xcode 6 để kiểm tra cách ứng dụng của tôi hoạt động trên iOS 8. Tôi nhận thấy rằng nó không sử dụng bộ nhớ cache mặc dù nó nên. Tôi đang sử dụng AFNetworking thiết lập cachePolicy như thế này:iOS 8 có phá vỡ NSURLCache không?

sessionManager.requestSerializer.cachePolicy = NSURLRequestReturnCacheDataElseLoad; 

tôi vẫn còn có một thiết bị iOS 7, trong đó tôi đã thử nghiệm mã tương tự và nó hoạt động có như mong đợi.

Có ai có giải pháp cho việc này hay không, chúng ta có cần đợi Apple sửa chữa không?

+0

Tôi đã nhận thấy điều gì đó rất giống với NSURLSession. Tôi nghĩ rằng NSURLConnection vẫn hoạt động chính xác với NSURLCache. –

+0

Tôi vừa nhận thấy điều tương tự (với AFNetworking2) với lớp con NSURLCache tùy chỉnh của tôi (storeCachedResponse: forRequest: được gọi, nhưng cachedResponseForRequest: không bao giờ được gọi). –

Trả lời

12

Tôi gần như chắc chắn rằng iOS 8.0 đã phá vỡ khả năng lưu trữ dữ liệu phản hồi HTTP của NSURLSession. Tôi đã mở một radar với Apple về vấn đề này.

Dưới đây là một số mẫu mã tôi đã viết để chứng minh điều này:

NSURLSession *session = [NSURLSession sharedSession]; 
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 
                diskCapacity:32 * 1024 * 1024 
                 diskPath:nil]; 
[NSURLCache setSharedURLCache:URLCache]; 

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 
NSURL *URL = [NSURL URLWithString:@"http://i.imgur.com/b5pyONe.jpg"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:URL 
             cachePolicy:NSURLRequestReturnCacheDataElseLoad 
            timeoutInterval:5]; 
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    if (error) { 
     NSLog(@"Error occurred"); 
    } else { 
     NSLog(@"Fetched resource!"); 
    } 
    dispatch_semaphore_signal(semaphore); 
}]; 
[task resume]; 

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 

request = [NSURLRequest requestWithURL:URL 
          cachePolicy:NSURLRequestReturnCacheDataDontLoad 
         timeoutInterval:5]; 
task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    if (error) { 
     NSLog(@"Something bad happened: %@", error); 
    } else { 
     NSLog(@"Fetched resource!"); 
    } 
}]; 
[task resume]; 

Thậm chí tạo của riêng bạn NSURLSession - với một NSURLSessionConfiguration có một NSURLCache do bạn tự tạo - sẽ không giải quyết được vấn đề này. Hiện tại, nếu bạn cần phản hồi được lưu trữ nặng, bạn phải sử dụng NSURLConnection.

+0

Đó là những gì tôi nghĩ. Tôi ngạc nhiên trước bao nhiêu vấn đề mà Apple đã có gần đây. – Pahnev

+1

Richard, bạn có câu trả lời nào từ Apple về NSURLCache không? Tôi thực sự cần bộ nhớ cache trong ứng dụng của tôi nhưng nó bị hỏng trong iOS 8 ... –

+0

@JohnKakon Chưa nghe gì từ Apple. Chỉ cần thử nghiệm với Xcode 6.1 GM và nó vẫn bị hỏng. Nếu bạn cần bộ nhớ đệm, bạn phải sử dụng NSURLConnection. –

5

NSURLConnection không hoạt động bình thường. Nó sẽ lưu trữ phản hồi đúng cách, nhưng nó never purges the cache (diskCapacity được bỏ qua) trên iOS 8.0 để bộ nhớ cache sẽ grow without limit, mặc dù thủ công xóa bộ nhớ cache không hoạt động. Đây là fixed in iOS 8.1, mặc dù removeCachedResponseForRequest: vẫn không hoạt động.

Ngoài ra, nếu bạn chỉ định kích thước bộ nhớ cache nhỏ hơn 5 megabyte, nó sẽ không lưu bất kỳ thứ gì.

1

Cả hai NSURLCacheNSURLSession đều lỗi. Ngay cả khi bạn đặt NSURLRequestReturnCacheDataElseLoad cho yêu cầu, iOS có thể thử tải lại tệp từ máy chủ. Ví dụ: khi phản hồi được lưu trong bộ nhớ cache có tiêu đề Vary. Cũng xin lưu ý rằng phương pháp

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request 

sử dụng User-Agent tiêu đề từ yêu cầu để phân biệt đối tượng được lưu trữ. Điều đó có nghĩa là iOS sẽ lưu trữ cùng một tệp hai lần, nếu bạn truy cập nó bằng NSURLSession và UIWebView, bởi vì User-Agent là khác nhau.

Các vấn đề liên quan