Skip to content

Instantly share code, notes, and snippets.

@solomon23
Created November 19, 2014 04:08
Show Gist options
  • Save solomon23/f000472061dedee11fde to your computer and use it in GitHub Desktop.
Save solomon23/f000472061dedee11fde to your computer and use it in GitHub Desktop.
//
// MWPhoto.h
// MWPhotoBrowser
//
// Created by Michael Waterfall on 17/10/2010.
// Copyright 2010 d3i. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MWPhotoProtocol.h"
// This class models a photo/image and it's caption
// If you want to handle photos, caching, decompression
// yourself then you can simply ensure your custom data model
// conforms to MWPhotoProtocol
@interface MWPhotoObj : NSObject <MWPhoto>
@property (nonatomic, strong) NSString *caption;
@property (nonatomic, readonly) UIImage *image;
@property (nonatomic, readonly) NSURL *photoURL;
@property (nonatomic, readonly) NSString *filePath __attribute__((deprecated("Use photoURL"))); // Depreciated
+ (MWPhotoObj *)photoWithImage:(UIImage *)image;
+ (MWPhotoObj *)photoWithFilePath:(NSString *)path __attribute__((deprecated("Use photoWithURL: with a file URL"))); // Depreciated
+ (MWPhotoObj *)photoWithURL:(NSURL *)url;
- (id)initWithImage:(UIImage *)image;
- (id)initWithURL:(NSURL *)url;
- (id)initWithFilePath:(NSString *)path __attribute__((deprecated("Use initWithURL: with a file URL"))); // Depreciated
@end
//
// MWPhoto.m
// MWPhotoBrowser
//
// Created by Michael Waterfall on 17/10/2010.
// Copyright 2010 d3i. All rights reserved.
//
#import "MWPhoto.h"
#import "MWPhotoBrowser.h"
#import "SDWebImageDecoder.h"
#import "SDWebImageManager.h"
#import "SDWebImageOperation.h"
#import <AssetsLibrary/AssetsLibrary.h>
@interface MWPhotoObj () {
BOOL _loadingInProgress;
id <SDWebImageOperation> _webImageOperation;
}
- (void)imageLoadingComplete;
@end
@implementation MWPhotoObj
@synthesize underlyingImage = _underlyingImage; // synth property from protocol
#pragma mark - Class Methods
+ (MWPhotoObj *)photoWithImage:(UIImage *)image {
return [[MWPhotoObj alloc] initWithImage:image];
}
// Deprecated
+ (MWPhotoObj *)photoWithFilePath:(NSString *)path {
return [MWPhotoObj photoWithURL:[NSURL fileURLWithPath:path]];
}
+ (MWPhotoObj *)photoWithURL:(NSURL *)url {
return [[MWPhotoObj alloc] initWithURL:url];
}
#pragma mark - Init
- (id)initWithImage:(UIImage *)image {
if ((self = [super init])) {
_image = image;
}
return self;
}
// Deprecated
- (id)initWithFilePath:(NSString *)path {
if ((self = [super init])) {
_photoURL = [NSURL fileURLWithPath:path];
}
return self;
}
- (id)initWithURL:(NSURL *)url {
if ((self = [super init])) {
_photoURL = [url copy];
}
return self;
}
#pragma mark - MWPhoto Protocol Methods
- (UIImage *)underlyingImage {
return _underlyingImage;
}
- (void)loadUnderlyingImageAndNotify {
NSAssert([[NSThread currentThread] isMainThread], @"This method must be called on the main thread.");
if (_loadingInProgress) return;
_loadingInProgress = YES;
@try {
if (self.underlyingImage) {
[self imageLoadingComplete];
} else {
[self performLoadUnderlyingImageAndNotify];
}
}
@catch (NSException *exception) {
self.underlyingImage = nil;
_loadingInProgress = NO;
[self imageLoadingComplete];
}
@finally {
}
}
// Set the underlyingImage
- (void)performLoadUnderlyingImageAndNotify {
// Get underlying image
if (_image) {
// We have UIImage!
self.underlyingImage = _image;
[self imageLoadingComplete];
} else if (_photoURL) {
// Check what type of url it is
if ([[[_photoURL scheme] lowercaseString] isEqualToString:@"assets-library"]) {
// Load from asset library async
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@autoreleasepool {
@try {
ALAssetsLibrary *assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:_photoURL
resultBlock:^(ALAsset *asset){
ALAssetRepresentation *rep = [asset defaultRepresentation];
CGImageRef iref = [rep fullScreenImage];
if (iref) {
self.underlyingImage = [UIImage imageWithCGImage:iref];
}
[self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO];
}
failureBlock:^(NSError *error) {
self.underlyingImage = nil;
MWLog(@"Photo from asset library error: %@",error);
[self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO];
}];
} @catch (NSException *e) {
MWLog(@"Photo from asset library error: %@", e);
[self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO];
}
}
});
} else if ([_photoURL isFileReferenceURL]) {
// Load from local file async
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@autoreleasepool {
@try {
self.underlyingImage = [UIImage imageWithContentsOfFile:_photoURL.path];
if (!_underlyingImage) {
MWLog(@"Error loading photo from path: %@", _photoURL.path);
}
} @finally {
[self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO];
}
}
});
} else {
// Load async from web (using SDWebImage)
@try {
SDWebImageManager *manager = [SDWebImageManager sharedManager];
_webImageOperation = [manager downloadImageWithURL:_photoURL
options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (expectedSize > 0) {
float progress = receivedSize / (float)expectedSize;
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:progress], @"progress",
self, @"photo", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:MWPHOTO_PROGRESS_NOTIFICATION object:dict];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (error) {
MWLog(@"SDWebImage failed to download image: %@", error);
}
_webImageOperation = nil;
self.underlyingImage = image;
[self imageLoadingComplete];
}];
} @catch (NSException *e) {
MWLog(@"Photo from web: %@", e);
_webImageOperation = nil;
[self imageLoadingComplete];
}
}
} else {
// Failed - no source
@throw [NSException exceptionWithName:nil reason:nil userInfo:nil];
}
}
// Release if we can get it again from path or url
- (void)unloadUnderlyingImage {
_loadingInProgress = NO;
self.underlyingImage = nil;
}
- (void)imageLoadingComplete {
NSAssert([[NSThread currentThread] isMainThread], @"This method must be called on the main thread.");
// Complete so notify
_loadingInProgress = NO;
// Notify on next run loop
[self performSelector:@selector(postCompleteNotification) withObject:nil afterDelay:0];
}
- (void)postCompleteNotification {
[[NSNotificationCenter defaultCenter] postNotificationName:MWPHOTO_LOADING_DID_END_NOTIFICATION
object:self];
}
- (void)cancelAnyLoading {
if (_webImageOperation) {
[_webImageOperation cancel];
_loadingInProgress = NO;
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment