7
7
//
8
8
9
9
#import " RootViewController.h"
10
+ #import " RWebViewController.h"
10
11
11
- @interface RootViewController ()
12
+ NSString * const kWebAppStartLink = @" http://v2ex.com/" ;
13
+ NSString * const kWebAppHost = @" v2ex.com" ;
14
+ NSUInteger const kWebAppMaxFailRefreshCount = 3 ;
15
+
16
+ @interface RootViewController () <UIWebViewDelegate, UIAlertViewDelegate>
17
+
18
+ @property (nonatomic , strong ) NSURL *startURL;
19
+ @property (nonatomic , strong ) NSString *webAppHost;
20
+ @property (nonatomic , strong ) NSArray *otherInternalHosts;
21
+ @property (nonatomic , strong ) NSArray *blockedHosts;
22
+
23
+ @property (nonatomic , assign ) BOOL shouldCheckAuthenticity;
24
+ @property (nonatomic , strong ) NSString *authenticityCheckQueryJavaScript;
25
+ @property (nonatomic , strong ) NSString *authenticityCheckResult;
26
+
27
+ @property (nonatomic , assign ) NSUInteger currentFailRefreshCount;
28
+ @property (nonatomic , assign ) NSUInteger maxFailRefreshCount;
29
+ @property (nonatomic , weak ) UIAlertView *failLoadAlertView;
30
+
31
+ @property (nonatomic , strong ) UIWebView *webView;
32
+
33
+ - (void )showFailLoadWarning ;
34
+
35
+ - (void )loadStartPage ;
36
+ - (void )refresh ;
37
+ - (void )failRefresh ;
38
+
39
+ - (void )configure ;
12
40
13
41
@end
14
42
15
43
@implementation RootViewController
16
44
45
+ #pragma mark - View control
46
+
47
+ - (void )showFailLoadWarning
48
+ {
49
+ UIAlertView *alertView = [[UIAlertView alloc ] initWithTitle: NSLocalizedString(@" Error" , nil )
50
+ message: NSLocalizedString(@" An error occurred on loading." , nil )
51
+ delegate: self
52
+ cancelButtonTitle: NSLocalizedString(@" Quit" , nil )
53
+ otherButtonTitles: NSLocalizedString(@" Retry" , nil ), nil ];
54
+ alertView.delegate = self;
55
+ self.failLoadAlertView = alertView;
56
+ [alertView show ];
57
+ }
58
+
59
+ #pragma mark - Web view control
60
+
61
+ - (void )loadStartPage
62
+ {
63
+ NSURLRequest *request = [NSURLRequest requestWithURL: self .startURL];
64
+ [self .webView loadRequest: request];
65
+ }
66
+
67
+ - (void )refresh
68
+ {
69
+ [self .webView reload ];
70
+ }
71
+
72
+ - (void )failRefresh
73
+ {
74
+ if (self.currentFailRefreshCount ) {
75
+ [self refresh ];
76
+ self.currentFailRefreshCount --;
77
+ } else {
78
+ [self showFailLoadWarning ];
79
+ }
80
+ }
81
+
82
+ - (void )resetFailRefreshCount
83
+ {
84
+ self.currentFailRefreshCount = self.maxFailRefreshCount ;
85
+ }
86
+
87
+ #pragma mark - Life cycle
88
+
89
+ - (void )configure
90
+ {
91
+ // Init start URL.
92
+
93
+ self.startURL = [NSURL URLWithString: kWebAppStartLink ];
94
+
95
+ // Set web app host.
96
+
97
+ self.webAppHost = kWebAppHost ;
98
+
99
+ // Set other internal hosts.
100
+
101
+ self.otherInternalHosts = @[
102
+ @" about:blank" ,
103
+ @" googleads.g.doubleclick.net"
104
+ ];
105
+
106
+ // Set blocked hosts.
107
+
108
+ self.blockedHosts = @[
109
+ ];
110
+
111
+ // Set max fail refresh count.
112
+
113
+ self.maxFailRefreshCount = kWebAppMaxFailRefreshCount ;
114
+ [self resetFailRefreshCount ];
115
+ }
116
+
17
117
- (id )initWithNibName : (NSString *)nibNameOrNil bundle : (NSBundle *)nibBundleOrNil
18
118
{
19
119
self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil];
@@ -26,7 +126,24 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
26
126
- (void )viewDidLoad
27
127
{
28
128
[super viewDidLoad ];
29
- // Do any additional setup after loading the view.
129
+
130
+ [self configure ];
131
+
132
+ // Init & add web view.
133
+
134
+ self.webView = [[UIWebView alloc ] initWithFrame: self .view.bounds];
135
+ self.webView .delegate = self;
136
+ self.webView .scalesPageToFit = YES ;
137
+ [self .view addSubview: self .webView];
138
+ }
139
+
140
+ - (void )viewDidAppear : (BOOL )animated
141
+ {
142
+ [super viewDidAppear: animated];
143
+
144
+ if (!self.webView .request ) {
145
+ [self loadStartPage ];
146
+ }
30
147
}
31
148
32
149
- (void )didReceiveMemoryWarning
@@ -35,4 +152,103 @@ - (void)didReceiveMemoryWarning
35
152
// Dispose of any resources that can be recreated.
36
153
}
37
154
155
+ #pragma mark - Web view delegate
156
+
157
+ - (BOOL )webView : (UIWebView *)webView shouldStartLoadWithRequest : (NSURLRequest *)request navigationType : (UIWebViewNavigationType)navigationType
158
+ {
159
+ if (webView == self.webView ) {
160
+ NSString *host = request.URL .host ;
161
+
162
+ // Determine if the URL is blocked.
163
+
164
+ __block BOOL isBlocked = NO ;
165
+ [self .blockedHosts enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
166
+ NSString *blockedHost = obj;
167
+ if (NSMaxRange ([host rangeOfString: blockedHost options: (NSCaseInsensitiveSearch | NSBackwardsSearch)]) == host.length ) {
168
+ isBlocked = YES ;
169
+ *stop = YES ;
170
+ }
171
+ }];
172
+
173
+ // Determine if the URL is external.
174
+
175
+ __block BOOL isExternal = NO ;
176
+ if (!isBlocked) {
177
+ if (NSMaxRange ([host rangeOfString: self .webAppHost options: (NSCaseInsensitiveSearch | NSBackwardsSearch)]) != host.length ) {
178
+ isExternal = YES ;
179
+ [self .otherInternalHosts enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
180
+ NSString *internalHost = obj;
181
+ if (NSMaxRange ([host rangeOfString: internalHost options: (NSCaseInsensitiveSearch | NSBackwardsSearch)]) == host.length ) {
182
+ isExternal = NO ;
183
+ *stop = YES ;
184
+ }
185
+ }];
186
+ }
187
+ }
188
+
189
+ // Open in external web view controller if the URL is external.
190
+
191
+ if (isExternal) {
192
+ RWebViewController *externalWebViewController = [[RWebViewController alloc ] init ];
193
+ externalWebViewController.startURL = request.URL ;
194
+ UINavigationController *navigationController = [[UINavigationController alloc ] initWithRootViewController: externalWebViewController];
195
+ [self presentViewController: navigationController animated: YES completion: nil ];
196
+ }
197
+
198
+ return !(isExternal | isBlocked);
199
+ }
200
+ return YES ;
201
+ }
202
+
203
+ - (void )webViewDidFinishLoad : (UIWebView *)webView
204
+ {
205
+ if (webView == self.webView ) {
206
+ BOOL success = NO ;
207
+
208
+ // Check authenticity.
209
+
210
+ if (self.shouldCheckAuthenticity ) {
211
+ if ([[self .webView stringByEvaluatingJavaScriptFromString: self .authenticityCheckQueryJavaScript] isEqualToString: self .authenticityCheckResult]) {
212
+ success = YES ;
213
+ }
214
+ } else {
215
+ success = YES ;
216
+ }
217
+
218
+ // Refresh on fail.
219
+
220
+ if (success) {
221
+ [self resetFailRefreshCount ];
222
+ } else {
223
+ [self failRefresh ];
224
+ }
225
+ }
226
+ }
227
+
228
+ - (void )webView : (UIWebView *)webView didFailLoadWithError : (NSError *)error
229
+ {
230
+ if (webView == self.webView ) {
231
+ [self failRefresh ];
232
+ }
233
+ }
234
+
235
+ #pragma mark - Alert view delegate
236
+
237
+ - (void )alertView : (UIAlertView *)alertView didDismissWithButtonIndex : (NSInteger )buttonIndex
238
+ {
239
+ if (alertView == self.failLoadAlertView ) {
240
+ switch (buttonIndex) {
241
+ case 0 : // Quit
242
+ abort ();
243
+ break ;
244
+ case 1 : // Retry
245
+ [self resetFailRefreshCount ];
246
+ [self failRefresh ];
247
+ break ;
248
+ default :
249
+ break ;
250
+ }
251
+ }
252
+ }
253
+
38
254
@end
0 commit comments