ImageManager
The imageManager simplifies the process of accessing thumbnails for nodes as well as user's avatars. While the imageManager is built on top of the diskManager, its API is simplified and specialized for UIImage and OSImage objects.
User Avatars
ZeroDarkCloud user accounts have an avatar image associated with them. This avatar originates from the social media or Storm4 account they use to login to ZeroDarkCloud. There is no guaranteed that a copy of the avatar will always be on the device, so we created imageManager
APIs to access the avatar. The fetchUserAvatar
is what most applications will need to use. This API will first check if there is a copy in the in memory cache and return it if possible, else it attempt to asynchronously load it from disk, as a last resort it will attempt to downloaded from the cloud or the social media site whichever is appropriate and cache the copy for later use.
Since these operations can occur asynchronously, we return the results with blocks or swift closures. In the case of fetchUserAvatar there is a preFetchBlock and a postFetchBlock. The preFetchBlock is always invoked, synchronously before the function returns. It only returns an image if there's a match in the cache that can immediately be used. The preFetchBlock also provides a willFetch
Boolean parameter that will be FALSE if the the postFetchBlock will NOT be invoked. In the case that a an image can be provided, the postFetchBlock will be invoked after the image has been read from disk or downloaded from the cloud.
The imageManager also provides a defaultUserAvatar
function to simply the cases where no avatar was available.
The following code snippet demonstrates fetching an avatar for ZDCLocalUser or ZDCUser object.
@IBOutlet public var userAvatar : UIImageView!
// assume user is ZDCLocalUser or ZDCUser object.
// fallback to default if no image found.
let defaultImage = {
return ZDCManager.imageManager().defaultUserAvatar()
}
// handle image found in cache
let preFetch = {(image: UIImage?, willFetch: Bool) in
userAvatar.image = image ?? defaultImage()
}
// image fetched from disk or cloud
let postFetch = {(image: UIImage?, error: Error?) in
userAvatar.image = image ?? defaultImage()
}
ZDCManager.imageManager().fetchUserAvatar(user,
preFetch: preFetch,
postFetch: postFetch)
Preprocessing a user image
There might be times when you want to do some preprocessing of the user image. For example you might want to scale the image to a certain size, round the corners, give it tint, etc. . In this case there is variant of the fetchUserAvatar api that will take a processingBlock
parameter. Note that the processingBlock will be invoked on a background thread.
The API also takes a processingID
parameter which is a unique identifier that distinguishes the results of this imageProcessingBlock from other imageProcessingBlocks that you may be using in other parts of your application. For example, if your block resizes the image to 64x64, then you might pass the string "64*64". If you pass a nil processingID, then the image won't be cached in memory.
@IBOutlet public var userAvatar : UIImageView!
// assume user is ZDCLocalUser or ZDCUser object.
// fallback to default if no image found.
let defaultImage = {
return ZDCManager.imageManager().defaultUserAvatar()
}
// process image for cache
let processing = {(image: UIImage) in
return image.scaled(to: size, scalingMode: .aspectFit)
}
// handle image found in cache
let preFetch = {[weak self](image: UIImage?, willFetch: Bool) -> Void in
userAvatar.image = image ?? defaultImage()
}
// image fetched from disk or cloud
let postFetch = {[weak self](image: UIImage?, error: Error?) -> Void in
userAvatar.image = image ?? defaultImage()
}
ZDCManager.imageManager().fetchUserAvatar(user,
withProcessingID: "64*64",
processingBlock: processing,
preFetch: preFetch,
postFetch: postFetch)
Tidying up after yourself
When you are done with this particular kind of avatar you might consider invoking the flushUserAvatarsCacheWithProcessingID to remove it from the cache.
ZDCManager.imageManager().flushUserAvatarsCache(withProcessingID: "64*64")
Or assuming you are done with a particular user, you can remove that avatar's associated with that userID from the cache by calling flushUserAvatarsCache
ZDCManager.imageManager().flushUserAvatarsCache(userID)
Node Thumbnails
A ZDCNode object can have thumbnail images associated with them. Similarly the imageManager has the fetchNodeThumbnail
API and a variant with for a processingBlock for accessing these images. These APIs function the same way as the avatar APIs.
@IBOutlet public var nodeImage : UIImageView!
// assume objectID is the nodeID associated with your object
var imageNode: ZDCNode? = nil
// get a copy of the ZDCNode assciated with the objectID's thumbnail
databaseConnection.read { (transaction) in
imageNode = zdc.nodeManager.findNode(withName: "thumbnail",
parentID: objectID,
transaction: transaction)
}
// fetch and display the image
if let imageNode = imageNode {
// handle image found in cache
let preFetch = {(image: UIImage?, willInvoke: Bool) in
nodeImage.image = image ?? self.defaultImage
}
// image fetched from disk or cloud
let postFetch = {(image: UIImage?, error: Error?) in
if (image != nil) {
nodeImage.image = image
} else {
// Network request failed.
// You may want to display an error image ?
}
}
ZDCManager.imageManager().fetchNodeThumbnail(imageNode,
preFetch: preFetch,
postFetch: postFetch)
}
In addition there is are the flushNodeThumbnailCache
and flushNodeThumbnailCacheWithProcessingID
API's for explicitly flushing these thumbnails from he cache.