Detailed explanation of IOS network image Cache

Source: Internet
Author: User

IOS network image cache details

 

 

 

 

 

When developing mobile applications, such as Android and IOS, our mobile applications target the Internet and frequently access the network due to factors such as mobile phone traffic, network speed, and memory, network optimization is particularly important.

For example, if an application needs to display network images frequently, it will not be able to download images from the Internet each time. This will take too much time and traffic, and the network image will be cached, the following are some of my opinions on IOS network image caching and some shortcomings. You are welcome to point them out and discuss them together.

 

Steps for processing the network image cache:

1. Check whether the memory has this image based on the image URL. If yes, return the image. If NO, go to step 2.

2. Check whether the physical storage has this image. If yes, return the image. If NO, go to step 3.

3. Download the image from the network, save it to the memory and physical storage, and return the image.

Note: Because the URL contains special characters and the length is unknown, MD5 processing or other processing should be performed on the URL.

 

The following describes the code for the above steps:

1. Memory Cache Image Processing

Use NSMutableDictionary to store the image UIImage. The Key of the array is the URL address of the image.

// Cache images to memory
[Plain]View plaincopy
  1. [MemCache setObject: image forKey: key];


2. Physical cache Image Processing

If you keep the image on a physical storage device, you can directly use NSFileManager to save the URL as a file name.

 

3. online image download Processing

The image is downloaded asynchronously. After the download, the image is saved to NSMutableDictionary and physical storage.

 

The following is a class from SDWebImageleik network image cache processing., With detailed notes

. H file

