Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Cocoanetics/DTFoundation
Browse files Browse the repository at this point in the history
Conflicts:
	Core/Source/UIWebView+DTFoundation.h
	Core/Source/UIWebView+DTFoundation.m
  • Loading branch information
odrobnik committed Jun 19, 2012
2 parents 76a1614 + 19206fe commit 6e40577
Show file tree
Hide file tree
Showing 14 changed files with 577 additions and 8 deletions.
4 changes: 3 additions & 1 deletion Core/Source/DTASN1Parser.h
Expand Up @@ -95,7 +95,9 @@ typedef enum
- (void)parserFoundNull:(DTASN1Parser *)parser;

/**
Sent by a parser object when a NULL type is encountered.
Sent by a parser object to provide its delegate with the date encoded in the current element.
All the ASN1 date types are provided via this method.
@param parser A parser object.
@param date A date representing the date encoded in the current element.
Expand Down
49 changes: 49 additions & 0 deletions Core/Source/DTActionSheet.h
@@ -0,0 +1,49 @@
//
// DTActionSheet.h
// DTFoundation
//
// Created by Oliver Drobnik on 08.06.12.
// Copyright (c) 2012 Cocoanetics. All rights reserved.
//

typedef void (^DTActionSheetBlock)(void);

/**
Extends UIActionSheet with support for blocks
*/

@interface DTActionSheet : UIActionSheet

/**
Initializes the action sheet using the specified title.
*/
- (id)initWithTitle:(NSString *)title;

/**
Adds a custom button to the action sheet.
@param title The title of the new button.
@param block The block to execute when the button is tapped.
@returns The index of the new button. Button indices start at 0 and increase in the order they are added.
*/
- (NSInteger)addButtonWithTitle:(NSString *)title block:(DTActionSheetBlock)block;

/**
Adds a custom destructive button to the action sheet.
Since there can only be one destructive button a previously marked destructive button becomes a normal button.
@param title The title of the new button.
@param block The block to execute when the button is tapped.
@returns The index of the new button. Button indices start at 0 and increase in the order they are added.
*/
- (NSInteger)addDestructiveButtonWithTitle:(NSString *)title block:(DTActionSheetBlock)block;

/**
Adds a custom cancel button to the action sheet.
Since there can only be one cancel button a previously marked cancel button becomes a normal button.
@param title The title of the new button.
@returns The index of the new button. Button indices start at 0 and increase in the order they are added.
*/
- (NSInteger)addCancelButtonWithTitle:(NSString *)title;

@end
179 changes: 179 additions & 0 deletions Core/Source/DTActionSheet.m
@@ -0,0 +1,179 @@
//
// DTActionSheet.m
// DTFoundation
//
// Created by Oliver Drobnik on 08.06.12.
// Copyright (c) 2012 Cocoanetics. All rights reserved.
//

#import "DTActionSheet.h"

@interface DTActionSheet () <UIActionSheetDelegate>

@end

@implementation DTActionSheet
{
id <UIActionSheetDelegate> _externalDelegate;

NSMutableDictionary *_actionsPerIndex;

// lookup bitmask what delegate methods are implemented
struct
{
unsigned int delegateSupportsActionSheetCancel:1;
unsigned int delegateSupportsWillPresentActionSheet:1;
unsigned int delegateSupportsDidPresentActionSheet:1;
unsigned int delegateSupportsWillDismissWithButtonIndex:1;
unsigned int delegateSupportsDidDismissWithButtonIndex:1;
} _delegateFlags;
}

- (id)initWithTitle:(NSString *)title
{
self = [super initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];

if (self)
{
_actionsPerIndex = [[NSMutableDictionary alloc] init];
}

return self;
}

- (NSInteger)addButtonWithTitle:(NSString *)title block:(DTActionSheetBlock)block
{
NSInteger retIndex = [self addButtonWithTitle:title];

if (block)
{
NSNumber *key = [NSNumber numberWithInt:retIndex];
[_actionsPerIndex setObject:[block copy] forKey:key];
}

return retIndex;
}

- (NSInteger)addDestructiveButtonWithTitle:(NSString *)title block:(DTActionSheetBlock)block
{
NSInteger retIndex = [self addButtonWithTitle:title block:block];
[self setDestructiveButtonIndex:retIndex];

return retIndex;
}

