如何在iOS Reachability中检测网络信号强度

2023-12-06

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

  1. 当用户有较强的网络信号时,我的第一个地图将起作用(Apple 地图)。
  2. 我的第二张地图将在没有任何网络或信号非常低时使用(离线 地图框)。

为什么一个应用程序中有两张不同的地图?我的应用程序是一个方向应用程序,因此当用户网络非常低或没有网络时,它将转到离线地图MapBox。此外,Apple 地图将集成 Yelp,而不是离线地图MapBox.

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


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

@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 in didReceiveResponse,如果您想排除初始延迟。


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

为此,只需确保将视图控制器设置为delegate of the MKMapView。然后你可以这样做:

@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];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在iOS Reachability中检测网络信号强度 的相关文章

随机推荐

  • Amazon SES 从实例配置文件元数据服务器检索凭证时出错。 (客户端错误:404)

    在让 AWS SES 正常工作时遇到一些问题 我想从我的网站向用户发送电子邮件 看起来凭证没有经过验证 但是我使用了从 IAM 生成的正确凭证 我还尝试了服务器根密钥 但它给了我同样的错误 我已经没有关于如何进一步解决 调试的想法 因此任何
  • Spring Batch 和 Cloudera hadoop 版本不兼容

    我正在尝试 Spring Batch 字数统计程序并遇到这样的版本问题 ERROR org springframework batch core step AbstractStep
  • 函数生成;更改其他功能的默认值(部分)

    我需要一个函数生成器 它接受另一个函数和该函数的任何参数并设置新的默认值 我以为 hadley 的pryr partial这就是那个神奇的功能 它完全符合我的要求 只是您无法更改新的默认值 所以在这里我可以改变sep在我的新paste函数
  • 线程安全数据集

    我想让 DataTable DataSet 的更新操作成为线程安全的 有大约 20 个线程 每个线程使用以下命令更新大约 40 行全局 DataTableRows Find pk 数据表的方法 每个线程将更新 DataTable 的不同行
  • 如何提高 boost Interval_map 查找的性能

    我正在使用一个boost icl interval map将字节范围映射到一组字符串 该地图是从 已排序的 磁盘文件加载的 然后我使用下面的代码进行查找 问题是查找速度非常慢 在我的测试中 我在地图中插入了 66425 个范围 我分析了代码
  • 如何在多索引 Pandas 数据框中按组更新前 N 行的值?

    我正在尝试更新多索引数据框中的前 N 行 但在寻找解决方案时遇到了一些麻烦 所以我想为它创建一个帖子 示例代码如下 Imports import numpy as np import pandas as pd Set Up Data Fra
  • AWS Cloudformation 中 UserData 中的参考参数值

    我在参数部分有这个 Parameters PlatformSelect Description Cockpit platform Select Type String Default qa 1 AllowedValues qa 1 qa 2
  • 使用 javascript 播放以 Base64 编码的 .wav 声音文件

    我能够通过以下方式用 javascript 播放声音 var snd new Audio sound wav snd play 这会播放所需的声音 但有时加载速度很慢 甚至可能根本不加载 所以我用 Base 64 对声音进行编码并尝试以这种
  • 找不到添加到 xcode 7 的自定义字体的名称

    我在获取自定义字体的名称时遇到问题 我将字体添加到我的项目中 并选中 如果需要则复制 选项 我将字体名称添加到应用程序提供的 info plist 标签 Fonts 中 我将字体添加到复制捆绑资源中 该字体出现在自定义选项卡下的情节提要中
  • FileStore 4.2.1 分步示例

    我想要上传 csv 文件 验证它 然后上传到现有模型中 然而 我正在使用 ATK4 2 1 发现 google 搜索到的示例代码要么缺少一些步骤 要么与版本 4 2 1 不相关 为此 在我的第一步中 我尝试混合和匹配代码 试图让文件存储启动
  • mod_rewrite:删除尾部斜杠(只有一个!)

    我使用 mod rewrite htaccess 来获得漂亮的 URL 我使用此条件 规则来消除尾随斜杠 或者更确切地说 通过 301 重定向重写到非尾随斜杠 URL 我这样做是为了避免重复内容 因为我喜欢没有尾随斜杠的 URL更好的 Re
  • 为什么 Canvas API 在循环中使用错误的颜色填充这些路径的部分内容?

    我创建了一个JSFiddle所有代码均处于活动状态并正在运行 相关JS在这里 const canvas document getElementById base const ctx canvas getContext 2d const cW
  • Lambda 未加载加密共享库

    我正在使用 AWS Lambda 中的加密库 我已在 Amazon Linux VM 中使用 pip 编译了该包 我已将包作为图层上传 不管怎样 每次我调用库时 我都会遇到一个根本不具有描述性的错误 Unable to import mod
  • 如何在Python PyQt5中将变量分配给工作线程?

    我使用pyqt5设计了一个GUI程序 我有一个主线程和一个工作线程 当 GUI 启动时 我会从用户那里获得一些输入 例如年龄 姓名 并且我想在工作人员中处理这些输入 例如我如何发送我使用的输入self ui firstname text 给
  • Silverlight:从 silverlight 控件创建图像

    是否可以从 silverlight 控件生成图像 以便该控件将自身及其内容渲染到图像中 以便我可以对图像进行相同的像素操作 在 Silverlight 2 中无法实现此目的 我见过人们通过将 XAML 发布到服务器来解决此限制 该服务器将使
  • 如何在 C# 中反序列化包含可变数量对象的 json 对象并将它们作为键值集合?

    如何反序列化以下 JSON 对象并获取 Dictionary 的集合 其中键 字符串 应该是方法名称 对象是 C 中的详细信息 methods password 2 title Password CustomerID type passwo
  • 使用 iText 将标题添加到 pdf

    如何使用 iText 5 0 5 将页眉添加到每个 PDF 页面 这涵盖在 iText 实践 第二版第 5 章 代码示例均可在线免费获取 尤其电影国家1 and 电影史2两者都处理page页眉和页脚 归结为使用PdfPageEvent实现
  • 拼写错误:找不到合适的拼写检查程序

    虽然功能aspell标配utils包 它似乎不适合我 我不断收到同样的错误 aspell love Error in aspell love No suitable spell checker program found 有什么想法吗 gt
  • 使用 GAS AT&T 指令计算引导扇区的填充长度?

    所以我想在引导扇区添加填充 比方说 目前只有一个无限循环 jmp 该扇区的长度需要为 512 字节 还有 神奇的数字0xaa55需要在最后添加 jmp skip 508 0 word 0xaa55 但是 如果我想打印一些内容 但不想计算所有
  • 如何在iOS Reachability中检测网络信号强度

    我正在 iOS 中创建一个新的旅行应用程序 该应用程序高度依赖于地图 并且将包含两个地图 当用户有较强的网络信号时 我的第一个地图将起作用 Apple 地图 我的第二张地图将在没有任何网络或信号非常低时使用 离线 地图框 为什么一个应用程序