123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- //
- // UIView+Toast.m
- // Toast
- //
- // Copyright (c) 2011-2016 Charles Scalesse.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- #import "UIView+Toast.h"
- #import <QuartzCore/QuartzCore.h>
- #import <objc/runtime.h>
- NSString * CSToastPositionTop = @"CSToastPositionTop";
- NSString * CSToastPositionCenter = @"CSToastPositionCenter";
- NSString * CSToastPositionBottom = @"CSToastPositionBottom";
- // Keys for values associated with toast views
- static const NSString * CSToastTimerKey = @"CSToastTimerKey";
- static const NSString * CSToastDurationKey = @"CSToastDurationKey";
- static const NSString * CSToastPositionKey = @"CSToastPositionKey";
- static const NSString * CSToastCompletionKey = @"CSToastCompletionKey";
- // Keys for values associated with self
- static const NSString * CSToastActiveKey = @"CSToastActiveKey";
- static const NSString * CSToastActivityViewKey = @"CSToastActivityViewKey";
- static const NSString * CSToastQueueKey = @"CSToastQueueKey";
- @interface UIView (ToastPrivate)
- /**
- These private methods are being prefixed with "cs_" to reduce the likelihood of non-obvious
- naming conflicts with other UIView methods.
-
- @discussion Should the public API also use the cs_ prefix? Technically it should, but it
- results in code that is less legible. The current public method names seem unlikely to cause
- conflicts so I think we should favor the cleaner API for now.
- */
- - (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position;
- - (void)cs_hideToast:(UIView *)toast;
- - (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap;
- - (void)cs_toastTimerDidFinish:(NSTimer *)timer;
- - (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer;
- - (CGPoint)cs_centerPointForPosition:(id)position withToast:(UIView *)toast;
- - (NSMutableArray *)cs_toastQueue;
- @end
- @implementation UIView (Toast)
- #pragma mark - Make Toast Methods
- - (void)makeToast:(NSString *)message {
- [self makeToast:message duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] style:nil];
- }
- - (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position {
- [self makeToast:message duration:duration position:position style:nil];
- }
- - (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position style:(CSToastStyle *)style {
- UIView *toast = [self toastViewForMessage:message title:nil image:nil style:style];
- [self showToast:toast duration:duration position:position completion:nil];
- }
- - (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style completion:(void(^)(BOOL didTap))completion {
- UIView *toast = [self toastViewForMessage:message title:title image:image style:style];
- [self showToast:toast duration:duration position:position completion:completion];
- }
- #pragma mark - Show Toast Methods
- - (void)showToast:(UIView *)toast {
- [self showToast:toast duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] completion:nil];
- }
- - (void)showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position completion:(void(^)(BOOL didTap))completion {
- // sanity
- if (toast == nil) return;
-
- // store the completion block on the toast view
- objc_setAssociatedObject(toast, &CSToastCompletionKey, completion, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-
- if ([CSToastManager isQueueEnabled] && [self.cs_activeToasts count] > 0) {
- // we're about to queue this toast view so we need to store the duration and position as well
- objc_setAssociatedObject(toast, &CSToastDurationKey, @(duration), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- objc_setAssociatedObject(toast, &CSToastPositionKey, position, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-
- // enqueue
- [self.cs_toastQueue addObject:toast];
- } else {
- // present
- [self cs_showToast:toast duration:duration position:position];
- }
- }
- #pragma mark - Hide Toast Method
- - (void)hideToasts {
- for (UIView *toast in [self cs_activeToasts]) {
- [self hideToast:toast];
- }
- }
- - (void)hideToast:(UIView *)toast {
- // sanity
- if (!toast || ![[self cs_activeToasts] containsObject:toast]) return;
-
- NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey);
- [timer invalidate];
-
- [self cs_hideToast:toast];
- }
- #pragma mark - Private Show/Hide Methods
- - (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position {
- toast.center = [self cs_centerPointForPosition:position withToast:toast];
- toast.alpha = 0.0;
-
- if ([CSToastManager isTapToDismissEnabled]) {
- UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cs_handleToastTapped:)];
- [toast addGestureRecognizer:recognizer];
- toast.userInteractionEnabled = YES;
- toast.exclusiveTouch = YES;
- }
-
- [[self cs_activeToasts] addObject:toast];
-
- [self addSubview:toast];
-
- [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration]
- delay:0.0
- options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction)
- animations:^{
- toast.alpha = 1.0;
- } completion:^(BOOL finished) {
- NSTimer *timer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(cs_toastTimerDidFinish:) userInfo:toast repeats:NO];
- [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
- objc_setAssociatedObject(toast, &CSToastTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }];
- }
- - (void)cs_hideToast:(UIView *)toast {
- [self cs_hideToast:toast fromTap:NO];
- }
-
- - (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap {
- [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration]
- delay:0.0
- options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState)
- animations:^{
- toast.alpha = 0.0;
- } completion:^(BOOL finished) {
- [toast removeFromSuperview];
-
- // remove
- [[self cs_activeToasts] removeObject:toast];
-
- // execute the completion block, if necessary
- void (^completion)(BOOL didTap) = objc_getAssociatedObject(toast, &CSToastCompletionKey);
- if (completion) {
- completion(fromTap);
- }
-
- if ([self.cs_toastQueue count] > 0) {
- // dequeue
- UIView *nextToast = [[self cs_toastQueue] firstObject];
- [[self cs_toastQueue] removeObjectAtIndex:0];
-
- // present the next toast
- NSTimeInterval duration = [objc_getAssociatedObject(nextToast, &CSToastDurationKey) doubleValue];
- id position = objc_getAssociatedObject(nextToast, &CSToastPositionKey);
- [self cs_showToast:nextToast duration:duration position:position];
- }
- }];
- }
- #pragma mark - View Construction
- - (UIView *)toastViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style {
- // sanity
- if(message == nil && title == nil && image == nil) return nil;
-
- // default to the shared style
- if (style == nil) {
- style = [CSToastManager sharedStyle];
- }
-
- // dynamically build a toast view with any combination of message, title, & image
- UILabel *messageLabel = nil;
- UILabel *titleLabel = nil;
- UIImageView *imageView = nil;
-
- UIView *wrapperView = [[UIView alloc] init];
- wrapperView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
- wrapperView.layer.cornerRadius = style.cornerRadius;
-
- if (style.displayShadow) {
- wrapperView.layer.shadowColor = style.shadowColor.CGColor;
- wrapperView.layer.shadowOpacity = style.shadowOpacity;
- wrapperView.layer.shadowRadius = style.shadowRadius;
- wrapperView.layer.shadowOffset = style.shadowOffset;
- }
-
- wrapperView.backgroundColor = style.backgroundColor;
-
- if(image != nil) {
- imageView = [[UIImageView alloc] initWithImage:image];
- imageView.contentMode = UIViewContentModeScaleAspectFit;
- imageView.frame = CGRectMake(style.horizontalPadding, style.verticalPadding, style.imageSize.width, style.imageSize.height);
- }
-
- CGRect imageRect = CGRectZero;
-
- if(imageView != nil) {
- imageRect.origin.x = style.horizontalPadding;
- imageRect.origin.y = style.verticalPadding;
- imageRect.size.width = imageView.bounds.size.width;
- imageRect.size.height = imageView.bounds.size.height;
- }
-
- if (title != nil) {
- titleLabel = [[UILabel alloc] init];
- titleLabel.numberOfLines = style.titleNumberOfLines;
- titleLabel.font = style.titleFont;
- titleLabel.textAlignment = style.titleAlignment;
- titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
- titleLabel.textColor = style.titleColor;
- titleLabel.backgroundColor = [UIColor clearColor];
- titleLabel.alpha = 1.0;
- titleLabel.text = title;
-
- // size the title label according to the length of the text
- CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage);
- CGSize expectedSizeTitle = [titleLabel sizeThatFits:maxSizeTitle];
- // UILabel can return a size larger than the max size when the number of lines is 1
- expectedSizeTitle = CGSizeMake(MIN(maxSizeTitle.width, expectedSizeTitle.width), MIN(maxSizeTitle.height, expectedSizeTitle.height));
- titleLabel.frame = CGRectMake(0.0, 0.0, expectedSizeTitle.width, expectedSizeTitle.height);
- }
-
- if (message != nil) {
- messageLabel = [[UILabel alloc] init];
- messageLabel.numberOfLines = style.messageNumberOfLines;
- messageLabel.font = style.messageFont;
- messageLabel.textAlignment = style.messageAlignment;
- messageLabel.lineBreakMode = NSLineBreakByTruncatingTail;
- messageLabel.textColor = style.messageColor;
- messageLabel.backgroundColor = [UIColor clearColor];
- messageLabel.alpha = 1.0;
- messageLabel.text = message;
-
- CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage);
- CGSize expectedSizeMessage = [messageLabel sizeThatFits:maxSizeMessage];
- // UILabel can return a size larger than the max size when the number of lines is 1
- expectedSizeMessage = CGSizeMake(MIN(maxSizeMessage.width, expectedSizeMessage.width), MIN(maxSizeMessage.height, expectedSizeMessage.height));
- messageLabel.frame = CGRectMake(0.0, 0.0, expectedSizeMessage.width, expectedSizeMessage.height);
- }
-
- CGRect titleRect = CGRectZero;
-
- if(titleLabel != nil) {
- titleRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding;
- titleRect.origin.y = style.verticalPadding;
- titleRect.size.width = titleLabel.bounds.size.width;
- titleRect.size.height = titleLabel.bounds.size.height;
- }
-
- CGRect messageRect = CGRectZero;
-
- if(messageLabel != nil) {
- messageRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding;
- messageRect.origin.y = titleRect.origin.y + titleRect.size.height + style.verticalPadding;
- messageRect.size.width = messageLabel.bounds.size.width;
- messageRect.size.height = messageLabel.bounds.size.height;
- }
-
- CGFloat longerWidth = MAX(titleRect.size.width, messageRect.size.width);
- CGFloat longerX = MAX(titleRect.origin.x, messageRect.origin.x);
-
- // Wrapper width uses the longerWidth or the image width, whatever is larger. Same logic applies to the wrapper height.
- CGFloat wrapperWidth = MAX((imageRect.size.width + (style.horizontalPadding * 2.0)), (longerX + longerWidth + style.horizontalPadding));
- CGFloat wrapperHeight = MAX((messageRect.origin.y + messageRect.size.height + style.verticalPadding), (imageRect.size.height + (style.verticalPadding * 2.0)));
-
- wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight);
-
- if(titleLabel != nil) {
- titleLabel.frame = titleRect;
- [wrapperView addSubview:titleLabel];
- }
-
- if(messageLabel != nil) {
- messageLabel.frame = messageRect;
- [wrapperView addSubview:messageLabel];
- }
-
- if(imageView != nil) {
- [wrapperView addSubview:imageView];
- }
-
- return wrapperView;
- }
- #pragma mark - Storage
- - (NSMutableArray *)cs_activeToasts {
- NSMutableArray *cs_activeToasts = objc_getAssociatedObject(self, &CSToastActiveKey);
- if (cs_activeToasts == nil) {
- cs_activeToasts = [[NSMutableArray alloc] init];
- objc_setAssociatedObject(self, &CSToastActiveKey, cs_activeToasts, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- return cs_activeToasts;
- }
- - (NSMutableArray *)cs_toastQueue {
- NSMutableArray *cs_toastQueue = objc_getAssociatedObject(self, &CSToastQueueKey);
- if (cs_toastQueue == nil) {
- cs_toastQueue = [[NSMutableArray alloc] init];
- objc_setAssociatedObject(self, &CSToastQueueKey, cs_toastQueue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- return cs_toastQueue;
- }
- #pragma mark - Events
- - (void)cs_toastTimerDidFinish:(NSTimer *)timer {
- [self cs_hideToast:(UIView *)timer.userInfo];
- }
- - (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer {
- UIView *toast = recognizer.view;
- NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey);
- [timer invalidate];
-
- [self cs_hideToast:toast fromTap:YES];
- }
- #pragma mark - Activity Methods
- - (void)makeToastActivity:(id)position {
- // sanity
- UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey);
- if (existingActivityView != nil) return;
-
- CSToastStyle *style = [CSToastManager sharedStyle];
-
- UIView *activityView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, style.activitySize.width, style.activitySize.height)];
- activityView.center = [self cs_centerPointForPosition:position withToast:activityView];
- activityView.backgroundColor = style.backgroundColor;
- activityView.alpha = 0.0;
- activityView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
- activityView.layer.cornerRadius = style.cornerRadius;
-
- if (style.displayShadow) {
- activityView.layer.shadowColor = style.shadowColor.CGColor;
- activityView.layer.shadowOpacity = style.shadowOpacity;
- activityView.layer.shadowRadius = style.shadowRadius;
- activityView.layer.shadowOffset = style.shadowOffset;
- }
-
- UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
- activityIndicatorView.center = CGPointMake(activityView.bounds.size.width / 2, activityView.bounds.size.height / 2);
- [activityView addSubview:activityIndicatorView];
- [activityIndicatorView startAnimating];
-
- // associate the activity view with self
- objc_setAssociatedObject (self, &CSToastActivityViewKey, activityView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-
- [self addSubview:activityView];
-
- [UIView animateWithDuration:style.fadeDuration
- delay:0.0
- options:UIViewAnimationOptionCurveEaseOut
- animations:^{
- activityView.alpha = 1.0;
- } completion:nil];
- }
- - (void)hideToastActivity {
- UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey);
- if (existingActivityView != nil) {
- [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration]
- delay:0.0
- options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState)
- animations:^{
- existingActivityView.alpha = 0.0;
- } completion:^(BOOL finished) {
- [existingActivityView removeFromSuperview];
- objc_setAssociatedObject (self, &CSToastActivityViewKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }];
- }
- }
- #pragma mark - Helpers
- - (CGPoint)cs_centerPointForPosition:(id)point withToast:(UIView *)toast {
- CSToastStyle *style = [CSToastManager sharedStyle];
-
- if([point isKindOfClass:[NSString class]]) {
- if([point caseInsensitiveCompare:CSToastPositionTop] == NSOrderedSame) {
- return CGPointMake(self.bounds.size.width/2, (toast.frame.size.height / 2) + style.verticalPadding);
- } else if([point caseInsensitiveCompare:CSToastPositionCenter] == NSOrderedSame) {
- return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
- }
- } else if ([point isKindOfClass:[NSValue class]]) {
- return [point CGPointValue];
- }
-
- // default to bottom
- return CGPointMake(self.bounds.size.width/2, (self.bounds.size.height - (toast.frame.size.height / 2)) - style.verticalPadding);
- }
- @end
- @implementation CSToastStyle
- #pragma mark - Constructors
- - (instancetype)initWithDefaultStyle {
- self = [super init];
- if (self) {
- self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8];
- self.titleColor = [UIColor whiteColor];
- self.messageColor = [UIColor whiteColor];
- self.maxWidthPercentage = 0.8;
- self.maxHeightPercentage = 0.8;
- self.horizontalPadding = 10.0;
- self.verticalPadding = 10.0;
- self.cornerRadius = 10.0;
- self.titleFont = [UIFont boldSystemFontOfSize:16.0];
- self.messageFont = [UIFont systemFontOfSize:16.0];
- self.titleAlignment = NSTextAlignmentLeft;
- self.messageAlignment = NSTextAlignmentLeft;
- self.titleNumberOfLines = 0;
- self.messageNumberOfLines = 0;
- self.displayShadow = NO;
- self.shadowOpacity = 0.8;
- self.shadowRadius = 6.0;
- self.shadowOffset = CGSizeMake(4.0, 4.0);
- self.imageSize = CGSizeMake(80.0, 80.0);
- self.activitySize = CGSizeMake(100.0, 100.0);
- self.fadeDuration = 0.2;
- }
- return self;
- }
- - (void)setMaxWidthPercentage:(CGFloat)maxWidthPercentage {
- _maxWidthPercentage = MAX(MIN(maxWidthPercentage, 1.0), 0.0);
- }
- - (void)setMaxHeightPercentage:(CGFloat)maxHeightPercentage {
- _maxHeightPercentage = MAX(MIN(maxHeightPercentage, 1.0), 0.0);
- }
- - (instancetype)init NS_UNAVAILABLE {
- return nil;
- }
- @end
- @interface CSToastManager ()
- @property (strong, nonatomic) CSToastStyle *sharedStyle;
- @property (assign, nonatomic, getter=isTapToDismissEnabled) BOOL tapToDismissEnabled;
- @property (assign, nonatomic, getter=isQueueEnabled) BOOL queueEnabled;
- @property (assign, nonatomic) NSTimeInterval defaultDuration;
- @property (strong, nonatomic) id defaultPosition;
- @end
- @implementation CSToastManager
- #pragma mark - Constructors
- + (instancetype)sharedManager {
- static CSToastManager *_sharedManager = nil;
- static dispatch_once_t oncePredicate;
- dispatch_once(&oncePredicate, ^{
- _sharedManager = [[self alloc] init];
- });
-
- return _sharedManager;
- }
- - (instancetype)init {
- self = [super init];
- if (self) {
- self.sharedStyle = [[CSToastStyle alloc] initWithDefaultStyle];
- self.tapToDismissEnabled = YES;
- self.queueEnabled = YES;
- self.defaultDuration = 3.0;
- self.defaultPosition = CSToastPositionBottom;
- }
- return self;
- }
- #pragma mark - Singleton Methods
- + (void)setSharedStyle:(CSToastStyle *)sharedStyle {
- [[self sharedManager] setSharedStyle:sharedStyle];
- }
- + (CSToastStyle *)sharedStyle {
- return [[self sharedManager] sharedStyle];
- }
- + (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled {
- [[self sharedManager] setTapToDismissEnabled:tapToDismissEnabled];
- }
- + (BOOL)isTapToDismissEnabled {
- return [[self sharedManager] isTapToDismissEnabled];
- }
- + (void)setQueueEnabled:(BOOL)queueEnabled {
- [[self sharedManager] setQueueEnabled:queueEnabled];
- }
- + (BOOL)isQueueEnabled {
- return [[self sharedManager] isQueueEnabled];
- }
- + (void)setDefaultDuration:(NSTimeInterval)duration {
- [[self sharedManager] setDefaultDuration:duration];
- }
- + (NSTimeInterval)defaultDuration {
- return [[self sharedManager] defaultDuration];
- }
- + (void)setDefaultPosition:(id)position {
- if ([position isKindOfClass:[NSString class]] || [position isKindOfClass:[NSValue class]]) {
- [[self sharedManager] setDefaultPosition:position];
- }
- }
- + (id)defaultPosition {
- return [[self sharedManager] defaultPosition];
- }
- @end
|