- (NSInteger)addCancelButtonWithTitle:(NSString *)title
{
NSInteger retIndex = [self addButtonWithTitle:title];
[self setCancelButtonIndex:retIndex];

return retIndex;
}

#pragma UIActionSheetDelegate (forwarded)

- (void)actionSheetCancel:(UIActionSheet *)actionSheet
{
if (_delegateFlags.delegateSupportsActionSheetCancel)
{
[_externalDelegate actionSheetCancel:actionSheet];
}
}

- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{
if (_delegateFlags.delegateSupportsWillPresentActionSheet)
{
[_externalDelegate willPresentActionSheet:actionSheet];
}
}

- (void)didPresentActionSheet:(UIActionSheet *)actionSheet
{
if (_delegateFlags.delegateSupportsDidPresentActionSheet)
{
[_externalDelegate didPresentActionSheet:actionSheet];
}
}

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (_delegateFlags.delegateSupportsWillDismissWithButtonIndex)
{
[_externalDelegate actionSheet:actionSheet willDismissWithButtonIndex:buttonIndex];
}
}


- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSNumber *key = [NSNumber numberWithInt:buttonIndex];

DTActionSheetBlock block = [_actionsPerIndex objectForKey:key];

if (block)
{
block();
}

if (_delegateFlags.delegateSupportsDidDismissWithButtonIndex)
{
[_externalDelegate actionSheet:actionSheet didDismissWithButtonIndex:buttonIndex];
}
}


#pragma mark Properties

- (id <UIActionSheetDelegate>)delegate
{
return _externalDelegate;
}

- (void)setDelegate:(id <UIActionSheetDelegate>)delegate
{
if (delegate == self)
{
[super setDelegate:self];
}
else if (delegate == nil)
{
[super setDelegate:nil];
_externalDelegate = nil;
}
else
{
_externalDelegate = delegate;
}

// wipe
memset(&_delegateFlags, 0, sizeof(_delegateFlags));

// set flags according to available methods in delegate
if ([_externalDelegate respondsToSelector:@selector(actionSheetCancel:)])
{
_delegateFlags.delegateSupportsActionSheetCancel = YES;
}

if ([_externalDelegate respondsToSelector:@selector(willPresentActionSheet:)])
{
_delegateFlags.delegateSupportsWillPresentActionSheet = YES;
}

if ([_externalDelegate respondsToSelector:@selector(didPresentActionSheet:)])
{
_delegateFlags.delegateSupportsDidPresentActionSheet = YES;
}

if ([_externalDelegate respondsToSelector:@selector(actionSheet:willDismissWithButtonIndex:)])
{
_delegateFlags.delegateSupportsWillDismissWithButtonIndex = YES;
}

if ([_externalDelegate respondsToSelector:@selector(actionSheet:didDismissWithButtonIndex:)])
{
_delegateFlags.delegateSupportsDidDismissWithButtonIndex = YES;
}
}

@end
2 changes: 1 addition & 1 deletion Core/Source/DTDownload.m
Expand Up @@ -236,7 +236,7 @@ - (void)startWithResume:(BOOL)shouldResume

// start downloading
urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];

