我可以阻止特定时刻的网络访问吗?

Riz*_*zon 2 iphone networking objective-c ios

编写iOS应用程序时,我会向用户提供阻止此应用程序的网络访问权限的选项.是否可以在代码中执行此操作?

这意味着每个调用由代码的任何部分(以及包括静态库)构成,应该在特定时刻被阻止.

Ali*_*are 7

您可以使用NSURLProtocol拦截所有网络呼叫的自定义.

这正是我在我的OHHTTPStubs库中对存根网络请求所做的事情(我的库使用私有API来模拟网络响应,但在你的情况下,如果你不需要伪造响应,你可以避免这些调用私有API并使用生产代码中的这种技术)

[编辑]由于这个答案,OHHTTPStubs已经更新,不再使用任何私有API,所以你甚至可以在生产代码中使用它.有关代码示例,请参阅本答案末尾的编辑.


@interface BlockAllRequestsProtocol : NSURLProtocol
@end

@implementation BlockAllRequestsProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    return YES; // Intercept all outgoing requests, whatever the URL scheme
    // (you can adapt this at your convenience of course if you need to block only specific requests)
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; }
- (NSCachedURLResponse *)cachedResponse { return nil; }

- (void)startLoading
{
    // For every request, emit "didFailWithError:" with an NSError to reflect the network blocking state
    id<NSURLProtocolClient> client = [self client];
    NSError* error = [NSError errorWithDomain:NSURLErrorDomain
                                         code:kCFURLErrorNotConnectedToInternet // = -1009 = error code when network is down
                                     userInfo:@{ NSLocalizedDescriptionKey:@"All network requests are blocked by the application"}];
    [client URLProtocol:self didFailWithError:error];
}
- (void)stopLoading { }

@end
Run Code Online (Sandbox Code Playgroud)

然后安装此协议并阻止所有网络请求:

[NSURLProtocol registerClass:[BlockAllRequestsProtocol class]];
Run Code Online (Sandbox Code Playgroud)

并在以后卸载它并让您的网络请求到达现实世界:

[NSURLProtocol unregisterClass:[BlockAllRequestsProtocol class]];
Run Code Online (Sandbox Code Playgroud)

[编辑]自从我的回答,我已经更新了我的库,不再使用任何私有API.所以任何人都可以OHHTTPStubs直接使用,即使是你需要的用途,如下所示:

[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest* request) {
    return YES; // In your case, you want to prevent ALL requests to hit the real world
} withStubResponse:^OHHTTPStubsResponse*(NSURLRequest* request) {
    NSError* noNetworkError = [NSError errorWithDomain:NSURLErrorDomain
                    code:kCFURLErrorNotConnectedToInternet userInfo:nil];
    return [OHHTTPStubsResponse responseWithError:noNetworkError];
}];
Run Code Online (Sandbox Code Playgroud)