Skip to content

Commit

Permalink
Merge pull request #91 from dmiedema/NullabiltyUpdates
Browse files Browse the repository at this point in the history
Nullability & Document updates
  • Loading branch information
nfarina committed Sep 10, 2015
2 parents 2aede5d + 0be48e4 commit 60cad9e
Showing 1 changed file with 119 additions and 57 deletions.
176 changes: 119 additions & 57 deletions SMCalloutView.h
Expand Up @@ -6,26 +6,31 @@
SMCalloutView
-------------
Created by Nick Farina (nfarina@gmail.com)
Version 2.0.3
Version 2.1.2
*/

// options for which directions the callout is allowed to "point" in.
/// options for which directions the callout is allowed to "point" in.
typedef NS_OPTIONS(NSUInteger, SMCalloutArrowDirection) {
SMCalloutArrowDirectionUp = 1 << 0,
SMCalloutArrowDirectionDown = 1 << 1,
SMCalloutArrowDirectionAny = SMCalloutArrowDirectionUp | SMCalloutArrowDirectionDown
};

// options for the callout present/dismiss animation
/// options for the callout present/dismiss animation
typedef NS_ENUM(NSInteger, SMCalloutAnimation) {
SMCalloutAnimationBounce, // the "bounce" animation we all know and love from UIAlertView
SMCalloutAnimationFade, // a simple fade in or out
SMCalloutAnimationStretch // grow or shrink linearly, like in the iPad Calendar app
/// the "bounce" animation we all know and love from @c UIAlertView
SMCalloutAnimationBounce,
/// a simple fade in or out
SMCalloutAnimationFade,
/// grow or shrink linearly, like in the iPad Calendar app
SMCalloutAnimationStretch
};

// when delaying our popup in order to scroll content into view, you can use this amount to match the
// animation duration of UIScrollView when using -setContentOffset:animated.
NS_ASSUME_NONNULL_BEGIN

/// when delaying our popup in order to scroll content into view, you can use this amount to match the
/// animation duration of UIScrollView when using @c -setContentOffset:animated.
extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView;

@protocol SMCalloutViewDelegate;
Expand All @@ -37,47 +42,93 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView;

@interface SMCalloutView : UIView

@property (nonatomic, unsafe_unretained) id<SMCalloutViewDelegate> delegate;
@property (nonatomic, copy) NSString *title, *subtitle; // title/titleView relationship mimics UINavigationBar.
@property (nonatomic, retain) UIView *leftAccessoryView, *rightAccessoryView;
@property (nonatomic, assign) SMCalloutArrowDirection permittedArrowDirection; // default SMCalloutArrowDirectionDown
@property (nonatomic, weak, nullable) id<SMCalloutViewDelegate> delegate;
/// title/titleView relationship mimics UINavigationBar.
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) NSString *subtitle;

/// Left accessory view for the call out
@property (nonatomic, strong, nullable) UIView *leftAccessoryView;
/// Right accessoty view for the call out
@property (nonatomic, strong, nullable) UIView *rightAccessoryView;
/// Default @c SMCalloutArrowDirectionDown
@property (nonatomic, assign) SMCalloutArrowDirection permittedArrowDirection;
/// The current arrow direction
@property (nonatomic, readonly) SMCalloutArrowDirection currentArrowDirection;
@property (nonatomic, assign) UIEdgeInsets constrainedInsets; // if the UIView you're constraining to has portions that are overlapped by nav bar, tab bar, etc. you'll need to tell us those insets.
@property (nonatomic, retain) SMCalloutBackgroundView *backgroundView; // default is SMCalloutMaskedBackgroundView, or SMCalloutDrawnBackgroundView when using SMClassicCalloutView

// Custom title/subtitle views. if these are set, the respective title/subtitle properties will be ignored.
// Keep in mind that SMCalloutView calls -sizeThatFits on titleView/subtitleView if defined, so your view
// may be resized as a result of that (especially if you're using UILabel/UITextField). You may want to subclass
// and override -sizeThatFits, or just wrap your view in a "generic" UIView if you do not want it to be auto-sized.
@property (nonatomic, retain) UIView *titleView, *subtitleView;

// Custom "content" view that can be any width/height. If this is set, title/subtitle/titleView/subtitleView are all ignored.
/// if the @c UIView you're constraining to has portions that are overlapped by nav bar, tab bar, etc. you'll need to tell us those insets.
@property (nonatomic, assign) UIEdgeInsets constrainedInsets;
/// default is @c SMCalloutMaskedBackgroundView, or @c SMCalloutDrawnBackgroundView when using @c SMClassicCalloutView
@property (nonatomic, strong) SMCalloutBackgroundView *backgroundView;