[Plain]View plaincopy
  1. @ Interface SDImageCache: NSObject
  2. {
  3. NSMutableDictionary * memCache; // memory cache image reference
  4. NSString * diskCachePath; // physical cache path
  5. NSOperationQueue * cacheInQueue, * cacheOutQueue;
  6. }
  7.  
  8. + (SDImageCache *) nvidimagecache;
  9.  
  10. // Save the image
  11. -(Void) storeImage :( UIImage *) image forKey :( NSString *) key;
  12.  
  13. // Save the image and select whether to save it to the physical storage.
  14. -(Void) storeImage :( UIImage *) image forKey :( NSString *) key toDisk :( BOOL) toDisk;
  15.  
  16. // Save the image. You can save NSData to physical storage.
  17. -(Void) storeImage :( UIImage *) image imageData :( NSData *) data forKey :( NSString *) key toDisk :( BOOL) toDisk;
  18.  
  19. // Return UIImage with key
  20. -(UIImage *) imageFromKey :( NSString *) key;
  21.  
  22. // If an error occurred while obtaining the memory image, can the image be searched on the physical storage?
  23. -(UIImage *) imageFromKey :( NSString *) key fromDisk :( BOOL) fromDisk;
  24.  
  25.  
  26. -(Void) queryDiskCacheForKey :( NSString *) key delegate :( id ) Delegate userInfo :( NSDictionary *) info;
  27.  
  28. // Clear the key index image
  29. -(Void) removeImageForKey :( NSString *) key;
  30. // Clear memory image
  31. -(Void) clearMemory;
  32. // Clear the physical Cache
  33. -(Void) clearDisk;
  34. // Clear expired physical Cache
  35. -(Void) cleanDisk;
  36.  
  37. @ End
    . M file[Plain]View plaincopy
    1. @ Implementation SDImageCache
    2.  
    3. # Pragma mark NSObject
    4.  
    5. -(Id) init
    6. {
    7. If (self = [super init])
    8. {
    9. // Init the memory cache
    10. MemCache = [[NSMutableDictionary alloc] init];
    11.  
    12. // Init the disk cache
    13. NSArray * paths = NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES );
    14. DiskCachePath = [[[paths objectAtIndex: 0] stringByAppendingPathComponent: @ ImageCache] retain];
    15.  
    16. If (! [[NSFileManager defaultManager] fileExistsAtPath: diskCachePath])
    17. {
    18. [[NSFileManager defaultManager] createDirectoryAtPath: diskCachePath
    19. WithIntermediateDirectories: YES
    20. Attributes: nil
    21. Error: NULL];
    22. }
    23.  
    24. // Init the operation queue
    25. CacheInQueue = [[NSOperationQueue alloc] init];
    26. CacheInQueue. maxConcurrentOperationCount = 1;
    27. CacheOutQueue = [[NSOperationQueue alloc] init];
    28. CacheOutQueue. maxConcurrentOperationCount = 1;
    29.  
    30. # If TARGET_ OS _IPHONE
    31. // Subscribe to app events
    32. [[Nsicationcenter center defacenter center] addObserver: self
    33. Selector: @ selector (clearMemory)
    34. Name: UIApplicationDidReceiveMemoryWarningNotification
    35. Object: nil];
    36.  
    37. [[Nsicationcenter center defacenter center] addObserver: self
    38. Selector: @ selector (cleanDisk)
    39. Name: UIApplicationWillTerminateNotification
    40. Object: nil];
    41.  
    42. # If _ IPHONE_ OS _VERSION_MIN_REQUIRED> = _ IPHONE_4_0
    43. UIDevice * device = [UIDevice currentDevice];
    44. If ([device respondsToSelector: @ selector (isMultitaskingSupported)] & device. multitaskingSupported)
    45. {
    46. // When in background, clean memory in order to have less chance to be killed
    47. [[Nsicationcenter center defacenter center] addObserver: self
    48. Selector: @ selector (clearMemory)
    49. Name: UIApplicationDidEnterBackgroundNotification
    50. Object: nil];
    51. }
    52. # Endif
    53. # Endif
    54. }
    55.  
    56. Return self;
    57. }
    58.  
    59. -(Void) dealloc
    60. {
    61. [MemCache release], memCache = nil;
    62. [DiskCachePath release], diskCachePath = nil;
    63. [CacheInQueue release], cacheInQueue = nil;
    64.  
    65. [[Nsicationcenter center defacenter center] removeObserver: self];
    66.  
    67. [Super dealloc];
    68. }
    69.  
    70. # Pragma mark SDImageCache (class methods)
    71.  
    72. + (SDImageCache *) nvidimagecache
    73. {
    74. If (instance = nil)
    75. {
    76. Instance = [[SDImageCache alloc] init];
    77. }
    78.  
    79. Return instance;
    80. }
    81.  
    82. # Pragma mark SDImageCache (private)
    83.  
    84. /*
    85. * Create a path for the specified image key
    86. */
    87. -(NSString *) cachePathForKey :( NSString *) key
    88. {
    89. Const char * str = [key UTF8String];
    90. Unsigned char r [CC_MD5_DIGEST_LENGTH];
    91. CC_MD5 (str, (CC_LONG) strlen (str), r );
    92. NSString * filename = [NSString stringWithFormat: @ % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x % 02x,
    93. R [0], r [1], r [2], r [3], r [4], r [5], r [6], r [7], r [8], r [9], r [10], r [11], r [12], r [13], r [14], r [15];
    94.  
    95. Return [diskCachePath stringByAppendingPathComponent: filename];
    96. }
    97.  
    98. /*
    99. * Save key and Data to physical storage
    100. * KeyAndData [0]-> key
    101. * KeyAndData [1]-> Data
    102. */
    103. -(Void) storeKeyWithDataToDisk :( NSArray *) keyAndData
    104. {
    105. // Can't use defaultManager another thread
    106. NSFileManager * fileManager = [[NSFileManager alloc] init];
    107.  
    108. NSString * key = [keyAndData objectAtIndex: 0];
    109. NSData * data = [keyAndData count]> 1? [KeyAndData objectAtIndex: 1]: nil;
    110.  
    111. // If data exists, it is saved to the physical storage.
    112. If (data)
    113. {
    114. [FileManager createFileAtPath: [self cachePathForKey: key] contents: data attributes: nil];
    115. }
    116. Else
    117. {
    118. // If no data exists, convert the UIImage to JPEG and save it to the physical storage.
    119. // If no data representation given, convert the UIImage in JPEG and store it
    120. // This trick is more CPU/memory intensive and doesn' t preserve alpha channel
    121. UIImage * image = [[self imageFromKey: key fromDisk: YES] retain]; // be thread safe with no lock
    122. If (image)
    123. {
    124. # If TARGET_ OS _IPHONE
    125. [FileManager createFileAtPath: [self cachePathForKey: key] contents: UIImageJPEGRepresentation (image, (CGFloat) 1.0) attributes: nil];
    126. # Else
    127. NSArray * representations = [image representations];
    128. NSData * upload data = [NSBitmapImageRep representationOfImageRepsInArray: representations usingType: ns1_filetype properties: nil];
    129. [FileManager createFileAtPath: [self cachePathForKey: key] contents: external data attributes: nil];
    130. # Endif
    131. [Image release];
    132. }
    133. }
    134.  
    135. [FileManager release];
    136. }
    137.  
    138. /*
    139. * Search for image Delegation
    140. */
    141. -(Void) policydelegate :( NSDictionary *) arguments
    142. {
    143. NSString * key = [arguments objectForKey: @ key];
    144. Id Delegate = [arguments objectForKey: @ delegate];
    145. NSDictionary * info = [arguments objectForKey: @ userInfo];
    146. UIImage * image = [arguments objectForKey: @ image];
    147.  
    148. If (image)
    149. {
    150. [MemCache setObject: image forKey: key];
    151.  
    152. If ([delegate respondsToSelector: @ selector (imageCache: didFindImage: forKey: userInfo :)])
    153. {
    154. [Delegate imageCache: self didFindImage: image forKey: key userInfo: info];
    155. }
    156. }
    157. Else
    158. {
    159. If ([delegate respondsToSelector: @ selector (imageCache: didNotFindImageForKey: userInfo :)])
    160. {
    161. [Delegate imageCache: self didNotFindImageForKey: key userInfo: info];
    162. }
    163. }
    164. }
    165.  
    166. /*
    167. * Search for images in the physical Cache
    168. */
    169. -(Void) queryDiskCacheOperation :( NSDictionary *) arguments
    170. {
    171. NSString * key = [arguments objectForKey: @ key];
    172. NSMutableDictionary * mutableArguments = [[arguments mutableCopy] autorelease];
    173.  
    174. UIImage * image = [[UIImage alloc] initWithContentsOfFile: [self cachePathForKey: key] autorelease];
    175. If (image)
    176. {
    177. # Ifdef ENABLE_SDWEBIMAGE_DECODER
    178. UIImage * decodedImage = [UIImage decodedImageWithImage: image];
    179. If (decodedImage)
    180. {
    181. Image = decodedImage;
    182. }
    183. # Endif
    184. [MutableArguments setObject: image forKey: @ image];
    185. }
    186.  
    187. [Self defined mselecw.mainthread: @ selector (policydelegate :) withObject: mutableArguments waitUntilDone: NO];
    188. }
    189.  
    190. # Pragma mark ImageCache
    191.  
    192. /*
    193. * Cache Images
    194. *
    195. **/
    196. -(Void) storeImage :( UIImage *) image imageData :( NSData *) data forKey :( NSString *) key toDisk :( BOOL) toDisk
    197. {
    198. If (! Image |! Key)
    199. {
    200. Return;
    201. }
    202.  
    203. // Cache images to memory
    204. [MemCache setObject: image forKey: key];
    205.  
    206. // If the data needs to be cached to the physical storage and is not empty, the data will be cached to the physical storage.
    207. If (toDisk)
    208. {
    209. If (! Data) return;
    210. NSArray * keyWithData;
    211. If (data)
    212. {
    213. KeyWithData = [NSArray arrayWithObjects: key, data, nil];
    214. }
    215. Else
    216. {
    217. KeyWithData = [NSArray arrayWithObjects: key, nil];
    218. }
    219. // The background thread caches images to physical storage.
    220. [CacheInQueue addOperation: [[NSInvocationOperation alloc] initWithTarget: self
    221. Selector: @ selector (storeKeyWithDataToDisk :)
    222. Object: keyWithData] autorelease];
    223. }
    224. }
    225.  
    226. /*
    227. * Save images to memory instead of physical storage
    228. */
    229. -(Void) storeImage :( UIImage *) image forKey :( NSString *) key
    230. {
    231. [Self storeImage: image imageData: nil forKey: key toDisk: YES];
    232. }
    233. /*
    234. * Save images to memory instead of physical storage
    235. */
    236. -(Void) storeImage :( UIImage *) image forKey :( NSString *) key toDisk :( BOOL) toDisk
    237. {
    238. [Self storeImage: image imageData: nil forKey: key toDisk: toDisk];
    239. }
    240.  
    241. /*
    242. * Return the specified image using the key.
    243. */
    244. -(UIImage *) imageFromKey :( NSString *) key
    245. {
    246. Return [self imageFromKey: key fromDisk: YES];
    247. }
    248.  
    249. /*
    250. * Returns an image.
    251. * Key: the key of the image.
    252. * FromDisk: If there is no image in the memory, check whether it is found on the physical storage.
    253. * Return returns the searched image. If not, returns nil.
    254. */
    255. -(UIImage *) imageFromKey :( NSString *) key fromDisk :( BOOL) fromDisk
    256. {
    257. If (key = nil)
    258. {
    259. Return nil;
    260. }
    261.  
    262. UIImage * image = [memCache objectForKey: key];
    263.  
    264. If (! Image & fromDisk) // if there is no image in the memory and you can search for it on the physical storage, the image on the physical storage is returned.
    265. {
    266. Image = [[[UIImage alloc] initWithContentsOfFile: [self cachePathForKey: key] autorelease];
    267. If (image)
    268. {
    269. [MemCache setObject: image forKey: key];
    270. }
    271. }
    272.  
    273. Return image;
    274. }
    275.  
    276. -(Void) queryDiskCacheForKey :( NSString *) key delegate :( id ) Delegate userInfo :( NSDictionary *) info
    277. {
    278. If (! Delegate)
    279. {
    280. Return;
    281. }
    282.  
    283. If (! Key)
    284. {
    285. If ([delegate respondsToSelector: @ selector (imageCache: didNotFindImageForKey: userInfo :)])
    286. {
    287. [Delegate imageCache: self didNotFindImageForKey: key userInfo: info];
    288. }
    289. Return;
    290. }
    291.  
    292. // First check the in-memory cache...
    293. UIImage * image = [memCache objectForKey: key];
    294. If (image)
    295. {
    296. //... Your y delegate immediately, no need to go async
    297. If ([delegate respondsToSelector: @ selector (imageCache: didFindImage: forKey: userInfo :)])
    298. {
    299. [Delegate imageCache: self didFindImage: image forKey: key userInfo: info];
    300. }
    301. Return;
    302. }
    303.  
    304. NSMutableDictionary * arguments = [NSMutableDictionary dictionaryWithCapacity: 3];
    305. [Arguments setObject: key forKey: @ key];
    306. [Arguments setObject: delegate forKey: @ delegate];
    307. If (info)
    308. {
    309. [Arguments setObject: info forKey: @ userInfo];
    310. }
    311. [CacheOutQueue addOperation: [[[NSInvocationOperation alloc] initWithTarget: self selector: @ selector (queryDiskCacheOperation :) object: arguments] autorelease];
    312. }
    313.  
    314. /*
    315. * Remove a specified image from memory and physical storage
    316. */
    317. -(Void) removeImageForKey :( NSString *) key
    318. {
    319. If (key = nil)
    320. {
    321. Return;
    322. }
    323.  
    324. [MemCache removeObjectForKey: key];
    325. [[NSFileManager defaultManager] removeItemAtPath: [self cachePathForKey: key] error: nil];
    326. }
    327. /*
    328. * Clear images in the memory cache area
    329. */
    330. -(Void) clearMemory
    331. {
    332. [CacheInQueue cancelAllOperations]; // won't be able to complete
    333. [MemCache removeAllObjects];
    334. }
    335.  
    336. /*
    337. * Clear images stored in physical storage
    338. */
    339. -(Void) clearDisk
    340. {
    341. [CacheInQueue cancelAllOperations];
    342. [[NSFileManager defaultManager] removeItemAtPath: diskCachePath error: nil];
    343. [[NSFileManager defaultManager] createDirectoryAtPath: diskCachePath
    344. WithIntermediateDirectories: YES
    345. Attributes: nil
    346. Error: NULL];
    347. }
    348. /*
    349. * Clear expired cached images
    350. */
    351. -(Void) cleanDisk
    352. {
    353. NSDate * expirationDate = [NSDate dateWithTimeIntervalSinceNow:-cacheMaxCacheAge];
    354. NSDirectoryEnumerator * fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath: diskCachePath];
    355. For (NSString * fileName in fileEnumerator)
    356. {
    357. NSString * filePath = [diskCachePath stringByAppendingPathComponent: fileName];
    358. NSDictionary * attrs = [[NSFileManager defaultManager] attributesOfItemAtPath: filePath error: nil];
    359. If ([[[attrs fileModificationDate] laterDate: expirationDate] isEqualToDate: expirationDate])
    360. {
    361. [[NSFileManager defaultManager] removeItemAtPath: filePath error: nil];
    362. }
    363. }
    364. }
    365.  
    366. @ End

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.