惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
雷峰网
雷峰网
量子位
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
T
Tailwind CSS Blog
月光博客
月光博客
博客园 - 【当耐特】
博客园_首页
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
爱范儿
爱范儿
阮一峰的网络日志
阮一峰的网络日志
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
WordPress大学
WordPress大学
The Cloudflare Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell

Peter Steinberger

OpenClaw, OpenAI and the future | Peter Steinberger Shipping at Inference-Speed | Peter Steinberger The Signature Flicker | Peter Steinberger Just Talk To It - the no-bs Way of Agentic Engineering | Peter Steinberger Claude Code Anonymous | Peter Steinberger Live Coding Session: Building Arena | Peter Steinberger My Current AI Dev Workflow | Peter Steinberger Essential Reading for Agentic Engineers - August 2025 | Peter Steinberger Just One More Prompt | Peter Steinberger Poltergeist: The Ghost That Keeps Your Builds Fresh | Peter Steinberger Don't read this Startup Slop | Peter Steinberger Essential Reading for Agentic Engineers - July 2025 | Peter Steinberger Self-Hosting AI Models After Claude's Usage Limits | Peter Steinberger Logging Privacy Shenanigans | Peter Steinberger VibeTunnel's first AI-anniversary | Peter Steinberger Making AppleScript Work in macOS CLI Tools: The Undocumented Parts | Peter Steinberger Peekaboo 2.0 – Free the CLI from its MCP shackles | Peter Steinberger Command your Claude Code Army, Reloaded | Peter Steinberger Essential Reading for Agentic Engineers | Peter Steinberger Slot Machines for Programmers: How Peter Builds Apps 20x Faster with AI | Peter Steinberger My AI Workflow for Understanding Any Codebase | Peter Steinberger stats.store: Privacy-First Sparkle Analytics | Peter Steinberger Showing Settings from macOS Menu Bar Items: A 5-Hour Journey | Peter Steinberger VibeTunnel: Turn Any Browser into Your Mac's Terminal | Peter Steinberger Vibe Meter 2.0: Calculating Claude Code Usage with Token Counting | Peter Steinberger llm.codes: Make Apple Docs AI-Readable | Peter Steinberger Automatic Observation Tracking in UIKit and AppKit: The Feature Apple Forgot to Mention | Peter Steinberger Peekaboo MCP – lightning-fast macOS screenshots for AI agents | Peter Steinberger Migrating 700+ Tests to Swift Testing: A Real-World Experience | Peter Steinberger Commanding Your Claude Code Army | Peter Steinberger
NSURLCache Uses A Disk Cache As Of iOS 5 | Peter Steinberger
Peter Steinberger · 2012-04-11 · via Peter Steinberger

While writing AFDownloadRequestOperation, a new subclass for AFNetworking, I discovered that the behavior of NSURLCache changed between iOS 4.x and iOS 5.x.

Before iOS 5, NSURLCache just saved requests to memory, even if the documentation said otherwise — the diskCapacity property was silently ignored. This led to some open-source subclasses of NSURLCache, which retrofit disk caching. Most popular is SDURLCache and my enhanced, faster fork of it. Even Apple has an example online that shows how to create a simple URLCache.

As of iOS 5, NSURLCache automatically saves responses to disk. I haven’t found anything in the release notes that confirms the change, but I tried it both with iOS 4.3/5.0/5.1 on the simulator and the device, and with every 5.x version, a disk cache file is created and populated. This is great, as many developers probably aren’t aware of this and the system just does the right thing on its own — and it’s fast:

{% img /assets/cache_db.png [477] [116] [Cache.db] %}

If the Cache-Control headers indicate that this request can be cached, iOS automatically saves it to a local SQLite cache file in AppDirectory/Caches/(bundleid)/Cache.db. For example, public, max-age=31536000 marks that the request cache will be valid for a year, as max-age is listed in seconds.

The SQLite scheme for the cache looks identical to the one used in OS X:

{% gist 2356581 %}

So, why should you care? Well, the Cache.db caches any file that has a correct Cache-Control header set. Thus, if you download a PDF document, it might end up in your disk cache as well, taking up twice the memory.

The default NSURLCache will be used, with a disk limit of 20MB. You can easily test this with GDB/LLDB:

p (int)[[NSURLCache sharedURLCache] diskCapacity]

The memoryCapacity defaults to 40MB, although the cache will clear itself in low-memory situations.

So for downloads that you manually save to disk, you might want to override the NSURLConnection delegate connection:willCacheResponse: and return nil:

{% gist 2356842 %}

When creating NSURLRequest using requestWithURL:cachePolicy:timeoutInterval:, you can define the cachePolicy, but this only allows you to choose if and how the cache will be read.

Available options are: only use the cache value (NSURLRequestReturnCacheDataDontLoad); try the cache and load if different (NSURLRequestReturnCacheDataElseLoad); or ignore the cache entirely (NSURLRequestReloadIgnoringLocalCacheData).

The default option, if not set explicitly, is NSURLRequestUseProtocolCachePolicy, which most of the time is equivalent to NSURLRequestReturnCacheDataElseLoad. This uses the cache if the object hasn’t changed. There are a few other options in the enum, but those are unimplemented.

Note: There doesn’t seem a way to force caching of certain requests; connection:willCacheResponse: is only called if the response contains a Cache-Control header, according to Apple’s documentation: {% blockquote %} The delegate receives connection:willCacheResponse: messages only for protocols that support caching. {% endblockquote %}

Lastly, Apple suggests that caching can also be fine-tuned with subclassing NSURLProtocol, which indeed allows some interesting use cases, like providing a cache for UIWebView or decrypting files on the fly.

If you’re not yet using AFNetworking, you really should. It’s a big step forward compared to classical NSURLConnection handling, even if Apple recently added a few new fancy shorthands in iOS 5. In AFNetworking, your network operations are indeed subclasses of NSOperation, which allows much better control over what’s currently running, and AFHTTPClient is the perfect base class to implement any API.