/**
@brief Custom title view.
@disucssion Keep in mind that @c SMCalloutView calls @c -sizeThatFits on titleView/subtitleView if defined, so your view
may be resized as a result of that (especially if you're using @c UILabel/UITextField). You may want to subclass and override @c -sizeThatFits, or just wrap your view in a "generic" @c UIView if you do not want it to be auto-sized.
@warning If this is set, the respective @c title property will be ignored.
*/
@property (nonatomic, strong, nullable) UIView *titleView;

/**
@brief Custom subtitle view.
@discussion Keep in mind that @c SMCalloutView calls @c -sizeThatFits on subtitleView if defined, so your view
may be resized as a result of that (especially if you're using @c UILabel/UITextField). You may want to subclass and override @c -sizeThatFits, or just wrap your view in a "generic" @c UIView if you do not want it to be auto-sized.
@warning If this is set, the respective @c subtitle property will be ignored.
*/
@property (nonatomic, strong, nullable) UIView *subtitleView;

/// Custom "content" view that can be any width/height. If this is set, title/subtitle/titleView/subtitleView are all ignored.
@property (nonatomic, retain) UIView *contentView;

// Custom content view margin
/// Custom content view margin
@property (nonatomic, assign) UIEdgeInsets contentViewInset;

// calloutOffset is the offset in screen points from the top-middle of the target view, where the anchor of the callout should be shown.
/// calloutOffset is the offset in screen points from the top-middle of the target view, where the anchor of the callout should be shown.
@property (nonatomic, assign) CGPoint calloutOffset;

@property (nonatomic, assign) SMCalloutAnimation presentAnimation, dismissAnimation; // default SMCalloutAnimationBounce, SMCalloutAnimationFade respectively

/// default SMCalloutAnimationBounce, SMCalloutAnimationFade respectively
@property (nonatomic, assign) SMCalloutAnimation presentAnimation, dismissAnimation;

// Returns a new instance of SMCalloutView if running on iOS 7 or better, otherwise a new instance of SMClassicCalloutView if available.
/// Returns a new instance of SMCalloutView if running on iOS 7 or better, otherwise a new instance of SMClassicCalloutView if available.
+ (SMCalloutView *)platformCalloutView;

// Presents a callout view by adding it to "inView" and pointing at the given rect of inView's bounds.
// Constrains the callout to the bounds of the given view. Optionally scrolls the given rect into view (plus margins)
// if -delegate is set and responds to -delayForRepositionWithSize.
/**
@brief Presents a callout view by adding it to "inView" and pointing at the given rect of inView's bounds.
@discussion Constrains the callout to the bounds of the given view. Optionally scrolls the given rect into view (plus margins)
if @c -delegate is set and responds to @c -delayForRepositionWithSize.
@param rect @c CGRect to present the view from
@param view view to 'constrain' the @c constrainedView to
@param constrainedView @c UIView to be constrainted in @c view
@param animated @c BOOL if presentation should be animated
*/
- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated;

// Same as the view-based presentation, but inserts the callout into a CALayer hierarchy instead. Be aware that you'll have to direct
// your own touches to any accessory views, since CALayer doesn't relay touch events.
/**
@brief Present a callout layer in the `layer` and pointing at the given rect of the `layer` bounds
@discussion Same as the view-based presentation, but inserts the callout into a CALayer hierarchy instead.
@note Be aware that you'll have to direct your own touches to any accessory views, since CALayer doesn't relay touch events.
@param rect @c CGRect to present the view from
@param layer layer to 'constrain' the @c constrainedLayer to
@param constrainedLayer @c CALayer to be constrained in @c layer
@param animated @c BOOL if presentation should be animated
*/
- (void)presentCalloutFromRect:(CGRect)rect inLayer:(CALayer *)layer constrainedToLayer:(CALayer *)constrainedLayer animated:(BOOL)animated;

/**
Dismiss the callout view
@param animated @c BOOL if dismissal should be animated
*/
- (void)dismissCalloutAnimated:(BOOL)animated;

// For subclassers. You can override this method to provide your own custom animation for presenting/dismissing the callout.
/// For subclassers. You can override this method to provide your own custom animation for presenting/dismissing the callout.
- (CAAnimation *)animationWithType:(SMCalloutAnimation)type presenting:(BOOL)presenting;

@end
Expand All @@ -86,17 +137,22 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView;
// Background view - default draws the iOS 7 system background style (translucent white with rounded arrow).
//

