Skip to content

Commit d1faa04

Browse files
committed
Update README
1 parent 0d4ed9f commit d1faa04

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

README.md

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
* [Sync APIs](#sync-apis)
1919
* [Async APIS](#async-apis)
2020
* [Expiry date](#expiry-date)
21+
* [Observations](#observations)
22+
* [Storage observations](#storage-observations)
23+
* [Key observations](#key-observations)
2124
* [Handling JSON response](#handling-json-response)
2225
* [What about images?](#what-about-images)
2326
* [Installation](#installation)
@@ -70,8 +73,8 @@ let diskConfig = DiskConfig(name: "Floppy")
7073
let memoryConfig = MemoryConfig(expiry: .never, countLimit: 10, totalCostLimit: 10)
7174

7275
let storage = try? Storage(
73-
diskConfig: diskConfig,
74-
memoryConfig: memoryConfig,
76+
diskConfig: diskConfig,
77+
memoryConfig: memoryConfig,
7578
transformer: TransformerFactory.forCodable(ofType: User.self) // Storage<User>
7679
)
7780
```
@@ -158,7 +161,7 @@ let diskConfig = DiskConfig(
158161
// Maximum size of the disk cache storage (in bytes)
159162
maxSize: 10000,
160163
// Where to store the disk cache. If nil, it is placed in `cachesDirectory` directory.
161-
directory: try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask,
164+
directory: try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask,
162165
appropriateFor: nil, create: true).appendingPathComponent("MyPreferences"),
163166
// Data protection is used to store files in an encrypted format on disk and to decrypt them on demand
164167
protectionType: .complete
@@ -237,7 +240,7 @@ try? storage.setObject(user, forKey: "character")
237240

238241
### Async APIs
239242

240-
In `async` fashion, you deal with `Result` instead of `try catch` because the result is delivered at a later time, in order to not block the current calling queue. In the completion block, you either have `value` or `error`.
243+
In `async` fashion, you deal with `Result` instead of `try catch` because the result is delivered at a later time, in order to not block the current calling queue. In the completion block, you either have `value` or `error`.
241244

242245
You access Async APIs via `storage.async`, it is also thread safe, and you can use Sync and Async APIs in any order you want. All Async functions are constrained by `AsyncStorageAware` protocol.
243246

@@ -290,7 +293,7 @@ storage.async.removeExpiredObjects() { result in
290293
By default, all saved objects have the same expiry as the expiry you specify in `DiskConfig` or `MemoryConfig`. You can overwrite this for a specific object by specifying `expiry` for `setObject`
291294

292295
```swift
293-
// Default cexpiry date from configuration will be applied to the item
296+
// Default expiry date from configuration will be applied to the item
294297
try? storage.setObject("This is a string", forKey: "string")
295298

296299
// A given expiry date will be applied to the item
@@ -304,6 +307,61 @@ try? storage.setObject(
304307
storage.removeExpiredObjects()
305308
```
306309

310+
## Observations
311+
312+
[Storage](#storage) allows you to observe changes in the cache layer, both on
313+
a store and a key levels. The API lets you pass any object as an observer,
314+
while also passing an observation closure. The observation closure will be
315+
removed automatically when the weekly captured observer has been deallocated.
316+
317+
## Storage observations
318+
319+
```swift
320+
// Add observer
321+
let token = storage.addStorageObserver(self) { observer, storage, change
322+
switch change {
323+
case .add(let key):
324+
print("Added \(key)")
325+
case .remove(let key):
326+
print("Removed \(key)")
327+
case .removeAll:
328+
print("Removed all")
329+
case .removeExpired:
330+
print("Removed expired")
331+
}
332+
}
333+
334+
// Remove observer
335+
token.cancel()
336+
337+
// Remove all observers
338+
storage.removeAllStorageObservers()
339+
```
340+
341+
## Key observations
342+
343+
```swift
344+
let key = "user1"
345+
346+
let token = storage.addObserver(self, forKey: key) { observer, storage, change in
347+
switch change {
348+
case .edit(let before, let after):
349+
print("Changed object for \(key) from \(String(describing: before)) to \(after)")
350+
case .remove:
351+
print("Removed \(key)")
352+
}
353+
}
354+
355+
// Remove observer by token
356+
token.cancel()
357+
358+
// Remove observer for key
359+
storage.removeObserver(forKey: "user1")
360+
361+
// Remove all observers
362+
storage.removeAllKeyObservers()
363+
```
364+
307365
## Handling JSON response
308366

309367
Most of the time, our use case is to fetch some json from backend, display it while saving the json to storage for future uses. If you're using libraries like [Alamofire](https://github.com/Alamofire/Alamofire) or [Malibu](https://github.com/hyperoslo/Malibu), you mostly get json in the form of dictionary, string, or data.
@@ -360,7 +418,7 @@ You also need to add `SwiftHash.framework` in your [copy-frameworks](https://git
360418
## Author
361419

362420
- [Hyper](http://hyper.no) made this with ❤️
363-
- Inline MD5 implementation from [SwiftHash](https://github.com/onmyway133/SwiftHash)
421+
- Inline MD5 implementation from [SwiftHash](https://github.com/onmyway133/SwiftHash)
364422

365423
## Contributing
366424

0 commit comments

Comments
 (0)