Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several improvements #5

Merged
merged 2 commits into from
Aug 30, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions ALAlertBanner/ALAlertBanner.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**/

#import <Foundation/Foundation.h>

#import "ALAlertBannerManager.h"

@interface ALAlertBanner : NSObject
#if !__has_feature(objc_arc)
#error ALAlertBanner requires to be built with ARC
#endif

@end
#if (__IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_5_0)
#error ALAlertBanner requires iOS 5 or higher
#endif
20 changes: 10 additions & 10 deletions ALAlertBanner/ALAlertBannerManager.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -65,47 +65,47 @@
/**
The global shared instance that manages the presentation and dismissal of alert banners.
*/
+(ALAlertBannerManager*)sharedManager;
+ (ALAlertBannerManager *)sharedManager;

/**
The default methods to display a banner.
*/
-(void)showAlertBannerInView:(UIView*)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString*)title;
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title;

-(void)showAlertBannerInView:(UIView*)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString*)title subtitle:(NSString*)subtitle;
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle;

/**
Optional method to set the secondsToShow duration on a per-banner basis.
*/
-(void)showAlertBannerInView:(UIView*)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString*)title subtitle:(NSString*)subtitle hideAfter:(NSTimeInterval)secondsToShow;
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle hideAfter:(NSTimeInterval)secondsToShow;

/**
Optional methods to handle a tap on a banner.

By default, supplying a tap handler will disable allowTapToDismiss on this particular banner. If you want to reinstate this behavior alongside the tap handler, you can call `[[ALAlertBannerManager sharedManager] hideAlertBanner:alertBanner];` in tappedBlock().
*/
-(void)showAlertBannerInView:(UIView*)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString*)title subtitle:(NSString*)subtitle tappedHandler:(void(^)(ALAlertBannerView *alertBanner))tappedBlock;
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle tappedHandler:(void(^)(ALAlertBannerView *alertBanner))tappedBlock;

-(void)showAlertBannerInView:(UIView*)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString*)title subtitle:(NSString*)subtitle hideAfter:(NSTimeInterval)secondsToShow tappedHandler:(void(^)(ALAlertBannerView *alertBanner))tappedBlock;
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle hideAfter:(NSTimeInterval)secondsToShow tappedHandler:(void(^)(ALAlertBannerView *alertBanner))tappedBlock;

/**
Immediately hide a specific alert banner.
*/
-(void)hideAlertBanner:(ALAlertBannerView *)alertBanner;
- (void)hideAlertBanner:(ALAlertBannerView *)alertBanner;

/**
Returns an array of all banners within a certain view.
*/
-(NSArray *)alertBannersInView:(UIView*)view;
- (NSArray *)alertBannersInView:(UIView *)view;

/**
Immediately hides all alert banners in all views.
*/
-(void)hideAllAlertBanners;
- (void)hideAllAlertBanners;

/**
Immediately hides all alert banners in a certain view.
*/
-(void)hideAlertBannersInView:(UIView*)view;
- (void)hideAlertBannersInView:(UIView *)view;

@end
150 changes: 70 additions & 80 deletions ALAlertBanner/ALAlertBannerManager.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,31 @@ this software and associated documentation files (the "Software"), to deal in
#import "ALAlertBannerManager.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
#import "ALAlertBannerView+Private.h"

# pragma mark -
# pragma mark Categories for Convenience

@interface UIView (Convenience)

@property (nonatomic, strong) NSMutableArray *alertBanners;

@end

@implementation UIView (Convenience)

