diff --git a/Libraries/Network/RCTNetInfo.m b/Libraries/Network/RCTNetInfo.m index e41079b89699cd..afc3d1db33334c 100644 --- a/Libraries/Network/RCTNetInfo.m +++ b/Libraries/Network/RCTNetInfo.m @@ -41,6 +41,7 @@ @implementation RCTNetInfo NSString *_effectiveConnectionType; NSString *_statusDeprecated; NSString *_host; + BOOL _isObserving; } RCT_EXPORT_MODULE() @@ -48,6 +49,61 @@ @implementation RCTNetInfo static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) { RCTNetInfo *self = (__bridge id)info; + if ([self setReachabilityStatus:flags] && self->_isObserving) { + [self sendEventWithName:@"networkStatusDidChange" body:@{@"connectionType": self->_connectionType, + @"effectiveConnectionType": self->_effectiveConnectionType, + @"network_info": self->_statusDeprecated}]; + } +} + +#pragma mark - Lifecycle + +- (instancetype)initWithHost:(NSString *)host +{ + RCTAssertParam(host); + RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme."); + + if ((self = [self init])) { + _host = [host copy]; + } + return self; +} + +- (NSArray *)supportedEvents +{ + return @[@"networkStatusDidChange"]; +} + +- (void)startObserving +{ + _isObserving = YES; + _connectionType = RCTConnectionTypeUnknown; + _effectiveConnectionType = RCTEffectiveConnectionTypeUnknown; + _statusDeprecated = RCTReachabilityStateUnknown; + _reachability = [self getReachabilityRef]; +} + +- (void)stopObserving +{ + _isObserving = NO; + if (_reachability) { + SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); + CFRelease(_reachability); + } +} + +- (SCNetworkReachabilityRef)getReachabilityRef +{ + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, _host.UTF8String ?: "apple.com"); + SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL }; + SCNetworkReachabilitySetCallback(reachability, RCTReachabilityCallback, &context); + SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); + + return reachability; +} + +- (BOOL)setReachabilityStatus:(SCNetworkReachabilityFlags)flags +{ NSString *connectionType = RCTConnectionTypeUnknown; NSString *effectiveConnectionType = RCTEffectiveConnectionTypeUnknown; NSString *status = RCTReachabilityStateUnknown; @@ -96,47 +152,10 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC self->_connectionType = connectionType; self->_effectiveConnectionType = effectiveConnectionType; self->_statusDeprecated = status; - [self sendEventWithName:@"networkStatusDidChange" body:@{@"connectionType": connectionType, - @"effectiveConnectionType": effectiveConnectionType, - @"network_info": status}]; - } -} - -#pragma mark - Lifecycle - -- (instancetype)initWithHost:(NSString *)host -{ - RCTAssertParam(host); - RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme."); - - if ((self = [self init])) { - _host = [host copy]; - } - return self; -} - -- (NSArray *)supportedEvents -{ - return @[@"networkStatusDidChange"]; -} - -- (void)startObserving -{ - _connectionType = RCTConnectionTypeUnknown; - _effectiveConnectionType = RCTEffectiveConnectionTypeUnknown; - _statusDeprecated = RCTReachabilityStateUnknown; - _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, _host.UTF8String ?: "apple.com"); - SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL }; - SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context); - SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); -} - -- (void)stopObserving -{ - if (_reachability) { - SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); - CFRelease(_reachability); + return YES; } + + return NO; } #pragma mark - Public API @@ -144,6 +163,8 @@ - (void)stopObserving RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject) { + SCNetworkReachabilityRef reachability = [self getReachabilityRef]; + CFRelease(reachability); resolve(@{@"connectionType": _connectionType ?: RCTConnectionTypeUnknown, @"effectiveConnectionType": _effectiveConnectionType ?: RCTEffectiveConnectionTypeUnknown, @"network_info": _statusDeprecated ?: RCTReachabilityStateUnknown});