-
Notifications
You must be signed in to change notification settings - Fork 21
/
PSPDFAlertView.m
162 lines (128 loc) · 5.45 KB
/
PSPDFAlertView.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//
// PSPDFAlertView.m
//
// Copyright (c) 2011-2014 PSPDFKit GmbH. All rights reserved.
//
#import "PSPDFAlertView.h"
@interface PSPDFAlertView () <UIAlertViewDelegate>
@property (nonatomic, assign, getter=isDismissing) BOOL dismissing;
@property (nonatomic, copy) NSArray *blocks;
@property (nonatomic, copy) NSArray *willDismissBlocks;
@property (nonatomic, copy) NSArray *didDismissBlocks;
@property (nonatomic, weak) id<UIAlertViewDelegate> realDelegate;
@end
@implementation PSPDFAlertView
///////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - NSObject
- (id)init {
if (self = [super init]) {
[super setDelegate:self];
}
return self;
}
- (id)initWithTitle:(NSString *)title {
return self = [self initWithTitle:title message:nil];
}
- (id)initWithTitle:(NSString *)title message:(NSString *)message {
return self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
}
- (void)dealloc {
self.delegate = nil;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p numberOfButtons:%zd title:%@>", NSStringFromClass(self.class), self, self.numberOfButtons, self.title];
}
- (void)destroy {
self.blocks = nil;
self.willDismissBlocks = nil;
self.didDismissBlocks = nil;
self.delegate = nil;
}
///////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Public
- (void)setDelegate:(id/**<UIAlertViewDelegate>*/)delegate {
[super setDelegate:delegate ? self : nil];
self.realDelegate = delegate != self ? delegate : nil;
}
- (NSInteger)setCancelButtonWithTitle:(NSString *)title block:(void (^)(NSInteger buttonIndex))block {
NSUInteger buttonIndex = [self addButtonWithTitle:title block:block];
self.cancelButtonIndex = buttonIndex;
return buttonIndex;
}
- (NSInteger)addButtonWithTitle:(NSString *)title block:(void (^)(NSInteger buttonIndex))block {
NSParameterAssert(title);
self.blocks = [[NSArray arrayWithArray:self.blocks] arrayByAddingObject:block ? [block copy] : NSNull.null];
return [self addButtonWithTitle:title];
}
- (NSInteger)addButtonWithTitle:(NSString *)title {
NSInteger buttonIndex = [super addButtonWithTitle:title];
// Ensure blocks array is equal to number of buttons.
while (self.blocks.count < self.numberOfButtons) {
self.blocks = [[NSArray arrayWithArray:self.blocks] arrayByAddingObject:NSNull.null];
}
return buttonIndex;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated {
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
// In iOS 8, this method is being called even when we dismissed based on a button action.
// It's not called on iOS 7 or earlier. We track if it's a user-initiated or programmatic
// dismissal via `isDismissing`.
if (!self.isDismissing) {
[self alertView:self clickedButtonAtIndex:buttonIndex];
}
}
- (void)addWillDismissBlock:(void (^)(NSInteger buttonIndex))willDismissBlock {
NSParameterAssert(willDismissBlock);
self.willDismissBlocks = [[NSArray arrayWithArray:self.willDismissBlocks] arrayByAddingObject:willDismissBlock];
}
- (void)addDidDismissBlock:(void (^)(NSInteger buttonIndex))didDismissBlock {
NSParameterAssert(didDismissBlock);
self.didDismissBlocks = [[NSArray arrayWithArray:self.didDismissBlocks] arrayByAddingObject:didDismissBlock];
}
- (void)_callBlocks:(NSArray *)blocks withButtonIndex:(NSInteger)buttonIndex {
for (void (^block)(NSInteger buttonIndex) in blocks) {
block(buttonIndex);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
// Run the button's block.
if (buttonIndex >= 0 && buttonIndex < self.blocks.count) {
void (^block)(NSUInteger) = self.blocks[buttonIndex];
if (![block isEqual:NSNull.null]) {
block(buttonIndex);
}
}
id<UIAlertViewDelegate> delegate = self.realDelegate;
if ([delegate respondsToSelector:_cmd]) {
[delegate alertView:alertView clickedButtonAtIndex:buttonIndex];
}
}
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
self.dismissing = YES;
[self _callBlocks:self.willDismissBlocks withButtonIndex:buttonIndex];
id<UIAlertViewDelegate> delegate = self.realDelegate;
if ([delegate respondsToSelector:_cmd]) {
[delegate alertView:alertView willDismissWithButtonIndex:buttonIndex];
}
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
[self _callBlocks:self.didDismissBlocks withButtonIndex:buttonIndex];
id<UIAlertViewDelegate> delegate = self.realDelegate;
if ([delegate respondsToSelector:_cmd]) {
[delegate alertView:alertView didDismissWithButtonIndex:buttonIndex];
}
[self destroy];
self.dismissing = NO;
}
///////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Delegate Forwarder
- (BOOL)respondsToSelector:(SEL)s {
return [super respondsToSelector:s] || [self.realDelegate respondsToSelector:s];
}
- (id)forwardingTargetForSelector:(SEL)s {
id delegate = self.realDelegate;
return [delegate respondsToSelector:s] ? delegate : [super forwardingTargetForSelector:s];
}
@end