@dynamic alertBanners;
-(void)setAlertBanners:(NSMutableArray *)alertBanners
{
//
//static char ALAlertBannerAlertBanners;

- (void)setAlertBanners:(NSMutableArray *)alertBanners {
objc_setAssociatedObject(self, @selector(alertBanners), alertBanners, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSMutableArray *)alertBanners
{

- (NSMutableArray *)alertBanners {
NSMutableArray *alertBannersArray = objc_getAssociatedObject(self, @selector(alertBanners));
if (alertBannersArray == nil)
{
alertBannersArray = [NSMutableArray new];
if (!alertBannersArray) {
alertBannersArray = [NSMutableArray array];
[self setAlertBanners:alertBannersArray];
}
return alertBannersArray;
Expand All @@ -58,14 +63,13 @@ @interface ALAlertBannerManager () <ALAlertBannerViewDelegate>
@property (nonatomic) dispatch_semaphore_t navBarPositionSemaphore;
@property (nonatomic, strong) NSMutableArray *bannerViews;

-(void)didRotate:(NSNotification *)note;
- (void)didRotate:(NSNotification *)note;

@end

@implementation ALAlertBannerManager

+(ALAlertBannerManager *)sharedManager
{
+ (ALAlertBannerManager *)sharedManager {
static ALAlertBannerManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Expand All @@ -74,8 +78,7 @@ +(ALAlertBannerManager *)sharedManager
return sharedManager;
}

-(id)init
{
- (id)init {
self = [super init];
if (self) {

Expand All @@ -102,28 +105,23 @@ -(id)init
return self;
}

-(void)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString *)title
{
[self showAlertBannerInView:view style:style position:position title:title subtitle:nil hideAfter:self.secondsToShow tappedHandler:nil];
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title {
return [self showAlertBannerInView:view style:style position:position title:title subtitle:nil hideAfter:self.secondsToShow tappedHandler:nil];
}

-(void)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle
{
[self showAlertBannerInView:view style:style position:position title:title subtitle:subtitle hideAfter:self.secondsToShow tappedHandler:nil];
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle {
return [self showAlertBannerInView:view style:style position:position title:title subtitle:subtitle hideAfter:self.secondsToShow tappedHandler:nil];
}

-(void)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle hideAfter:(NSTimeInterval)secondsToShow
{
[self showAlertBannerInView:view style:style position:position title:title subtitle:subtitle hideAfter:secondsToShow tappedHandler:nil];
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle hideAfter:(NSTimeInterval)secondsToShow {
return [self showAlertBannerInView:view style:style position:position title:title subtitle:subtitle hideAfter:secondsToShow tappedHandler:nil];
}

-(void)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle tappedHandler:(void (^)(ALAlertBannerView *))tappedBlock
{
[self showAlertBannerInView:view style:style position:position title:title subtitle:subtitle hideAfter:self.secondsToShow tappedHandler:tappedBlock];
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle tappedHandler:(void (^)(ALAlertBannerView *))tappedBlock {
return [self showAlertBannerInView:view style:style position:position title:title subtitle:subtitle hideAfter:self.secondsToShow tappedHandler:tappedBlock];
}

-(void)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle hideAfter:(NSTimeInterval)secondsToShow tappedHandler:(void (^)(ALAlertBannerView *))tappedBlock
{
- (ALAlertBannerView *)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle *)style position:(ALAlertBannerPosition)position title:(NSString *)title subtitle:(NSString *)subtitle hideAfter:(NSTimeInterval)secondsToShow tappedHandler:(void (^)(ALAlertBannerView *))tappedBlock {
ALAlertBannerView *alertBanner = [ALAlertBannerView alertBannerForView:view style:style position:position title:title subtitle:subtitle];
alertBanner.delegate = self;
alertBanner.tag = arc4random_uniform(SHRT_MAX);
Expand All @@ -135,16 +133,18 @@ -(void)showAlertBannerInView:(UIView *)view style:(ALAlertBannerStyle)style posi
alertBanner.tappedBlock = tappedBlock;

//keep track of all views we've added banners to, to deal with rotation events and hideAllAlertBanners
if (![self.bannerViews containsObject:view])
if (![self.bannerViews containsObject:view]) {
[self.bannerViews addObject:view];
}

[self showAlertBanner:alertBanner hideAfter:secondsToShow];

return alertBanner;
}

-(void)showAlertBanner:(ALAlertBannerView*)alertBanner hideAfter:(NSTimeInterval)delay
{
- (void)showAlertBanner:(ALAlertBannerView *)alertBanner hideAfter:(NSTimeInterval)delay {
dispatch_semaphore_t semaphore;
switch (alertBanner.position) {
switch (alertBanner.bannerPosition) {
case ALAlertBannerPositionTop:
semaphore = self.topPositionSemaphore;
break;
Expand All @@ -160,26 +160,27 @@ -(void)showAlertBanner:(ALAlertBannerView*)alertBanner hideAfter:(NSTimeInterval
dispatch_async(dispatch_get_main_queue(), ^{
[alertBanner show];

if (delay > 0)
if (delay > 0) {
[self performSelector:@selector(hideAlertBanner:) withObject:alertBanner afterDelay:delay];
}
});
});
}

# pragma mark -
# pragma mark Delegate Methods

-(void)hideAlertBanner:(ALAlertBannerView *)alertBanner
{
if (alertBanner.isScheduledToHide)
- (void)hideAlertBanner:(ALAlertBannerView *)alertBanner {
if (alertBanner.isScheduledToHide) {
return;
}

[NSOperation cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideAlertBanner:) object:alertBanner];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideAlertBanner:) object:alertBanner];

alertBanner.isScheduledToHide = YES;

dispatch_semaphore_t semaphore;
switch (alertBanner.position) {
switch (alertBanner.bannerPosition) {
case ALAlertBannerPositionTop:
semaphore = self.topPositionSemaphore;
break;
Expand All @@ -198,27 +199,27 @@ -(void)hideAlertBanner:(ALAlertBannerView *)alertBanner
});
}

-(void)alertBannerWillShow:(ALAlertBannerView *)alertBanner inView:(UIView*)view
{
- (void)alertBannerWillShow:(ALAlertBannerView *)alertBanner inView:(UIView *)view {
//make copy so we can set shadow before pushing banners
NSArray *bannersToPush = [NSArray arrayWithArray:view.alertBanners];
NSMutableArray *bannersArray = view.alertBanners;

[bannersArray addObject:alertBanner];
NSArray *bannersInSamePosition = [bannersArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.position == %i", alertBanner.position]];
NSArray *bannersInSamePosition = [bannersArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.bannerPosition == %i", alertBanner.bannerPosition]];

//set shadow before pushing other banners, because the banner push may be delayed by the fade in duration (which is set at the same time as the shadow) on iOS7
alertBanner.showShadow = (bannersInSamePosition.count > 1 ? NO : YES);

for (ALAlertBannerView *banner in bannersToPush)
if (banner.position == alertBanner.position)
for (ALAlertBannerView *banner in bannersToPush) {
if (banner.bannerPosition == alertBanner.bannerPosition) {
[banner push:alertBanner.frame.size.height forward:YES delay:alertBanner.fadeInDuration];
}
}
}

-(void)alertBannerDidShow:(ALAlertBannerView *)alertBanner inView:(UIView *)view
{
- (void)alertBannerDidShow:(ALAlertBannerView *)alertBanner inView:(UIView *)view {
dispatch_semaphore_t semaphore;
switch (alertBanner.position) {
switch (alertBanner.bannerPosition) {
case ALAlertBannerPositionTop:
semaphore = self.topPositionSemaphore;
break;
Expand All @@ -232,36 +233,31 @@ -(void)alertBannerDidShow:(ALAlertBannerView *)alertBanner inView:(UIView *)view
dispatch_semaphore_signal(semaphore);
}

-(void)alertBannerWillHide:(ALAlertBannerView *)alertBanner inView:(UIView *)view
{
- (void)alertBannerWillHide:(ALAlertBannerView *)alertBanner inView:(UIView *)view {
NSMutableArray *bannersArray = view.alertBanners;
NSArray *bannersInSamePosition = [bannersArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.position == %i", alertBanner.position]];
NSArray *bannersInSamePosition = [bannersArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.bannerPosition == %i", alertBanner.bannerPosition]];
NSUInteger index = [bannersInSamePosition indexOfObject:alertBanner];
if (index != NSNotFound && index > 0)
{
if (index != NSNotFound && index > 0) {
NSArray *bannersToPush = [bannersInSamePosition subarrayWithRange:NSMakeRange(0, index)];

for (ALAlertBannerView *banner in bannersToPush)
[banner push:-alertBanner.frame.size.height forward:NO delay:0.f];
[banner push:-alertBanner.frame.size.height forward:NO delay:0.0f];
}

else if (index == 0)
{
if (bannersInSamePosition.count > 1)
{
ALAlertBannerView *nextAlertBanner = (ALAlertBannerView*)[bannersInSamePosition objectAtIndex:1];
else if (index == 0) {
if (bannersInSamePosition.count > 1) {
ALAlertBannerView *nextAlertBanner = (ALAlertBannerView *)[bannersInSamePosition objectAtIndex:1];
[nextAlertBanner setShowShadow:YES];
}

[alertBanner setShowShadow:NO];
}
}

-(void)alertBannerDidHide:(ALAlertBannerView *)alertBanner inView:(UIView *)view
{
- (void)alertBannerDidHide:(ALAlertBannerView *)alertBanner inView:(UIView *)view {
NSMutableArray *bannersArray = view.alertBanners;
dispatch_semaphore_t semaphore;
switch (alertBanner.position) {
switch (alertBanner.bannerPosition) {
case ALAlertBannerPositionTop:
semaphore = self.topPositionSemaphore;
break;
Expand All @@ -279,52 +275,47 @@ -(void)alertBannerDidHide:(ALAlertBannerView *)alertBanner inView:(UIView *)view
# pragma mark -
# pragma mark Instance Methods

-(NSArray *)alertBannersInView:(UIView *)view
{
- (NSArray *)alertBannersInView:(UIView *)view {
/*
NSMutableArray *arrayOfBanners = [[NSMutableArray alloc] init];
for (UIView *subview in view.subviews)
if ([subview isKindOfClass:[ALAlertBannerView class]])
[arrayOfBanners addObject:(ALAlertBannerView*)subview];
[arrayOfBanners addObject:(ALAlertBannerView *)subview];
*/

return [NSArray arrayWithArray:view.alertBanners];
}

-(void)hideAlertBannersInView:(UIView *)view
{
for (ALAlertBannerView *alertBanner in [self alertBannersInView:view])
- (void)hideAlertBannersInView:(UIView *)view {
for (ALAlertBannerView *alertBanner in [self alertBannersInView:view]) {
[self hideAlertBanner:alertBanner];
}
}

-(void)hideAllAlertBanners
{
for (UIView *view in self.bannerViews)
- (void)hideAllAlertBanners {
for (UIView *view in self.bannerViews) {
[self hideAlertBannersInView:view];
}
}

# pragma mark -
# pragma mark Private Methods

-(void)didRotate:(NSNotification *)note
{
for (UIView *view in self.bannerViews)
{
NSArray *topBanners = [view.alertBanners filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.position == %i", ALAlertBannerPositionTop]];
CGFloat topYCoord = 0.f;
- (void)didRotate:(NSNotification *)note {
for (UIView *view in self.bannerViews) {
NSArray *topBanners = [view.alertBanners filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.bannerPosition == %i", ALAlertBannerPositionTop]];
CGFloat topYCoord = 0.0f;
if (AL_IOS_7_OR_GREATER)
topYCoord += [UIApplication navigationBarHeight] + kStatusBarHeight;
for (ALAlertBannerView *alertBanner in [topBanners reverseObjectEnumerator])
{
for (ALAlertBannerView *alertBanner in [topBanners reverseObjectEnumerator]) {
[alertBanner updateSizeAndSubviewsAnimated:YES];
[alertBanner updatePositionAfterRotationWithY:topYCoord animated:YES];
topYCoord += alertBanner.layer.bounds.size.height;
}

NSArray *bottomBanners = [view.alertBanners filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.position == %i", ALAlertBannerPositionBottom]];
NSArray *bottomBanners = [view.alertBanners filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.bannerPosition == %i", ALAlertBannerPositionBottom]];
CGFloat bottomYCoord = view.bounds.size.height;
for (ALAlertBannerView *alertBanner in [bottomBanners reverseObjectEnumerator])
{
for (ALAlertBannerView *alertBanner in [bottomBanners reverseObjectEnumerator]) {
//update frame size before animating to new position
[alertBanner updateSizeAndSubviewsAnimated:YES];
bottomYCoord -= alertBanner.layer.bounds.size.height;
Expand All @@ -335,8 +326,7 @@ -(void)didRotate:(NSNotification *)note
}
}

-(void)dealloc
{
- (void)dealloc {
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}

Expand Down
Loading