// without this special it would get paused during scrolling of scroll views
[urlConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode: NSRunLoopCommonModes];
[urlConnection start];
Expand Down
15 changes: 15 additions & 0 deletions Core/Source/DTDownloadCache.h
Expand Up @@ -20,6 +20,9 @@ enum {
typedef NSUInteger DTDownloadCacheOption;


typedef void (^DTDownloadCacheDataCompletionBlock)(NSData *);
typedef void (^DTDownloadCacheImageCompletionBlock)(UIImage *);

@interface DTDownloadCache : NSObject <DTDownloadDelegate>

/**
Expand Down Expand Up @@ -67,4 +70,16 @@ typedef NSUInteger DTDownloadCacheOption;
*/
- (UIImage *)cachedImageForURL:(NSURL *)URL option:(DTDownloadCacheOption)option;


/**
Provides the cached or downloaded image.
If the image is already cached it will be returned and the block not be executed. If it needs to be loaded then `nil` is returned and the block gets executed as soon as the image has been downloaded.
@param URL The URL of the image
@param option A loading option to specify wheter the file should be loaded if it is already cached.
@param completion The block to be executed when the image is available.
@returns The cached image or `nil` if none is cached.
*/
- (UIImage *)cachedImageForURL:(NSURL *)URL option:(DTDownloadCacheOption)option completion:(DTDownloadCacheImageCompletionBlock)completion;

@end
71 changes: 70 additions & 1 deletion Core/Source/DTDownloadCache.m
Expand Up @@ -46,6 +46,9 @@ @implementation DTDownloadCache
NSUInteger _maxNumberOfConcurrentDownloads;
NSUInteger _diskCapacity;

// completion handling
NSMutableDictionary *_completionHandlers;

// maintenance
dispatch_queue_t _maintenanceQueue;
dispatch_queue_t _storeQueue;
Expand Down Expand Up @@ -80,6 +83,8 @@ - (id)init

_maxNumberOfConcurrentDownloads = 1;
_diskCapacity = 1024*1024*20; // 20 MB

_completionHandlers = [[NSMutableDictionary alloc] init];
}

return self;
Expand Down Expand Up @@ -141,6 +146,14 @@ - (void)_removeDownloadFromQueue:(DTDownload *)download
[_activeDownloads removeObject:download];
[_downloads removeObjectForKey:download.URL];
[_downloadQueue removeObject:download];

// remove a handler if it exists
DTDownloadCacheDataCompletionBlock completion = [_completionHandlers objectForKey:download.URL];

if (completion)
{
[_completionHandlers removeObjectForKey:download.URL];
}
}

- (void)_startNextQueuedDownload
Expand Down Expand Up @@ -274,7 +287,7 @@ - (NSUInteger)currentDiskUsage
- (void)download:(DTDownload *)download didFailWithError:(NSError *)error
{
[self _removeDownloadFromQueue:download];

[self _startNextQueuedDownload];
}

Expand Down Expand Up @@ -308,6 +321,17 @@ - (void)download:(DTDownload *)download didFinishWithFile:(NSString *)path
[self _commitContext:tmpContext];

dispatch_sync(dispatch_get_main_queue(), ^{
// execute completion block if there is one registered
DTDownloadCacheDataCompletionBlock completion = [_completionHandlers objectForKey:download.URL];

if (completion)
{
completion(data);

[_completionHandlers removeObjectForKey:download.URL];
}

// send notification
[[NSNotificationCenter defaultCenter] postNotificationName:DTDownloadCacheDidCacheFileNotification object:download.URL];

// we transfered the file into the database, so we don't need it any more
Expand Down Expand Up @@ -604,6 +628,13 @@ - (void)_runMaintenance
});
}

#pragma mark Completion Blocks

- (void)_registerCompletion:(DTDownloadCacheDataCompletionBlock)completion forURL:(NSURL *)URL
{
[_completionHandlers setObject:[completion copy] forKey:URL];
}

#pragma mark Properties

- (void)setMaxNumberOfConcurrentDownloads:(NSUInteger)maxNumberOfConcurrentDownloads
Expand Down Expand Up @@ -681,4 +712,42 @@ - (UIImage *)cachedImageForURL:(NSURL *)URL option:(DTDownloadCacheOption)option
return cachedImage;
}

- (UIImage *)cachedImageForURL:(NSURL *)URL option:(DTDownloadCacheOption)option completion:(DTDownloadCacheImageCompletionBlock)completion
{
UIImage *cachedImage = [self cachedImageForURL:URL option:option];

if (cachedImage)
{
return cachedImage;
}

// register handler
if (completion)
{
DTDownloadCacheDataCompletionBlock internalBlock = ^(NSData *data)
{
// make an image out of the data
UIImage *cachedImage = [UIImage imageWithData:data];

if (!cachedImage)
{
NSLog(@"Illegal Data cached for %@", URL);
return;
}

// put in memory cache
NSUInteger cost = (NSUInteger)(cachedImage.size.width * cachedImage.size.height);
[_memoryCache setObject:cachedImage forKey:URL cost:cost];

// execute wrapped completion block
completion(cachedImage);
};

[self _registerCompletion:internalBlock forURL:URL];
}

return nil;
}


@end

0 comments on commit 6e40577

Please sign in to comment.