如何在ios中永远运行后台服务以同步数据

2024-03-27

您好,我正在开发一个应用程序,它需要在网络服务器上进行同步操作(数据提交和检索)。

用户可以离线提交表单(即将数据存储到设备上的本地数据库)。只要网络可用,后台服务就应该将这些数据提交到网络服务器。

后台服务具体需求如下:

  • 后台服务会先检查网络是否可用
  • 如果网络可用,它将收集本地数据库(SQLite)中的数据存储 在设备上
  • 它将数据提交到服务器
  • 询问服务器是否有任何新数据,如果有的话,获取该数据 并更新设备上的本地数据库。

我对 iOS 和 xamarin/monotouch 很陌生,想知道如何实现这一点?

我了解iOS中的各种后台模式,例如后台获取、nsurlsession、后台传输等。

我尝试实现后台获取,我认为它适合我的情况。但它按照自己的时间运行。

还想知道如果用户杀死了我的应用程序,那么后台提取也将调用并仍然运行我的应用程序?

我的 appdelegate -> PerformFetch 方法中的代码是这样的:

if(networkService.IsNetworkAvailable())
{
   if(this.syncDataService.DownloadNewDataFromServer())
   {
       Console.WriteLine("Data downloaded successfully from server..");
   }
   if(this.syncDataService.UploadDataToServer())
   {
       Console.WriteLine("Data submitted successfully to server...");
   }
   completionHandler(UIBackgroundFetchResult.NewData);
}
else
{
   completionHandler(UIBackgroundFetchResult.NoData);
}

Update:最后我是这样实现的(希望对某人有帮助):

public class LocationUpdatedEventArgs : EventArgs
{
    private CLLocation location;

    public LocationUpdatedEventArgs(CLLocation location)
    {
        this.location = location;
    }

    public CLLocation Location
    {
        get { return this.location; }
    }
}

public class LocationManager
    {
        private static DateTime lastServiceRun;

        private CLLocationManager locMgr;

        public LocationManager()
        {
            this.locMgr = new CLLocationManager();
            this.LocationUpdated += this.PrintLocation;
            this.locMgr.Failed += (object sender, NSErrorEventArgs e) =>
            {
                Console.WriteLine("didFailWithError " + e.Error);
                Console.WriteLine("didFailWithError coe " + e.Error.Code);
            };
        }


        public event EventHandler<LocationUpdatedEventArgs> LocationUpdated = delegate { };


        public static TimeSpan TimeDiff { get; set; }


        public CLLocationManager LocMgr
        {
            get
            {
                return this.locMgr;
            }
        }


        public void StartLocationUpdates()
        {

            if (CLLocationManager.LocationServicesEnabled)
            {
                // sets the accuracy that we want in meters
                this.LocMgr.DesiredAccuracy = 1;

                //// Location updates are handled differently pre-iOS 6. If we want to support older versions of iOS,
                //// we want to do perform this check and let our LocationManager know how to handle location updates.

                if (UIDevice.CurrentDevice.CheckSystemVersion(6, 0))
                {
                    this.LocMgr.LocationsUpdated += (object sender, CLLocationsUpdatedEventArgs e) =>
                    {
                        //// fire our custom Location Updated event
                        this.LocationUpdated(this, new LocationUpdatedEventArgs(e.Locations[e.Locations.Length - 1]));
                    };
                }
                else
                {
                    //// this won't be called on iOS 6 (deprecated). We will get a warning here when we build.
                    this.LocMgr.UpdatedLocation += (object sender, CLLocationUpdatedEventArgs e) =>
                    {
                        this.LocationUpdated(this, new LocationUpdatedEventArgs(e.NewLocation));
                    };
                }

                //// Start our location updates
                this.LocMgr.StartUpdatingLocation();

                lastServiceRun = DateTime.Now;

                // Get some output from our manager in case of failure
                this.LocMgr.Failed += (object sender, NSErrorEventArgs e) =>
                {
                    Console.WriteLine(e.Error);
                };
            }
            else
            {
                //// Let the user know that they need to enable LocationServices
                Console.WriteLine("Location services not enabled, please enable this in your Settings");
            }
        }

        /// <summary>
        /// The stop updating location.
        /// </summary>
        public void StopUpdatingLocation()
        {
            this.locMgr.StopUpdatingLocation();
        }

        /// <summary>
        /// The print location. (This will keep going in the background)
        /// </summary>
        /// <param name="sender"> The sender. </param>
        /// <param name="e"> Location updated event argument </param>
        public void PrintLocation(object sender, LocationUpdatedEventArgs e)
        {
            CLLocation location = e.Location;

            Console.WriteLine("Longitude: " + location.Coordinate.Longitude);
            Console.WriteLine("Latitude: " + location.Coordinate.Latitude);

            var diff = DateTime.Now - lastServiceRun;
            TimeDiff = diff;
            if (TimeDiff.Minutes == 2)
            {
        // RunInBackground() is my method which call the service to upload/download data from server
                if (this.RunInBackground())
                {
                    lastServiceRun = DateTime.Now;
                }
            }
        }
}

计时器永远不会在后台工作,并且您不能在此方法中添加另一个线程。DidEnterBackground用于完成待处理的任务。这通常会持续大约 30 秒 - 1 分钟。

您可以在此方法中添加循环或添加长时间运行的任务。

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

