เป็นไปได้หรือไม่ที่จะป้องกัน NSURLRequest จากการแคชข้อมูลหรือลบข้อมูลแคชตามคำขอ


90

บน iPhone ฉันขอ HTTP โดยใช้ NSURLRequest สำหรับกลุ่มข้อมูล การจัดสรรวัตถุเพิ่มขึ้นอย่างรวดเร็วและฉันกำหนดข้อมูลตามนั้น เมื่อฉันกรอกข้อมูลเสร็จฉันก็ปล่อยมันให้เป็นอิสระ - อย่างไรก็ตามเครื่องมือไม่แสดงข้อมูลใด ๆ ที่จะได้รับการปลดปล่อย!

ทฤษฎีของฉันคือตามค่าเริ่มต้นคำขอ HTTP จะถูกแคชอย่างไรก็ตามฉันไม่ต้องการให้แอป iPhone ของฉันแคชข้อมูลนี้

มีวิธีล้างแคชนี้หลังจากการร้องขอหรือป้องกันไม่ให้แคชข้อมูลใด ๆ ตั้งแต่แรกหรือไม่?

ฉันได้ลองใช้นโยบายแคชทั้งหมดตามเอกสารด้านล่าง:

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

แต่ดูเหมือนจะไม่มีอะไรทำให้หน่วยความจำว่าง!


เป็นไปได้ไหมว่ามันไม่เกี่ยวข้องกับแคช? คุณได้ลองตรวจสอบข้อมูลเพื่อดูว่าข้อมูลที่ควรโหลดซ้ำนั้นเป็นข้อมูลเก่าหรือไม่ บางทีต้นหอมของคุณอาจมาจากที่อื่น คุณจะเริ่มต้นและปลดปล่อย NSURLRequests ได้อย่างไร? ซึ่งอาจช่วยในการวินิจฉัยปัญหา
lpfavreau

FYI - หากคุณต้องการลบไฟล์โดย brute force มีตัวอย่างโค้ดให้ทำที่นี่: salesforce.stackexchange.com/a/69736
zekel

คำตอบ:


158

โดยปกติแล้วการสร้างคำขอเช่นนี้จะง่ายกว่า

NSURLRequest *request = [NSURLRequest requestWithURL:url
      cachePolicy:NSURLRequestReloadIgnoringCacheData
      timeoutInterval:60.0];

จากนั้นสร้างการเชื่อมต่อ

NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
       delegate:self];

และใช้การเชื่อมต่อ: willCacheResponse: เมธอดบนผู้รับมอบสิทธิ์ เพียงแค่คืนศูนย์ควรทำ

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
  return nil;
}

ขอบคุณมากสำหรับความช่วยเหลือ! นิค.
Nick Cartwright

1
ขอบคุณสำหรับความคิดนั้น - ฉันเรียกใช้บริการเว็บ SOAP แบบนี้ซ้ำ ๆ และมันก็เพิ่มขึ้นเรื่อย ๆ อย่างไม่สามารถควบคุมได้แม้ว่าการรั่วไหลจะไม่ได้แสดงว่ามีอะไรผิดปกติก็ตาม ฉันปรับให้เหมาะสมมาหลายวันและในที่สุดก็พยายามป้องกันการแคชเนื่องจากมีวัตถุ CFURL * จำนวนมากจากกรอบงานภายในแขวนอยู่รอบ ๆ การคืนค่าศูนย์จาก willCacheResponse เป็นสิ่งเดียวที่ใช้ได้ผล!
Bron Davies

15
ทำไมจึงต้องทำทั้งสองอย่างNSURLRequestReloadIgnoringCacheData และนำไปใช้connection:willCacheResponse:?
fabb

1
สวัสดีฉันสามารถใช้สิ่งนี้เพื่อโหลดเนื้อหาในเครื่องได้หรือไม่? ข้างต้นมีไว้สำหรับ NSUrlConnection แต่ฉันกำลังโหลดข้อมูล HTML ในเครื่องลงใน UIWebView โดยใช้ NSUrlRequest ฉันจำเป็นต้องปฏิเสธการแคชเนื่องจากมีภาพเข้าสู่มุมมองเว็บจาก SQLite และหน่วยความจำก็เพิ่มขึ้นทุกครั้งที่โหลดหน้าเว็บ ขอบคุณ.
jim

7
@fabb การแทนที่connection:willCacheResponse:ช่วยให้คุณไม่เก็บการตอบสนองไว้ในแคช NSURLRequestReloadIgnoringCacheDataระบุว่าการเชื่อมต่อควรโหลดคำขอโดยไม่ต้องตรวจสอบแคช ในอดีตเป็นสิ่งที่ช่วยจัดการการจัดสรรหน่วยความจำ
Christopher Pickslay

12

ฉันมีปัญหาเดียวกันในแอพของฉันเมื่อฉันขอข้อมูลจาก twitter ในกรณีของฉันฉันไม่จำเป็นต้องรักษาข้อมูลรับรองเหล่านั้นดังนั้นฉันจึงลบออกโดยใช้รหัสถัดไป:

