@@ -35,6 +35,12 @@ @interface RealReachability()
35
35
@property (nonatomic ,strong ) NSArray *typeStrings2G;
36
36
37
37
@property (nonatomic , assign ) ReachabilityStatus previousStatus;
38
+
39
+ // / main helper
40
+ @property (nonatomic , strong ) PingHelper *pingHelper;
41
+
42
+ // / for double check
43
+ @property (nonatomic , strong ) PingHelper *pingChecker;
38
44
@end
39
45
40
46
@implementation RealReachability
@@ -63,13 +69,17 @@ - (id)init
63
69
_typeStrings4G = @[CTRadioAccessTechnologyLTE];
64
70
65
71
_hostForPing = kDefaultHost ;
72
+ _hostForCheck = kDefaultHost ;
66
73
_autoCheckInterval = kDefaultCheckInterval ;
67
74
_pingTimeout = kDefaultPingTimeout ;
68
75
69
76
[[NSNotificationCenter defaultCenter ] addObserver: self
70
77
selector: @selector (appBecomeActive )
71
78
name: UIApplicationDidBecomeActiveNotification
72
79
object: nil ];
80
+
81
+ _pingHelper = [[PingHelper alloc ] init ];
82
+ _pingChecker = [[PingHelper alloc ] init ];
73
83
}
74
84
return self;
75
85
}
@@ -124,16 +134,20 @@ - (void)startNotifier
124
134
125
135
[GLocalConnection startNotifier ];
126
136
[[NSNotificationCenter defaultCenter ] addObserver: self
127
- selector: @selector (localConnectionChanged : )
137
+ selector: @selector (localConnectionHandler : )
128
138
name: kLocalConnectionChangedNotification
129
139
object: nil ];
130
140
[[NSNotificationCenter defaultCenter ] addObserver: self
131
- selector: @selector (localConnectionInitialized : )
141
+ selector: @selector (localConnectionHandler : )
132
142
name: kLocalConnectionInitializedNotification
133
143
object: nil ];
134
144
135
- GPingHelper.host = _hostForPing;
136
- GPingHelper.timeout = self.pingTimeout ;
145
+ self.pingHelper .host = _hostForPing;
146
+ self.pingHelper .timeout = self.pingTimeout ;
147
+
148
+ self.pingChecker .host = _hostForCheck;
149
+ self.pingChecker .timeout = self.pingTimeout ;
150
+
137
151
[self autoCheckReachability ];
138
152
}
139
153
@@ -168,56 +182,31 @@ - (void)reachabilityWithBlock:(void (^)(ReachabilityStatus status))asyncHandler
168
182
return ;
169
183
}
170
184
171
- ReachabilityStatus status = [self currentReachabilityStatus ];
172
185
__weak __typeof (self)weakSelf = self;
173
- [GPingHelper pingWithBlock: ^(BOOL isSuccess)
186
+ [self .pingHelper pingWithBlock: ^(BOOL isSuccess)
174
187
{
175
188
__strong __typeof (weakSelf)strongSelf = weakSelf;
176
- NSDictionary *inputDic = @{kEventKeyID :@(RREventPingCallback), kEventKeyParam :@(isSuccess)};
177
- NSInteger rtn = [strongSelf.engine receiveInput: inputDic];
178
- if (rtn == 0 ) // state changed & state available, post notification.
189
+ if (isSuccess)
179
190
{
180
- if ([strongSelf.engine isCurrentStateAvailable ])
191
+ // no need to post the notification because the status is not changing.
192
+ NSDictionary *inputDic = @{kEventKeyID :@(RREventPingCallback), kEventKeyParam :@(YES )};
193
+ [strongSelf.engine receiveInput: inputDic];
194
+
195
+ if (asyncHandler != nil )
181
196
{
182
- strongSelf.previousStatus = status;
183
- // this makes sure the change notification happens on the MAIN THREAD
184
- __weak __typeof (strongSelf)deepWeakSelf = strongSelf;
185
- dispatch_async (dispatch_get_main_queue (), ^{
186
- __strong __typeof (deepWeakSelf)deepStrongSelf = deepWeakSelf;
187
- [[NSNotificationCenter defaultCenter ] postNotificationName: kRealReachabilityChangedNotification
188
- object: deepStrongSelf];
189
- });
197
+ ReachabilityStatus currentStatus = [strongSelf currentReachabilityStatus ];
198
+ asyncHandler (currentStatus);
190
199
}
191
200
}
192
-
193
- if (asyncHandler != nil )
201
+ else
194
202
{
195
- RRStateID currentID = strongSelf.engine .currentStateID ;
196
- switch (currentID)
197
- {
198
- case RRStateUnReachable:
199
- {
200
- asyncHandler (RealStatusNotReachable);
201
- break ;
202
- }
203
- case RRStateWIFI:
204
- {
205
- asyncHandler (RealStatusViaWiFi);
206
- break ;
207
- }
208
- case RRStateWWAN:
209
- {
210
- asyncHandler (RealStatusViaWWAN);
211
- break ;
212
- }
213
-
214
- default :
215
- {
216
- NSLog (@" warning! reachState uncertain! state unmatched, treat as unreachable temporary" );
217
- asyncHandler (RealStatusNotReachable);
218
- break ;
219
- }
220
- }
203
+ // delay 1 seconds, then make a double check.
204
+ dispatch_time_t time = dispatch_time (DISPATCH_TIME_NOW, (int64_t )(1 *NSEC_PER_SEC));
205
+ __weak __typeof (self)weakSelf = self;
206
+ dispatch_after (time , dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
207
+ __strong __typeof (weakSelf)self = weakSelf;
208
+ [self makeDoubleCheck: asyncHandler];
209
+ });
221
210
}
222
211
}];
223
212
}
@@ -264,12 +253,22 @@ - (void)setHostForPing:(NSString *)hostForPing
264
253
_hostForPing = nil ;
265
254
_hostForPing = [hostForPing copy ];
266
255
267
- GPingHelper.host = _hostForPing;
256
+ self.pingHelper .host = _hostForPing;
257
+ }
258
+
259
+ - (void )setHostForCheck : (NSString *)hostForCheck
260
+ {
261
+ _hostForCheck = nil ;
262
+ _hostForCheck = [hostForCheck copy ];
263
+
264
+ self.pingChecker .host = _hostForCheck;
268
265
}
269
266
270
- - (void )setPingTimeout : (NSTimeInterval )pingTimeout {
267
+ - (void )setPingTimeout : (NSTimeInterval )pingTimeout
268
+ {
271
269
_pingTimeout = pingTimeout;
272
- GPingHelper.timeout = pingTimeout;
270
+ self.pingHelper .timeout = pingTimeout;
271
+ self.pingChecker .timeout = pingTimeout;
273
272
}
274
273
275
274
- (WWANAccessType)currentWWANtype
@@ -294,6 +293,34 @@ - (WWANAccessType)currentWWANtype
294
293
}
295
294
296
295
#pragma mark - inner methods
296
+ - (void )makeDoubleCheck : (void (^)(ReachabilityStatus status))asyncHandler
297
+ {
298
+ __weak __typeof (self)weakSelf = self;
299
+ [self .pingChecker pingWithBlock: ^(BOOL isSuccess) {
300
+ __strong __typeof (weakSelf)strongSelf = weakSelf;
301
+
302
+ NSDictionary *inputDic = @{kEventKeyID :@(RREventPingCallback), kEventKeyParam :@(isSuccess)};
303
+ [strongSelf.engine receiveInput: inputDic];
304
+
305
+ if (!isSuccess)
306
+ {
307
+ // Only fail make the change; then we post the fail notification.
308
+ __weak __typeof (strongSelf)deepWeakSelf = strongSelf;
309
+ dispatch_async (dispatch_get_main_queue (), ^{
310
+ __strong __typeof (deepWeakSelf)deepStrongSelf = deepWeakSelf;
311
+ [[NSNotificationCenter defaultCenter ] postNotificationName: kRealReachabilityChangedNotification
312
+ object: deepStrongSelf];
313
+ });
314
+ }
315
+
316
+ if (asyncHandler != nil )
317
+ {
318
+ ReachabilityStatus currentStatus = [strongSelf currentReachabilityStatus ];
319
+ asyncHandler (currentStatus);
320
+ }
321
+ }];
322
+ }
323
+
297
324
- (NSString *)paramValueFromStatus : (LocalConnectionStatus)status
298
325
{
299
326
switch (status)
@@ -368,11 +395,11 @@ - (WWANAccessType)accessTypeForString:(NSString *)accessString
368
395
}
369
396
370
397
#pragma mark - Notification observer
371
- - (void )localConnectionChanged : (NSNotification *)notification
398
+ - (void )localConnectionHandler : (NSNotification *)notification
372
399
{
373
400
LocalConnection *lc = (LocalConnection *)notification.object ;
374
401
LocalConnectionStatus lcStatus = [lc currentLocalConnectionStatus ];
375
- // NSLog(@"currentLocalConnectionStatus:%@",@(lcStatus));
402
+ // NSLog(@"currentLocalConnectionStatus:%@, receive notification:%@ ",@(lcStatus), notification.name );
376
403
ReachabilityStatus status = [self currentReachabilityStatus ];
377
404
378
405
NSDictionary *inputDic = @{kEventKeyID :@(RREventLocalConnectionCallback), kEventKeyParam :[self paramValueFromStatus: lcStatus]};
@@ -383,10 +410,14 @@ - (void)localConnectionChanged:(NSNotification *)notification
383
410
if ([self .engine isCurrentStateAvailable ])
384
411
{
385
412
self.previousStatus = status;
386
- // already in main thread.
387
- [[NSNotificationCenter defaultCenter ] postNotificationName: kRealReachabilityChangedNotification
388
- object: self ];
389
413
414
+ // already in main thread.
415
+ if ([notification.name isEqualToString: kLocalConnectionChangedNotification ])
416
+ {
417
+ [[NSNotificationCenter defaultCenter ] postNotificationName: kRealReachabilityChangedNotification
418
+ object: self ];
419
+ }
420
+
390
421
if (lcStatus != LC_UnReachable)
391
422
{
392
423
// To make sure your reachability is "Real".
@@ -396,22 +427,5 @@ - (void)localConnectionChanged:(NSNotification *)notification
396
427
}
397
428
}
398
429
399
- - (void )localConnectionInitialized : (NSNotification *)notification
400
- {
401
- LocalConnection *lc = (LocalConnection *)notification.object ;
402
- LocalConnectionStatus lcStatus = [lc currentLocalConnectionStatus ];
403
- NSLog (@" localConnectionInitializedStatus:%@ " ,@(lcStatus));
404
-
405
- NSDictionary *inputDic = @{kEventKeyID :@(RREventLocalConnectionCallback), kEventKeyParam :[self paramValueFromStatus: lcStatus]};
406
- NSInteger rtn = [self .engine receiveInput: inputDic];
407
-
408
- // Initialized state, ping once to check the reachability(if local status reachable).
409
- if ((rtn == 0 ) && [self .engine isCurrentStateAvailable ] && (lcStatus != LC_UnReachable))
410
- {
411
- // To make sure your reachability is "Real".
412
- [self reachabilityWithBlock: nil ];
413
- }
414
- }
415
-
416
430
@end
417
431
0 commit comments