Permalink
Browse files

Refactor WBNoticeView for simplicity and to support easier implementa…

…tion of additional notice types.

* Reorganizes codebase to rely on properties instead of methods.
* Adds `ForSubclassEyesOnly` category to expose protected interfaces needed by subclasses to implement notice types.
* Removes the `noticeType` notion in favor of using subclassing to create notice types.
* Removes seemingly unused `defaultManager` static method.
* Removes `_raiseIfObjectIsNil:named:` method in favor of `NSParameterAssert`
* Adds Appledoc documentation to all public interfaces.
* Adds a Boolean argument to the dismiss callback block to disambiguate interactive vs. non-interactive dismissal.
* Replaces the dimissed block property with a setter method to enable code completion in Xcode.
* Adds Default-568h@2x.png image to suppress Xcode warning.
  • Loading branch information...
blakewatters committed Nov 13, 2012
1 parent 793fcb7 commit 6286f992197b395fee35356f803cffa54469f6b7
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 250628781651F7DC00D3443E /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 250628771651F7DB00D3443E /* Default-568h@2x.png */; };
592BDDE915645BEE00B78820 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 592BDDE115645BEE00B78820 /* Default.png */; };
592BDDEA15645BEE00B78820 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 592BDDE215645BEE00B78820 /* Default@2x.png */; };
592BDDEB15645BEE00B78820 /* NoticeView.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 592BDDE415645BEE00B78820 /* NoticeView.bundle */; };
@@ -31,6 +32,8 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 250628731651E78600D3443E /* WBNoticeView+ForSubclassEyesOnly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WBNoticeView+ForSubclassEyesOnly.h"; sourceTree = "<group>"; };
+ 250628771651F7DB00D3443E /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../../Default-568h@2x.png"; sourceTree = "<group>"; };
592BDDE115645BEE00B78820 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
592BDDE215645BEE00B78820 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = "<group>"; };
592BDDE415645BEE00B78820 /* NoticeView.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = NoticeView.bundle; sourceTree = "<group>"; };
@@ -55,7 +58,6 @@
59A782581562F8750001F08D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
746CBCFE1570A1D100B844B1 /* WBErrorNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBErrorNoticeView.h; sourceTree = "<group>"; };
746CBCFF1570A1D100B844B1 /* WBErrorNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBErrorNoticeView.m; sourceTree = "<group>"; };
- 746CBD011570A65D00B844B1 /* WBNoticeView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WBNoticeView_Private.h; sourceTree = "<group>"; };
746CBD061570A8FA00B844B1 /* WBSuccessNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBSuccessNoticeView.h; sourceTree = "<group>"; };
746CBD071570A8FA00B844B1 /* WBSuccessNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBSuccessNoticeView.m; sourceTree = "<group>"; };
748A6A57157D0B74003C7655 /* WBGrayGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBGrayGradientView.h; sourceTree = "<group>"; };
@@ -86,6 +88,7 @@
592BDDE015645BEE00B78820 /* Images */ = {
isa = PBXGroup;
children = (
+ 250628771651F7DB00D3443E /* Default-568h@2x.png */,
595FE868156F021E004C505B /* navigationBar.png */,
592BDDE115645BEE00B78820 /* Default.png */,
592BDDE215645BEE00B78820 /* Default@2x.png */,
@@ -166,7 +169,6 @@
children = (
592BDDE715645BEE00B78820 /* WBNoticeView.h */,
592BDDE815645BEE00B78820 /* WBNoticeView.m */,
- 746CBD011570A65D00B844B1 /* WBNoticeView_Private.h */,
592BDDE415645BEE00B78820 /* NoticeView.bundle */,
592BDDE515645BEE00B78820 /* UILabel+WBExtensions.h */,
592BDDE615645BEE00B78820 /* UILabel+WBExtensions.m */,
@@ -176,6 +178,7 @@
748A6A58157D0B74003C7655 /* WBGrayGradientView.m */,
7492FA43157C8CD700FB834C /* WBRedGradientView.h */,
7492FA44157C8CD700FB834C /* WBRedGradientView.m */,
+ 250628731651E78600D3443E /* WBNoticeView+ForSubclassEyesOnly.h */,
);
name = Private;
sourceTree = "<group>";
@@ -238,6 +241,7 @@
592BDDEA15645BEE00B78820 /* Default@2x.png in Resources */,
592BDDEB15645BEE00B78820 /* NoticeView.bundle in Resources */,
595FE869156F021E004C505B /* navigationBar.png in Resources */,
+ 250628781651F7DC00D3443E /* Default-568h@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -8,10 +8,23 @@
#import "WBNoticeView.h"
+/**
+ The `WBErrorNoticeView` class is a `WBNoticeView` subclass suitable for displaying an error to a user. The notice is presented on a red gradient background with an error icon on the left hand side of the notice. It supports the display of a title and a message.
+ */
@interface WBErrorNoticeView : WBNoticeView
-+ (WBErrorNoticeView *)errorNoticeInView:(UIView *)view title:(NSString *)title message:(NSString *)message;
+///-------------------------------
+/// @name Creating an Error Notice
+///-------------------------------
-@property (nonatomic, strong) NSString *message; // default: @"Information not provided."
+/**
+ Creates and returns an error notice in the given view with the specified title and message.
+
+ @param view The view to display the notice in.
+ @param title The title of the notice.
+ @param message The message of the notice.
+ @return The newly created error notice object.
+ */
++ (WBErrorNoticeView *)errorNoticeInView:(UIView *)view title:(NSString *)title message:(NSString *)message;
@end
@@ -7,7 +7,8 @@
//
#import "WBErrorNoticeView.h"
-#import "WBNoticeView_Private.h"
+#import "WBNoticeView+ForSubclassEyesOnly.h"
+#import "WBRedGradientView.h"
@implementation WBErrorNoticeView
@@ -25,14 +26,91 @@ + (WBErrorNoticeView *)errorNoticeInView:(UIView *)view title:(NSString *)title
- (void)show
{
- [self _showNoticeOfType:WBNoticeViewTypeError
- view:self.view
- title:self.title
- message:self.message
- duration:self.duration
- delay:self.delay
- alpha:self.alpha
- yOrigin:self.originY];
+ // Obtain the screen width
+ CGFloat viewWidth = self.view.frame.size.width;
+
+ // Locate the images
+ NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"NoticeView.bundle"];
+ NSString *noticeIconImageName = [path stringByAppendingPathComponent:@"notice_error_icon.png"];
+
+ // Make and add the title label
+ float titleYOrigin = 10.0;
+
+ self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, titleYOrigin, viewWidth - 70.0, 16.0)];
+ self.titleLabel.textColor = [UIColor whiteColor];
+ self.titleLabel.shadowOffset = CGSizeMake(0.0, -1.0);
+ self.titleLabel.shadowColor = [UIColor blackColor];
+ self.titleLabel.font = [UIFont boldSystemFontOfSize:14.0];
+ self.titleLabel.backgroundColor = [UIColor clearColor];
+ self.titleLabel.text = self.title;
+
+ // Make the message label
+ self.messageLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, 20.0 + 10.0, viewWidth - 70.0, 12.0)];
+ self.messageLabel.font = [UIFont systemFontOfSize:13.0];
+ self.messageLabel.textColor = [UIColor colorWithRed:239.0/255.0 green:167.0/255.0 blue:163.0/255.0 alpha:1.0];
+ self.messageLabel.backgroundColor = [UIColor clearColor];
+ self.messageLabel.text = message;
+
+ // Calculate the number of lines it'll take to display the text
+ NSInteger numberOfLines = [[self.messageLabel lines]count];
+ self.messageLabel.numberOfLines = numberOfLines;
+ [self.messageLabel sizeToFit];
+ CGFloat messageLabelHeight = self.messageLabel.frame.size.height;
+
+ CGRect r = self.messageLabel.frame;
+ r.origin.y = self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height;
+
+ float noticeViewHeight = 0.0;
+ double currOsVersion = [[[UIDevice currentDevice]systemVersion]doubleValue];
+ if (currOsVersion >= 6.0f) {
+ noticeViewHeight = messageLabelHeight;
+ } else {
+ // Now we can determine the height of one line of text
+ r.size.height = self.messageLabel.frame.size.height * numberOfLines;
+ r.size.width = viewWidth - 70.0;
+ self.messageLabel.frame = r;
+
+ // Calculate the notice view height
+ noticeViewHeight = 10.0;
+ if (numberOfLines > 1) {
+ noticeViewHeight += ((numberOfLines - 1) * messageLabelHeight);
+ }
+ }
+
+ // Add some bottom margin for the notice view
+ noticeViewHeight += 30.0;
+
+ // Make sure we hide completely the view, including its shadow
+ float hiddenYOrigin = -noticeViewHeight - 20.0;
+
+ // Make and add the notice view
+ self.gradientView = [[WBRedGradientView alloc] initWithFrame:CGRectMake(0.0, hiddenYOrigin, viewWidth, noticeViewHeight + 10.0)];
+ [self.view addSubview:self.gradientView];
+
+ // Make and add the icon view
+ UIImageView *iconView = [[UIImageView alloc]initWithFrame:CGRectMake(10.0, 10.0, 20.0, 30.0)];
+ iconView.image = [UIImage imageWithContentsOfFile:noticeIconImageName];
+ iconView.contentMode = UIViewContentModeScaleAspectFit;
+ iconView.alpha = 0.8;
+ [self.gradientView addSubview:iconView];
+
+ // Add the title label
+ [self.gradientView addSubview:self.titleLabel];
+
+ // Add the message label
+ [self.gradientView addSubview:self.messageLabel];
+
+ // Add the drop shadow to the notice view
+ CALayer *noticeLayer = self.gradientView.layer;
+ noticeLayer.shadowColor = [[UIColor blackColor]CGColor];
+ noticeLayer.shadowOffset = CGSizeMake(0.0, 3);
+ noticeLayer.shadowOpacity = 0.50;
+ noticeLayer.masksToBounds = NO;
+ noticeLayer.shouldRasterize = YES;
+
+ self.hiddenYOrigin = hiddenYOrigin;
+
+ [self displayNotice];
}
@end
@@ -0,0 +1,25 @@
+//
+// WBNoticeView+ForSubclassEyesOnly.h
+// NoticeView
+//
+// Created by Blake Watters on 11/12/12.
+// Copyright (c) 2012 Tito Ciuro. All rights reserved.
+//
+
+#import <QuartzCore/QuartzCore.h>
+#import "WBNoticeView.h"
+#import "UILabel+WBExtensions.h"
+
+@interface WBNoticeView (ForSubclassEyesOnly)
+
+@property(nonatomic, strong) UIView *gradientView;
+@property(nonatomic, strong) UILabel *titleLabel;
+@property(nonatomic, strong) UILabel *messageLabel;
+@property(nonatomic, assign) CGFloat hiddenYOrigin;
+
+/**
+ Tells the superclass to display the notice.
+ */
+- (void)displayNotice;
+
+@end
@@ -8,76 +8,111 @@
#import <Foundation/Foundation.h>
+/**
+ `WBNoticeView` objects provides a lightweight, non-intrusive means for displaying information to the user. The `WBNoticeView` class is an abstract class that encapsulates the interface common to all notice objects.
+ */
@interface WBNoticeView : NSObject
-typedef enum {
- WBNoticeViewTypeError = 0,
- WBNoticeViewTypeSuccess,
- WBNoticeViewTypeSticky
-} WBNoticeViewType;
-
-typedef void (^WBNoticeViewDismissedBlock)(void);
-
-@property (nonatomic, readwrite) WBNoticeViewType noticeType;
-
-@property (nonatomic, strong) UIView *view;
-@property (nonatomic, strong) NSString *title; // default: @"Unknown Error"
-
-@property (nonatomic, readwrite) CGFloat duration; // default: 0.5
-@property (nonatomic, readwrite) CGFloat delay; // default: 2.0
-@property (nonatomic, readwrite) CGFloat alpha; // default: 1.0
-@property (nonatomic, readwrite) CGFloat originY; // default: 0.0
-@property (nonatomic, readwrite, getter = isSticky) BOOL sticky; // default NO (Error and Success notice); YES (Sticky notice)
-@property (nonatomic, readwrite, strong) WBNoticeViewDismissedBlock dismissedBlock;
-
-
-+ (WBNoticeView *)defaultManager;
-
-- (id)initWithView:(UIView *)theView title:(NSString *)theTitle; // throws NSInvalidArgumentException is view is nil.
-
-- (void)show; // Must be implemented in the subclasses, or else it'll raise an exception.
-
-- (void)dismissNotice; // Only succeeds if the notice is sticky.
-
-// Error notice methods
-
-- (void)showErrorNoticeInView:(UIView *)view
- title:(NSString *)title
- message:(NSString *)message;
-
-- (void)showErrorNoticeInView:(UIView *)view
- title:(NSString *)title
- message:(NSString *)message
- duration:(float)duration
- delay:(float)delay
- alpha:(float)alpha;
-
-- (void)showErrorNoticeInView:(UIView *)view
- title:(NSString *)title
- message:(NSString *)message
- duration:(float)duration
- delay:(float)delay
- alpha:(float)alpha
- yOrigin:(CGFloat)origin;
-
-// Success notice methods
-
-- (void)showSuccessNoticeInView:(UIView *)view
- message:(NSString *)message;
-
-- (void)showSuccessNoticeInView:(UIView *)view
- message:(NSString *)message
- duration:(float)duration
- delay:(float)delay
- alpha:(float)alpha
- yOrigin:(CGFloat)origin;
-
-// Sticky notice methods
-
-- (void)showStickyNoticeInView:(UIView *)view
- message:(NSString *)message
- duration:(float)duration
- alpha:(float)alpha
- yOrigin:(CGFloat)origin;
+///----------------------------
+/// @name Initializing a Notice
+///----------------------------
+
+/**
+ Initializes the receiver with the given origin view and title.
+
+ This is the designated initializer.
+
+ @param view The view from which the notice will originate when displayed.
+ @param title The title for the notice.
+ @return The receiver, initialized with the given view and title.
+ */
+- (id)initWithView:(UIView *)view title:(NSString *)title;
+
+///---------------------------------
+/// @name Configuring Notice Display
+///---------------------------------
+
+/**
+ The view from which the notice will be displayed.
+ */
+@property (nonatomic, weak) UIView *view;
+
+/**
+ The title text for the notice.
+
+ **Default**: `"Unknown Error"`
+ */
+@property (nonatomic, copy) NSString *title;
+
+/**
+ The message for the notice. Not supported by all notice types.
+ */
+@property (nonatomic, copy) NSString *message;
+
+/**
+ The animation duration for the notice.
+
+ **Default**: `0.5`
+ */
+@property (nonatomic, readwrite) NSTimeInterval duration;
+
+/**
+ The time interval in seconds that the notice will be displayed before being automatically dismissed.
+
+ **Default**: `2.0`
+ */
+@property (nonatomic, readwrite) NSTimeInterval delay;
+
+/**
+ The amount of transparency applied to the notice. Values can range between `0.0` (transparent) and `1.0` (opaque). Values outside this range are clamped to `0.0` or `1.0`.
+
+ **Default**: `1.0`
+ */
+@property (nonatomic, readwrite) CGFloat alpha;
+
+/**
+ The number of points that the notice will be offset vertically from the origin view when being displayed.
+
+ **Default**: `0.0`
+ */
+@property (nonatomic, readwrite) CGFloat originY;
+
+/**
+ A Boolean value that determines if the notice will be automatically dismissed after the time interval specified by the `delay` property expires.
+
+ **Default**: `NO`
+ */
+@property (nonatomic, readwrite, getter = isSticky) BOOL sticky;
+
+///----------------------------------------
+/// @name Showing and Dismissing the Notice
+///----------------------------------------
+
+/**
+ Shows the notice.
+
+ @warning The `WBNoticeView` class is abstract. Concrete subclasses must provide an implementation of the `show` method or else an exception will be raised.
+ */
+- (void)show;
+
+/**
+ Dismisses the notice.
+
+ Only succeeds if the notice is sticky.
+ */
+- (void)dismissNotice;
+
+///----------------------------------
+/// @name Setting the Dismissal Block
+///----------------------------------
+
+/**
+ Sets a block to be executed when the notice is dismissed.
+
+ The block accepts a single Boolean value that indicates if the notice was dismissed interactively by the user or was dismissed due to expiration of the display interval.
+
+ @param block The block to be executed when the notice is dismissed.
+ */
+- (void)setDismissalBlock:(void (^)(BOOL dismissedInteractively))block;
@end
Oops, something went wrong.

0 comments on commit 6286f99

Please sign in to comment.