// Abstract base class
/// Abstract base class
@interface SMCalloutBackgroundView : UIView
@property (nonatomic, assign) CGPoint arrowPoint; // indicates where the tip of the arrow should be drawn, as a pixel offset
@property (nonatomic, assign) BOOL highlighted; // will be set by the callout when the callout is in a highlighted state
@property (nonatomic, assign) CALayer *contentMask; // returns an optional layer whose contents should mask the callout view's contents (not honored by SMClassicCalloutView)
@property (nonatomic, assign) CGFloat anchorHeight; // height of the callout "arrow"
@property (nonatomic, assign) CGFloat anchorMargin; // the smallest possible distance from the edge of our control to the "tip" of the anchor, from either left or right
/// indicates where the tip of the arrow should be drawn, as a pixel offset
@property (nonatomic, assign) CGPoint arrowPoint;
/// will be set by the callout when the callout is in a highlighted state
@property (nonatomic, assign) BOOL highlighted;
/// returns an optional layer whose contents should mask the callout view's contents (not honored by @c SMClassicCalloutView )
@property (nonatomic, assign) CALayer *contentMask;
/// height of the callout "arrow"
@property (nonatomic, assign) CGFloat anchorHeight;
/// the smallest possible distance from the edge of our control to the "tip" of the anchor, from either left or right
@property (nonatomic, assign) CGFloat anchorMargin;
@end

// Default for iOS 7, this reproduces the "masked" behavior of the iOS 7-style callout view.
// Accessories are masked by the shape of the callout (including the arrow itself).
/// Default for iOS 7, this reproduces the "masked" behavior of the iOS 7-style callout view.
/// Accessories are masked by the shape of the callout (including the arrow itself).
@interface SMCalloutMaskedBackgroundView : SMCalloutBackgroundView
@end

Expand All @@ -107,32 +163,38 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView;
@protocol SMCalloutViewDelegate <NSObject>
@optional

// Controls whether the callout "highlights" when pressed. default YES. You must also respond to `-calloutViewClicked` below.
// Not honored by SMClassicCalloutView.
/// Controls whether the callout "highlights" when pressed. default YES. You must also respond to @c -calloutViewClicked below.
/// Not honored by @c SMClassicCalloutView.
- (BOOL)calloutViewShouldHighlight:(SMCalloutView *)calloutView;

// Called when the callout view is clicked. Not honored by SMClassicCalloutView.
/// Called when the callout view is clicked. Not honored by @c SMClassicCalloutView.
- (void)calloutViewClicked:(SMCalloutView *)calloutView;

// Called when the callout view detects that it will be outside the constrained view when it appears,
// or if the target rect was already outside the constrained view. You can implement this selector to
// respond to this situation by repositioning your content first in order to make everything visible. The
// CGSize passed is the calculated offset necessary to make everything visible (plus a nice margin).
// It expects you to return the amount of time you need to reposition things so the popup can be delayed.
// Typically you would return kSMCalloutViewRepositionDelayForUIScrollView if you're repositioning by
// calling [UIScrollView setContentOffset:animated:].
/**
Called when the callout view detects that it will be outside the constrained view when it appears,
or if the target rect was already outside the constrained view. You can implement this selector
to respond to this situation by repositioning your content first in order to make everything visible.
The @c CGSize passed is the calculated offset necessary to make everything visible (plus a nice margin).
It expects you to return the amount of time you need to reposition things so the popup can be delayed.
Typically you would return @c kSMCalloutViewRepositionDelayForUIScrollView if you're repositioning by calling @c [UIScrollView @c setContentOffset:animated:].
@param calloutView the @c SMCalloutView to reposition
@param offset caluclated offset necessary to make everything visible
@returns @c NSTimeInterval to delay the repositioning
*/
- (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset;

// Called before the callout view appears on screen, or before the appearance animation will start.
- (void)calloutViewWillAppear:(SMCalloutView*)calloutView;
/// Called before the callout view appears on screen, or before the appearance animation will start.
- (void)calloutViewWillAppear:(SMCalloutView *)calloutView;

// Called after the callout view appears on screen, or after the appearance animation is complete.
/// Called after the callout view appears on screen, or after the appearance animation is complete.
- (void)calloutViewDidAppear:(SMCalloutView *)calloutView;

// Called before the callout view is removed from the screen, or before the disappearance animation is complete.
- (void)calloutViewWillDisappear:(SMCalloutView*)calloutView;
/// Called before the callout view is removed from the screen, or before the disappearance animation is complete.
- (void)calloutViewWillDisappear:(SMCalloutView *)calloutView;

// Called after the callout view is removed from the screen, or after the disappearance animation is complete.
/// Called after the callout view is removed from the screen, or after the disappearance animation is complete.
- (void)calloutViewDidDisappear:(SMCalloutView *)calloutView;

NS_ASSUME_NONNULL_END
@end

0 comments on commit 60cad9e

Please sign in to comment.