如何检测iOS可达性中的网络信号强度 [英] How to detect Network Signal Strength in iOS Reachability

查看:172
本文介绍了如何检测iOS可达性中的网络信号强度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在iOS中创建一个新的旅行应用程序,此应用程序高度依赖于地图,并将包含两个地图。

I am creating a new Traveling Application in iOS, this application is highly dependent on Maps and will include two Maps.



  1. 当用户拥有强大的网络信号(Apple Maps)时,我的第一张地图将会正常工作。

  2. 我的第二张地图将在他们不是任何网络或真正低时使用信号(离线
    MapBox)。


为什么我在一个地方有两个不同的地图应用?我的应用程序是一个方向应用程序,所以当用户网络真的很低或没有网络时,它将转到离线地图 MapBox 。此外,Apple Maps将具有Yelp集成,而不是离线Map MapBox

Why do I have two different maps in one Application? My Application is a Direction App, so when the user has really low network or none it will go to the offline Map MapBox. Also the Apple Maps will have Yelp integration and not the offline Map MapBox.

所以我的问题:如何检测WiFi,4G Lte和3G中的网络信号。

So my Question: How can I detect the network signal in WiFi, 4G Lte, and 3G.

推荐答案

我最初的想法是下载一个文件,看看需要多长时间:

My original thought was to time the download of a file, and see how long it takes:

@interface ViewController () <NSURLSessionDelegate, NSURLSessionDataDelegate>

@property (nonatomic) CFAbsoluteTime startTime;
@property (nonatomic) CFAbsoluteTime stopTime;
@property (nonatomic) long long bytesReceived;
@property (nonatomic, copy) void (^speedTestCompletionHandler)(CGFloat megabytesPerSecond, NSError *error);

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self testDownloadSpeedWithTimout:5.0 completionHandler:^(CGFloat megabytesPerSecond, NSError *error) {
        NSLog(@"%0.1f; error = %@", megabytesPerSecond, error);
    }];
}

/// Test speed of download
///
/// Test the speed of a connection by downloading some predetermined resource. Alternatively, you could add the
/// URL of what to use for testing the connection as a parameter to this method.
///
/// @param timeout             The maximum amount of time for the request.
/// @param completionHandler   The block to be called when the request finishes (or times out).
///                            The error parameter to this closure indicates whether there was an error downloading
///                            the resource (other than timeout).
///
/// @note                      Note, the timeout parameter doesn't have to be enough to download the entire
///                            resource, but rather just sufficiently long enough to measure the speed of the download.

- (void)testDownloadSpeedWithTimout:(NSTimeInterval)timeout completionHandler:(nonnull void (^)(CGFloat megabytesPerSecond, NSError * _Nullable error))completionHandler {
    NSURL *url = [NSURL URLWithString:@"http://insert.your.site.here/yourfile"];

    self.startTime = CFAbsoluteTimeGetCurrent();
    self.stopTime = self.startTime;
    self.bytesReceived = 0;
    self.speedTestCompletionHandler = completionHandler;

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    configuration.timeoutIntervalForResource = timeout;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    [[session dataTaskWithURL:url] resume];
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    self.bytesReceived += [data length];
    self.stopTime = CFAbsoluteTimeGetCurrent();
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    CFAbsoluteTime elapsed = self.stopTime - self.startTime;
    CGFloat speed = elapsed != 0 ? self.bytesReceived / (CFAbsoluteTimeGetCurrent() - self.startTime) / 1024.0 / 1024.0 : -1;

    // treat timeout as no error (as we're testing speed, not worried about whether we got entire resource or not

    if (error == nil || ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorTimedOut)) {
        self.speedTestCompletionHandler(speed, nil);
    } else {
        self.speedTestCompletionHandler(speed, error);
    }
}

@end

注意,这会测量速度,包括启动连接的延迟。您也可以在 startTime /library/ios/documentation/Foundation/Reference/NSURLSessionDataDelegate_protocol/index.html#//apple_ref/occ/intfm/NSURLSessionDataDelegate/URLSession:dataTask:didReceiveResponse:completionHandler:\">didReceiveResponse ,如果你想要考虑初始延迟。

Note, this measures the speed including the latency of starting the connection. You could alternatively initialize startTime in didReceiveResponse, if you wanted to factor out that initial latency.

完成后,回想起来,我不要t等花时间或带宽下载的东西,有应用程序没有实际的好处。因此,作为替代方案,我可能会建议采用更实用的方法:为什么不尝试打开 MKMapView ,看看完成下载地图需要多长时间?如果失败或者花费的时间超过一定时间,请切换到离线地图。同样,这里存在相当多的可变性(不仅因为网络带宽和延迟,还因为某些地图图像似乎被缓存),因此请务必设置 kMaximumElapsedTime 足够大以处理成功连接的所有合理排列(即,在使用低值时不要过于激进)。

Having done that, in retrospect, I don't like spending time or bandwidth downloading something that has no practical benefit to the app. So, as an alternative, I might suggest a far more pragmatic approach: Why don't you just try to open a MKMapView and see how long it takes to finish downloading the map? If it fails or if it takes more than a certain amount of time, then switch to your offline map. Again, there is quite a bit of variability here (not only because network bandwidth and latency, but also because some map images appear to be cached), so make sure to set a kMaximumElapsedTime to be large enough to handle all the reasonable permutations of a successful connection (i.e., don't be too aggressive in using a low value).

为此,请确保将视图控制器设置为<$ c $的委托 C>的MKMapView 。然后你可以这样做:

To do this, just make sure to set your view controller to be the delegate of the MKMapView. And then you can do:

@interface ViewController () <MKMapViewDelegate>
@property (nonatomic, strong) NSDate *startDate;
@end

static CGFloat const kMaximumElapsedTime = 5.0;

@implementation ViewController

// insert the rest of your implementation here

#pragma mark - MKMapViewDelegate methods

- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView {
    NSDate *localStartDate = [NSDate date];
    self.startDate = localStartDate;

    double delayInSeconds = kMaximumElapsedTime;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        // Check to see if either:
        //   (a) start date property is not nil (because if it is, we 
        //       finished map download); and
        //   (b) start date property is the same as the value we set
        //       above, as it's possible this map download is done, but
        //       we're already in the process of downloading the next
        //       map.

        if (self.startDate && self.startDate == localStartDate)
        {
            [[[UIAlertView alloc] initWithTitle:nil
                                        message:[NSString stringWithFormat:@"Map timed out after %.1f", delayInSeconds]
                                       delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil] show];
        }
    });
}

- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
    self.startDate = nil;

    [[[UIAlertView alloc] initWithTitle:nil
                                message:@"Online map failed"
                               delegate:nil
                      cancelButtonTitle:@"OK"
                      otherButtonTitles:nil] show];
}

- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
    NSTimeInterval elapsed = [[NSDate date] timeIntervalSinceDate:self.startDate];
    self.startDate = nil;
    self.statusLabel.text = [NSString stringWithFormat:@"%.1f seconds", elapsed];
}

这篇关于如何检测iOS可达性中的网络信号强度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