如何在ios中永远运行后台服务以同步数据 的相关文章

  • 如何从 List 中的字符串中删除数字/数字?

    我有一个字符串列表 List
  • 使用 Selenium for C# 登录 Facebook

    我一直在使用 Selenium C 框架并尝试进行 facebook 登录 但没有任何运气 这是我到目前为止得到的 基于这篇文章 使用 Selenium 测试 Facebook Connect 应用程序 https stackoverflo
  • 将列表(对象)转换为列表(字符串)

    有没有办法转换List of Object to a List of String 在 c 或 vb net 中而不迭代所有项目 幕后迭代很好 我只想要简洁的代码 Update 最好的方法可能就是进行新的选择 myList Select f
  • Azure 2012 年 10 月 SDK 损坏 UseDevelopmentStorage=true

    有人尝试过使用 usedevelopmentstorage true 连接字符串的 2012 年 10 月 Azure sdk 吗 CloudStorageAccount Parse UseDevelopmentStorage true 抛
  • 如何在 Swift 编程中获得基于导航的模板功能

    我的项目需要一个导航控制器 并且我的应用程序最初有一个社交登录 一旦验证通过 用户将被推送到另一个视图 我在其中显示一个具有 2 个选项卡的选项卡控制器 我不知道如何在 Swift 编程中做到这一点 我已将视图控制器嵌入到导航控制器中 一旦
  • 使用成员作为实现者来实现接口

    我有实现 IA 的 A 类 现在我需要创建也应该实现 IA 的类 B B 类有 A 类的实例作为成员 有什么方法可以定义A的实例实现B类中的IA吗 interfase IA void method1 void method2 void me
  • C 中“for”循环中的两个变量

    我正在编写一些代码 需要在其中使用两个变量for环形 下面的代码看起来没问题吗 它确实给了我预期的结果 for loop 1 offset loop 2 offset 2 loop 1 gt offset 190 loop 2 lt 190
  • Create CFrameWnd 给出了第一次机会异常——为什么?

    我正在尝试使用基于 CFrameWnd 的代码编写一个简单的 MFC 应用程序 该应用程序在可滚动窗口中绘制 下面的代码改编自 Prosise Programming Windows with MFC 第 2 版 第 89ff 页 当我在调
  • GIDSignIn 在提示前指定范围

    我在 iOS 上升级到 GoogleSignIn 6 0 但找不到在登录时指定登录范围的方法 我只能看到一个名为 addScopes 的 API 我可以在基本登录后指定范围 但这会导致两个单独的登录提示 这很奇怪 之前 我们可以简单地指定登
  • 如何使用 libpq 获取双精度值?

    The examples http www postgresql org docs 9 3 interactive libpq example htmllibpq 文档中展示了如何通过将整数值转换为主机字节序表示来获取整数值 我很好奇必须做
  • 如何解释“错误C2018:未知字符'0x40'?[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 在编译一些代码时 我收到以下信息 错误 C2018 未知字符 0x40 我想知道如何解决这样的问题 这是我要开始的地方
  • C 中的 N 依赖注入 - 比链接器定义的数组更好的方法?

    Given a 库模块 在下文中称为Runner 它作为可重复使用的组件 无需重新编译 即静态链接库 中应用程序分区架构的 而不是主分区 请注意 它仅包含main 出于演示目的 Given a set 顺序无关 调用的其他模块 对象Call
  • Xcode 找不到我的静态库!

    这是链接器错误 i686 apple darwin10 gcc 4 2 1 Users william Documents SettingsLibrary build Debug iphonesimulator libSettingsLib
  • 如何分析 VSCode 中函数的性能

    我用 C Golang 编写了一个程序 如何找到占用最高 CPU 周期的函数 目的是提高正在执行的程序的性能 2021 年 10 月 金香儿哈娜 https github com hyangah宣布 tweet https twitter
  • 如何使用简历实现一个“一网打尽”的异常处理程序?

    我想知道我怎样才能写一个抓住他们全部应用程序级别的异常处理程序将为用户提供恢复应用程序流程的选项 如果您正在运行 Windows 窗体应用程序 将处理程序添加到Application ThreadException event
  • 致命错误 C1001:编译器中发生内部错误(编译器文件“msc1.cpp”,第 1325 行)

    当我编译代码时 错误指向以下类 该错误在两行上突出显示 如下所示 tm validFrom tm validUntil struct t SslCertData final struct t Contact TCHAR Organizati
  • 具有多种类型的 C# 泛型类型推断

    我有以下通用方法 用于将一种类型的输入对象序列化为超类型 如下所示 public string SerialiseAs
  • FakeItEasy 代理方法调用实际实现

    我正在尝试将对假对象的调用代理到实际的实现 这样做的原因是我希望能够使用 Machine Specifications 的 WasToldTo 和 WhenToldTo 它们仅适用于接口类型的伪造 因此 我正在执行以下操作来代理对我的真实对
  • 什么时候使用静态库需要头文件?

    如果我在 Linux 中用 C 创建一个静态库并生成 a 文件 我 或其他人 如何使用该库 例如 我的库定义了一个类 我认为仅仅提供 a 文件是不够的 还需要提供头文件 我如何知道 a 文件必须提供哪些头文件 例如 我是否需要提供我的库代码
  • 如何将 char 转换为 unsigned int?

    我有一个字符数组 它实际上用作字节数组 而不是用于存储文本 在数组中 有两个特定字节表示我需要存储到无符号 int 值中的数值 下面的代码解释了设置 char bytes bytes 2 bytes 0 0x0C For the sake

随机推荐