- (void) eraseCredentials{
NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [credentialsStorage allCredentials];

//iterate through all credentials to find the twitter host
for (NSURLProtectionSpace *protectionSpace in allCredentials)
    if ([[protectionSpace host] isEqualToString:@"twitter.com"]){
        //to get the twitter's credentials
        NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
        //iterate through twitter's credentials, and erase them all
        for (NSString *credentialKey in credentials)
            [credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
    }
}

ฉันหวังว่ามันจะใช้ได้กับใครสักคน :)


นี่เป็นทางออกที่สมบูรณ์แบบสำหรับปัญหาของฉันฉันมีปัญหาในการเข้าสู่ระบบอีกครั้งเนื่องจากข้อมูลประจำตัวถูกจัดเก็บและถูกส่งโดย NSURLConnection โดยอัตโนมัติขอบคุณมากสิ่งนี้ช่วยฉันได้มาก :)
RVN

ขอบคุณที่ทำงานให้ฉันฉันขอขอบคุณสำหรับข้อเสนอแนะของคุณ จริงๆแล้วปัญหาของฉันคือ NSURLRequest จัดเก็บชื่อผู้ใช้และรหัสผ่าน ดังนั้นสิ่งนี้ช่วยลบข้อมูลรับรองผู้ใช้ออกจากแคช ...
Nilesh Kikani

10

หากคุณใช้ NSURLConnection โปรดดูที่ผู้รับมอบสิทธิ์:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse

ส่งคืนค่า

การตอบสนองที่แคชจริงเพื่อจัดเก็บในแคช ผู้รับมอบสิทธิ์อาจส่งคืน cachedResponse ที่ไม่ได้แก้ไขส่งคืนการตอบกลับแคชที่แก้ไขหรือส่งคืนค่าศูนย์หากไม่ควรเก็บการตอบกลับที่แคชไว้สำหรับการเชื่อมต่อ


ขอบคุณมากที่นี่ รอยความทรงจำของแอพของฉันลดลงครึ่งหนึ่งทันที! นิค.
Nick Cartwright

9

หากคุณกำลังใช้NSURLSessionวิธีอื่นในการป้องกันคำขอและพารามิเตอร์ที่เขียนไปยังCache.dbiOS ที่สร้างขึ้นภายในCachesไดเร็กทอรีของแอปคือการตั้งค่าNSURLCacheสำหรับการกำหนดค่าของเซสชันเป็นหน่วยความจำขนาด 0 และดิสก์แคชขนาด 0เช่น

let configuration = URLSessionConfiguration.default    
configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
let session = URLSession(configuration: configuration)

หรือตามที่กล่าวไว้ข้างต้นตั้งค่าไว้ที่ระดับแคชส่วนกลาง

URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

น่าจะเป็น 0 สำหรับขนาดดิสก์ที่หยุดการเขียน iOS ลงในดิสก์ แต่ถ้าคุณมีนโยบายreloadIgnoringLocalCacheDataคุณอาจไม่สนใจแคชหน่วยความจำเช่นกัน

หมายเหตุสิ่งนี้จะป้องกันไม่ให้มีการสร้างCaches/Cache.db(การร้องขอและการตอบกลับ) หรือCaches/fsCachedData/โฟลเดอร์ (ข้อมูลการตอบกลับ) เลย เราได้ตัดสินใจที่จะใช้แนวทางนี้ในแอปเพื่อจุดประสงค์ด้านความปลอดภัยเนื่องจากเราไม่ต้องการให้คำขอของเราถูกเก็บไว้ในดิสก์แคชเลย

หากใครรู้ว่ามีวิธีหยุดเฉพาะการร้องขอการแคช แต่ยังคงแคชข้อมูลการตอบกลับจากกลไกการโหลด URL ของ iOS ฉันสนใจที่จะทราบ (ไม่มี API หรือเอกสารอย่างเป็นทางการเกี่ยวกับสิ่งนี้จากสิ่งที่ฉันบอกได้)


7

หากไม่เฉพาะเจาะจงสำหรับคำขอเดียว (คุณต้องการปิดการใช้งานแคชสำหรับทั้งแอป) ด้านล่างหนึ่งเป็นตัวเลือกที่ดีที่สุดเพิ่มรหัสนี้ในผู้ร่วมประชุมแอปหรือตามคุณต้องการที่ใด

        int cacheSizeMemory = 0*4*1024*1024; // 0MB
        int cacheSizeDisk = 0*32*1024*1024; // 0MB
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
        [NSURLCache setSharedURLCache:sharedCache];

7
ใช้งานได้ดีสำหรับฉัน แต่คุณสามารถใช้ 0 แทนการคูณที่ลงท้ายด้วย 0 ก็ได้
Gary Riches

1
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url];
[request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

สมมติว่าเซิร์ฟเวอร์ถูกนำไปใช้อย่างถูกต้องการใส่Cache-Control:no-storeส่วนหัวในคำขอจะสร้างการตอบสนองของเซิร์ฟเวอร์ที่มีส่วนหัวเดียวกันจึงทำให้NSURLCacheไม่เก็บข้อมูลการตอบสนองไว้ในดิสก์

ดังนั้นไม่จำเป็นต้องใช้ปืนลูกซองในการปิดการใช้งานการNSURLCacheแคชดิสก์

PS: การเพิ่มส่วนหัวควรใช้ได้กับเฟรมเวิร์ก HTTP ทั้งหมดเช่น AFNetworking

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.