0

我正在尝试使用以下代码收听互联网状态变化。这适用于可可应用程序,但在守护程序应用程序中,networkChangeHappend方法永远不会被调用。我需要为守护程序应用程序做任何不同的事情吗?或者有没有其他方法可以在守护程序应用程序中监听互联网状态变化?

主文件

#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#import "ViewController.h"

int main(int argc, const char * argv[])
{
    
    [NSThread detachNewThreadWithBlock:^{
        [[ViewController sharedInstance] startOperation];
    }];

    [[NSRunLoop currentRunLoop] run];
    
    return 0;
}

视图控制器.h

#import <Foundation/Foundation.h>

@interface ViewController : NSObject

+ (instancetype _Nonnull )sharedInstance;
- (BOOL)startOperation;

@end

视图控制器.m

#import "ViewController.h"
#import <SystemConfiguration/SystemConfiguration.h>
#include <arpa/inet.h>

@implementation ViewController

+ (instancetype)sharedInstance
{
    static ViewController *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[ViewController alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self registerNetworkChangeCallback];
    }
    return self;
}

//MARK: -
- (BOOL)startOperation {
   //some stuff..
}

-(void)registerNetworkChangeCallback
{
    
    struct sockaddr_in zeroAddress;
    
    zeroAddress.sin_addr.s_addr = inet_addr("64.14.192.121");
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;
    
    
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    
    void *info = (__bridge void *)(self);
    SCNetworkReachabilitySetCallback ((SCNetworkReachabilityRef)defaultRouteReachability,(SCNetworkReachabilityCallBack)networkChangeHappend,info);

    SCNetworkReachabilityScheduleWithRunLoop (
                                              defaultRouteReachability,
                                              CFRunLoopGetCurrent(),
                                              kCFRunLoopDefaultMode
                                              );
    
    [Logger logString:@"registerNetworkChangeCallback"];
    
}


static void networkChangeHappend(
                                 SCNetworkReachabilityRef target,
                                 SCNetworkReachabilityFlags flags,
                                 void *info
                                 )
{
    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;

    ViewController *viewController = (__bridge ViewController *)info;
    (isReachable && !needsConnection) ? [viewController connected] : [viewController disconnected];
}

-(void)connected {
    [Logger logString:@"Network connected"];
}

-(void)disconnected {
    [Logger logString:@"Network disconnected"];
}

@end
4

1 回答 1

0

您可以使用您的 *info 指针为您的回调提供一种访问您放置回调的对象的方法。

void *info = (__bridge void *)(self);
SCNetworkReachabilitySetCallback ((SCNetworkReachabilityRef)defaultRouteReachability,(SCNetworkReachabilityCallBack)networkChangeHappend,info);

并在您的回调中"self"再次访问。

....
YourClass *yourclass = (__bridge YourClass *)info;
(isReachable && !needsConnection) ? [yourclass connected] : [yourclass disconnected];

在哪里-(void)connected{}并且-(void)disconnected{}可能是 YourControllerClass 的方法

于 2020-07-17T19:53:54.453 回答