理财类项目怎么实现前后台oracle 数据同步步 iOS

iOS BLE 开发小记[4] - 如何实现 CoreBluetooth 后台运行模式 - 简书
iOS BLE 开发小记[4] - 如何实现 CoreBluetooth 后台运行模式
欢迎访问我的博客 ,该文章出自我的博客,欢迎转载,转载请注明来源: 。
在这一节,主要是 iOS APP 关于蓝牙后台处理方面的知识和经验。
对于 iOS APP 来说,知道你的 APP 是运行在前台还是运行在后台很重要。一个 APP 在后台运行状态下的行为表现必须不同于前台,因为 iOS 设备的系统资源是有限的。关于 iOS 后台运行处理的更多论述 请查阅 .
默认情况下,当你的 APP 在 background(后台运行)或者处于 suspended state(暂停状态)时,无论是 Central 端还是 Peripheral 端,许多常见的 CoreBluetooth 任务是不能被执行的。也就是说,你可以声明你的 APP 支持 CoreBluetooth 后台运行模式来允许你的 APP 进入 suspended state 后依然能够唤醒来处理一些蓝牙的事件。即使你的 APP 不需要全面的后台处理支持,但是当有重要事件发生的时候也需要系统给你发出弹框提醒。
即使你的 APP 不管支持哪一个 CoreBluetooth 后台运行模式,它也不能一直在后台运行。在某个时刻,系统会终止你的 APP 来为处于前台的其他 APP 提供内存空间,从而导致一些活动或者连接丢失。比如,对于 iOS 7, CoreBluetooth 支持 Central Manager 和 Peripheral Manager 对象状态信息的保存和在 APP 启动时恢复该状态信息,你可以使用这个功能来支持蓝牙设备的长期操作。
只能前台运行的 APP
除非你请求允许执行特定的后台任务,否则对于大多数 iOS APP 来说,当你的 APP 进入 background state(后台状态)不久后就会处于 suspended state(暂停状态)。当你的 APP 处于 suspended state 时是不能执行蓝牙相关的任务,也不能感知到任何蓝牙事件直到重新进入 foreground(前台)。
在 Central 端,没有声明支持 CoreBluetooth 后台运行模式的 APP,也就是只能前台运行的 APP,在 background 和 suspended 状态时,是不能搜索正在广播数据的 Peripheral。在 Peripheral 端,则是不能进行广播数据。此时如果一个 Central 尝试获取 Peripheral Characteristic 的值会收到一个错误。
根据使用情况,这种默认行为可能会以多种方式影响你的 APP,举个例子,试想一下,当你正在与刚连接的 Peripheral 进行数据交互时,此时你的 APP 进入 suspended 状态(当用户切换到另一个 APP时)中,如果 Peripheral 此时失去连接,你是不能感知到已经发生 disconnection(断开连接)事件了,直到你的 APP 重新进入 foreground 为止。
使用 Peripheral Connection options(选项)
只在前台运行的 APP 处于 suspended 状态时,系统会将发生的所有蓝牙事件加入队列,只有当 APP 重新进入前台时,才会将事件传递给 APP,也就是说,当 Central 产生事件时,CoreBluetooth 通过弹框提醒的方式通知用户。用户可以通过这个提醒来决定是否将 APP 重新打开来处理这个特定事件。
当调用 CBCentralManager 类的 connectPeripheral:options: 方法连接 Remote Peripheral 时,你可以利用下面这些 Peripheral 连接选项来设置弹框提醒。
CBConnectPeripheralOptionNotifyOnConnectionKey
-- 如果建立了一个成功的连接,此时 APP 进入 suspended 状态时,如果你想要系统为给定 Peripheral 显示一个弹框,你可以在 options 选项中包含这个键。
CBConnectPeripheralOptionNotifyOnDisconnectionKey -- 如果发生了 disconnection 事件,此时 APP 进入 suspended 状态时,如果你想要系统为给定 Peripheral 显示一个弹框,你可以在 options 选项中包含这个键。
CBConnectPeripheralOptionNotifyOnNotificationKey -- 如果收到了 Peripheral 的通知,此时 APP 进入 suspended 状态时,如果你想要系统显示一个来自 Peripheral 的通知弹框,你可以在 options 选项中包含这个件。
关于 Peripheral 连接参数的更多信息可以查阅
CoreBluetooth 后台运行模式
如果你的 APP 在后台运行状态下也需要执行蓝牙任务,你必须在 Info.plist (Infomation property list) 文件中声明你的 APP 支持 CoreBluetooth 后台运行模式。当你声明后,系统会唤醒 suspended 状态中的 APP 来处理蓝牙事件。这对于和每隔一段时间就传递数据的 BLE 设备进行交互的 APP 来说很重要,比如一个心率监测器。
APP 可能会声明的 CoreBluetooth 后台运行模式有两种。一种是 APP 扮演了 Central 的角色,另一种则是 APP 扮演了 Peripheral 的角色。如果你的 APP 同时扮演了这两种角色,你可以同时声明这两种后台运行模式。声明 CoreBluetooth 后台运行模式的方式就是在 Info.plist 文件中加入一个 UIBackgroundModes 的 Key,Value 则是包含以下提到的两种字符串的数组:
bluetooth-central -- APP 使用 CoreBluetooth 框架与其他 BLE 设备进行通信。
bluetooth-peripheral -- APP 使用 CoreBluetooth 框架来分享数据。
提示:Xcode 的属性列表编辑器默认显示的 Key 是人类易读的字符,而不是实际的 Key 的名字,要在 Info.plist 文件中显示实际 Key 名,按住 Control键并单击编辑器窗口中的任意 Key,并在弹出的上下文窗口中启用 Show Raw Keys/Values 项。比如 UIBackgroundModes 的易读 Key 名则是 Required background modes,如图所示
关于如何配置 Info.plist 文件内容的更多信息请查阅
bluetooth-central 后台运行模式
当扮演一个 Central 角色的 APP 在 Info.plist 文件中包含了 UIBackgroundModes bluetooth-central 键值对时,CoreBluetooth 框架允许你的 APP 在后台运行时执行蓝牙任务。当你的 APP 在后台运行时,你仍旧可以搜索和连接 Peripheral,然后与之进行数据交互。此外,当 CBCentralManagerDelegate 或者 CBPeripheralDelegate 的代理方法进行回调时,系统会唤醒你的 APP 允许你来处理这些 Central 端的重要事件。比如,成功建立了连接,连接中断,Peripheral 发送了一个更新值的通知,或者 Central Manager 的状态发生改变。
尽管你的 APP 在后台运行时可以执行许多蓝牙任务,但是你要注意这些,在后台运行状态下,当你搜索 Peripheral 的操作是不同于前台运行状态的。特别是当你 APP 在后台运行状态下搜索设备:
搜索参数 CBCentralManagerScanOptionAllowDuplicatesKey将会被忽略,多个广播数据的 Peripheral 发现事件将合并成一个发现事件。
如果所有的都在后台运行中搜索 Peripheral,则 Central 搜索广播数据包的时间间隔将会增加,你发现一个广播数据的 Peripheral 将会需要很长时间。
这种策略对降低 Radio 的使用频率和提高 iOS 设备的续航时间有帮助。
bluetooth-peripheral 后台运行模式
Peripheral 想要在后台执行蓝牙任务,你必须在 Info.plist 文件中包含了 UIBackgroundModes bluetooth-peripheral 键值对,这样系统会唤醒你的 APP 来处理读、写和订阅事件。
除了允许你的 APP 唤醒来处理读、写和来自 Central 的订阅请求外,CoreBluetooth 框架还允许你的 APP 在后台运行状态下广播数据。也就是说,你应该注意到,在后台状态下广播数据与在前台状态下的操作是不同的。特别是后台状态下广播数据:
广播的 CBAdvertisementDataLocalNameKey Key 将被忽略,Peripheral 的 local name 也不会广播。
广播中 CBAdvertisementDataServiceUUIDsKey 的值的所有服务 UUID 都被放置在 “overflow” 区域中。只有当 iOS 设备进行显式搜索才会被发现。
如果所有 APP 都在后台运行状态下广播数据,你的 Peripheral 广播数据包的频率将会降低。
谨慎使用后台运行模式
对于一般用户情况,可能不需要声明 APP 支持其中一个或两个 CoreBluetooth 后台运行模式,你应该对后台进程负责,因为执行蓝牙的任务需要使用用户设备的 onboard radio(板载广播),使用广播会影响用户设备的续航时间,应尽量减少在后台执行蓝牙任务。APP 被蓝牙时间唤醒后应迅速处理该事件然后尽可能快速的进入 suspended 状态。
声明支持 CoreBluetooth 后台运行模式的 APP 必须遵守一些基本准则:
APP 应该提供一个基于会话的界面来允许用户决定什么时候开始和结束发送蓝牙事件。
一个 APP 被唤醒时有 10秒 来完成一个任务,理想地,APP 应该尽快的完成任务然后再次进入 suspended 状态。APP 在后台运行时间太长会被系统限制或杀死。
APP 不应该一直处于唤醒状态来处理与系统唤醒无关的额外任务。
在后台运行状态下,你的 APP 应该如何操作的详情请查阅 .
在后台执行长期操作
一些 APP 可能需要使用 CoreBluetooth 框架来在后台运行状态下执行长期操作,比如,你想要为 iOS 设备开发一个 安全家庭 APP 来与配备 BLE 技术的门锁进行通信。APP 与门锁交互来自动锁门(当用户离开家的时候)和开锁(当用户回家的时候),整个期间 APP 一直在后台运行状态下。当用户离家的时候,iOS 设备终会超出门锁的有效范围,导致与门锁的连接中断。在这种情况下,APP 可以通过调用 CBCentralManager 类的 connectPeripheral:options:该方法来建立连接,因为连接请求不会超时,这样当用户到家的时候就会与门锁重新连接。
现在试想一种情况,当用户离家有一些天了,如果此时 APP 被系统给终止了。这样当用户回家的时候,APP 将不能与门锁重新连接,用户也不能打开门锁了。类似这样的 APP,使用 CoreBluetooth 来执行长期操作至关重要,例如监视活动和挂起连接。
状态保存和恢复
因为状态保存和恢复已经内置于 CoreBluetooth,你的 APP 可以选择加入这个功能来要求系统保存 APP 的 Central Manager 和 Peripheral Manager 的状态,并继续代表他们执行蓝牙任务,即使你的 APP 不在运行,当这些任务完成后,系统会重新让你的 APP 进入后台运行状态并给予一定的时间来保存状态和处理一些蓝牙事件。对于上述描述的安全家庭 APP 这种情况来说,系统将会监听连接请求,当用户回家的时候,系统将会重新启动 APP 来处理 centralManager:didConnectPeripheral: 代理回调和完成连接请求。
CoreBluetooth 对 扮演 Central 角色,Peripheral 角色,或者同时都扮演的 APP 都提供状态保存和恢复支持。当扮演 Central 角色的 APP 增加状态保存和恢复时,当系统释放内存空间需要终止你的 APP 时,会保存你的 Central Manager 的状态,如果你的 APP 拥有多个 Central Manager,你可以选择你想要系统跟踪的 Central Manager,尤其,对于给定的 CBCentralManager 对象,系统会跟踪:
Central Manger 搜索的 Service(和一些一开始指定搜索参数选项的)
Central Manager 尝试连接或者已经连接的 Peripheral
Central Manager 订阅的 Characteristic
扮演 Peripheral 角色的 APP 同样可以使用状态保存与恢复。对于 CBPeripheralManager 对象,系统会跟踪:
Peripheral Manager 广播的数据
Peripheral Manager 发布到设备库中的 Services 和 Characteristics
被 Central 订阅的 Characteristic 的值
当你的 APP 被系统置入后台运行状态时,你可以重新实例化 APP 的 Central Manager 和 Peripheral Manager 并恢复他们的状态。下面的章节会详细的描述如何在你的 APP 中使用状态保存和恢复。
添加状态保存和恢复支持
CoreBluetooth 的状态保存和恢复是选择性加入的功能,需要以下步骤来让 APP 这一功能生效,你可以参考一下的步骤来给你的 APP 增加状态保存和恢复功能:
1、(必须的)当你 allocate 和 initialize 一个 Central Manager 或 Peripheral Manager 对象时需要加入状态保存和恢复。这一步在 选择加入状态与恢复 小节有详细描述。
2、(必须的)当系统启动 APP 的时候需要重新实例化一些 Central Manager 或 Peripheral Manager 对象。这一步在 重新实例化你的 Central Manager 和 Peripheral Manager 小节有详细描述。
3、(必须的) 实现恰当的代理方法。这一步在 实现恰当的 Restoration Delegate 方法 小节有详细描述。
4、(可选的)更新你的 Central Manager 或 Peripheral Manager 的初始化进程。这一步在 更新你的初始化进程 小节中有详细描述。
选择加入状态保存与恢复
选择加入状态保存和恢复功能后,当你 allocate 和 initialize 一个 Central Manager 或者 Peripheral Manager 的时候,你需要提供一个唯一的恢复标识符。恢复标识符是一个标识 Central Manager 或者 Peripheral Manager 的字符串,字符串的值对你的代码很重要,它将会告诉 CoreBluetooth 需要保存使用该标记的对象,CoreBluetooth 只保存这些拥有恢复标识符的对象。
举个例子,为你的 APP (只有一个 CBCentralManager 对象的 Central )选择加入状态保存和恢复,当你初始化 Central Manager 的时候需要指定 options(初始化选项),选项是一个以 CBCentralManagerOptionRestoreIdentifierKey 为 key,Value 是 恢复标识符 的字典。示例代码如下:
myCentralManager =
[[CBCentralManager alloc] initWithDelegate:self queue:nil
options:@{ CBCentralManagerOptionRestoreIdentifierKey:
@"myCentralManagerIdentifier" }];
虽然上述例子没有证明这一点,当你给使用 Peripheral Manager 对象的 APP 选择加入状态保存与恢复时应使用类似的方式:在你初始化 Peripheral Manager 的时候指定 options(初始化选项),选项是一个以 CBCentralManagerOptionRestoreIdentifierKey 为 key,Value 是 恢复标识符 的字典。
提示:因为一个 APP 可能拥有多个 CBCentralManager 和 CBPeripheralManager 对象的实例,你应该确保他们的恢复标识符是唯一的,这样系统就能正确地区分它们。
重新实例化你的 Central Manager 和 Peripheral Manager
当你的 APP 被系统从后台启动时,你需要做的第一件事就是用状态恢复标识符重新实例化合适的 Central Manager 和 Peripheral Manager,恢复标识符要跟它们第一次被创建的一样。如果你的 APP 仅仅用到了一个 Central Manager 或者 Peripheral Manager,并且该 Manager 在你的 APP 生命周期中还存活着,则你就不需要做这一步。
如果你的 APP 使用超过一个以上的 Central Manager 或者 Peripheral Manager,或者使用的 Manager 在 APP 的生命周期中已经死亡了。当你的 APP 被系统启动时,它需要知道要恢复哪一个 Manager 。你可以通过 APP 终止时保存的 Manager 对象的恢复标识符列表,使用合适的 launch option(启动选项)参数(UIApplicationLaunchOptionsBluetoothCentralsKey 或者 UIApplicationLaunchOptionsBluetoothPeripheralsKey)在 application:didFinishLaunchingWithOptions: 代理方法回调中来获取恢复标识符数组。
举个例子,当系统启动 APP 时,你可以恢复所有 Central Manager 的恢复标识符,示例代码如下:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSArray *centralManagerIdentifiers =
launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];
当你获得恢复标识符列表后,遍历这个数组来重新实例化合适的 Central Manager 对象。
提示:当 APP 启动时,系统只会提供要执行一些蓝牙任务(此时 APP 没有在运行)的 Central Manager 和 Peripheral Manager 的恢复标识符。关于启动选项参数 Keys 的详情可以参考 .
实现恰当的 Restoration Delegate 方法
当你恢复合适的 Central Manager 和 Peripheral Manager 后,然后将他们的状态与蓝牙系统的状态同步。为了使你的 APP 达到系统处理的速度,你必须实现恰当的 Restoration Delegate 方法,对 Central Manager ,需要实现 centralManager:willRestoreState: 代理方法,而对于 Peripheral Manager,则需要实现 peripheralManager:willRestoreState: 代理方法。
重要提示:对于选择添加 CoreBluetooth 的状态保存与恢复的 APP,当 APP 从后台启动来完成一些蓝牙任务时,会第一个调用 centralManager:willRestoreState: 和 peripheralManager:willRestoreState: 代理方法,对于没有加入状态与恢复的 APP,会第一个调用 centralManagerDidUpdateState: 和 peripheralManagerDidUpdateState: 代理方法。
以上提到的这些代理方法,最后一个参数是一个字典,该字典包含 APP 终止时系统保存的 Manager 的信息。字典中可用的 Keys,可以查阅
用 centralManager:willRestoreState: 代理方法提供的字典的 Key 来恢复 CBCentralManager 对象的状态。举个例子,如果你的 Central Manager 拥有激活的或者中断的连接(APP 终止时),系统会继续监视 APP 的行为,如下所示,你可以通过 CBCentralManagerRestoredStatePeripheralsKey Key 去得到 Central Manager 连接的或者尝试连接的 Peripheral 列表(用 CBPeripheral 对象表示)。
- (void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary *)state {
NSArray *peripherals =
state[CBCentralManagerRestoredStatePeripheralsKey];
当你获得 Peripheral 列表后然后干什么取决于使用情况。举个例子,如果 APP 有一个 Central Manager 搜索的 Peripheral 列表,你可能想把恢复的 Peripheral 加入该列表中。此时确保要设置 Peripheral 的 Delegate 以保证能收到合适的代理回调。
你可以通过类似的方法利用 peripheralManager:willRestoreState: 代理方法提供的字典的 keys 来恢复 CBPeripheralManager 的状态。
更新你的初始化进程
当你实现前面必须的步骤后,你可能想要查看 Central Manager 和 Peripheral Manager 的初始化进程。尽管这是一个可选的步骤,但对确保 APP 稳定运行很重要。举个例子,当正与连接的 Peripheral 数据传输到一半时,APP 终止了。当你的 APP 恢复这个 Peripheral 时,你不知道 APP 终止时数据处理到哪一步,你想要确定从哪里继续开始处理。
举个例子,当在 centralManagerDidUpdateState: 代理方法中初始化 APP 时,如果你能够成功的从一个恢复的 Peripheral中找出指定的 Service(在 APP 终止之前),就像这样
NSUInteger serviceUUIDIndex =
[peripheral.services indexOfObjectPassingTest:^BOOL(CBService *obj,
NSUInteger index, BOOL *stop) {
return [obj.UUID isEqual:myServiceUUIDString];
if (serviceUUIDIndex == NSNotFound) {
[peripheral discoverServices:@[myServiceUUIDString]];
以上示例中,如果系统在你调用 discoverServices: 方法完成 Servic 搜索之前终止。如果 APP 搜索 Service 成功,你可以稍后查看是否发现合适的 Characteristic(一直订阅的) ,用这种方式来更新初始化进程,你需要在正确的时间调用正确的方法。
欢迎在本文下面留言一起交流心得...
飘在深圳的一枚iOS开发程序猿,坚信编程是一种技艺,一种用心学习的技艺!
欢迎访问我的博客 http://muhlenxi.com/
欢迎访问我的博客 muhlenXi,该文章出自我的博客,欢迎转载,转载请注明来源: http://muhlenxi.com//iOS-Bluetooth-Low-Energy-Develop-Chapter1。 导语: 不知不觉从事 iOS 低功耗蓝牙开...
Apple 官方文档 Core Bluetooth Programming Guide 的中文翻译本文翻译的是其中的第二章节 Performing Common Central Role Tasks一些术语:Bluetooth low energe(BLE):低功耗蓝牙,全...
这是 CoreBluetooth 系列的最后一篇,其他文章可查看: CoreBluetooth1 初识 CoreBluetooth2 作为 Central 时的数据读写 CoreBluetooth3 作为 Central 时的数据读写(补充) CoreBluetooth4 ...
iOS app中蓝牙的后台处理(Core Bluetooth Background Processing for iOS Apps) 对于iOS app来说,知道你的app是前台还是后台非常重要。由于iOS设备的系统资源有限,所以一个app在前台和后台时的表现一定是不一样的...
原文:http://blog.csdn.net/swibyn/article/details/ https://developer.apple.com/library/prerelease/content/documentation/NetworkingIn...
熟知驼鸟的人都知道,他身上有一显著特征:但凡遇到危险总爱将头钻入沙里,闭目塞听,一副眼不见、心不烦听天由命的样子,让人哭笑不得。 生活中不难发现这种驼鸟人,面对生活的压力与困难充耳不闻,视而不见,装聋作哑,习惯用“躲”与“逃&推卸责任,仿佛这样就能逃避人生的劫难与厄运。 见...
商量去市场买条鱼,二孩儿特别强调要买一条已经死了的,因为死了的除了被吃掉已经没其他价值了[微笑]可如果是活的鱼杀了会疼的[尴尬]我强烈表示同意他的善良的建议,然后我也建议:你在家等着吧[偷笑]妈妈去买保证按你的要求去做[微笑]他坚持要一起去监督[尴尬]路上看到两只鸟落在我们...
一个人走在回家的路上,听着永澄老师在手机的一端领读着《跃迁》这本书,最近这本书在我的朋友圈很火,也是我这半年以来看得最过瘾的一本书了。当收到书的时候,我用了三个早晚的时间把整本书看完了,而且还在书中记录了大量的思考笔记。 之所以参加领读,其中一个很重要的目的是看看,一样是阅...
越王勾践, 别名鸠浅、句践、菼执, 前496年-464年越国国君。常言道:“天将大任于斯人者,苦心智,劳筋骨,饿体肤,空乏其身,行拂乱其所为”短短数言,勾绘了勾践的传奇色彩。“鸟尽弓藏,兔死狗烹”范蠡一言道尽了勾践乃至天下君王的常态。“卧薪藏胆, 三千越甲可吞吴”字字句句,...
我姓崔,叫座山雕,今年五十岁零七天,处女座,喜欢吃鸡,职业是专业土匪头子,被行内人尊称三爷。 几年前和几个兄弟从日本那里接手了一座碉堡,还有几辆车和坦克,也算是小有成绩。 平常也没什么兴趣爱好,就是抢枪东西,安排一下任务,吃一点鸡。 哦,我不喜欢打手枪,喜欢打老婆。这当然是...iOS后台如何保持socket长连接和数据传输
工程中使用tcp长连接来和服务端进行数据传输,在平台上,由于苹果的后台机制,会有以下问题:
当程序退到后台的时候,所有线程被挂起,会回收所有的socket资源,那么socket连接就会被关闭,因此无法再进行数据的传输:
解决方法:
通过设置以下属性可以保持socket连接和数据的继续传输
1.需要在Info.plist文件中添加UIBackgroundModes中的VOIP键值;
2.设置流属性
CFReadStreamRef和CFWriteStreamRef通过如下方法设置kCFStreamNetworkServiceType属性为kCFStreamNetworkServiceTypeVoIP;
CFReadStreamSetProperty(theReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
CFWriteStreamSetProperty(theWriteStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
NSInputStream 和NSOutputStream通过如下方法设置NSStreamNetworkServiceType属性为NSStreamNetworkServiceTypeVoIP;
[self.stream setProperty: NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];
3.这里有一个问题,就是客户端是通过心跳来和服务端保持连接,心跳是由定时器触发的,当我退到后台以后,定时器方法被挂起,那么通过如下设置来在后台运行定时器
- (void)applicationDidEnterBackground:(UIApplication *)application{
UIApplication*
app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgT
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
bgTask = UIBackgroundTaskI
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
bgTask = UIBackgroundTaskI从Java转iOS第一个项目总结
招聘信息:
0.前言1.项目介绍2.项目使用的第三方开源库3.工具和插件介绍4.集成友盟5.即时通讯6.项目总结0.前言本人14年12月份,从网站开发组转到了移动开发组,自己的java两年半工作经验变成了Objective-C零经验。2015年1月份新启动了一个移动项目,年后因为人事变动,自己从辅助开发变成了"核心"开发,目前项目基本接近尾声,下面进行总结,希望对一些人能有帮助, 另外也希望iOS大牛进行指导。1.项目介绍项目属于一款社区类软件,包含小组/帖子、视频、文章、评论、推荐搜索、即时通讯、好友、第三方登录/分享以及推送等,涵盖常用app的基本功能。2.项目使用的第三方开源库整理了比较常用的iOS第三方组件,以及github上的统计。项目使用了CocoaPods(类似java中的maven)管理常用的第三方库,一些特殊的单独引用,下面介绍下比较好用的几个。(1)目前比较推荐的iOS网络请求组件,默认网络请求是异步,通过block回调的方式对返回数据进行处理。需要注意的是AFNetworking对服务器返回的ContentType要求比较严格,默认只支持application/json的返回。所以可能需要添加对text/html返回的支持,否则可能无法获得返回数据。另外就是文件上传,这里推荐使用第二种:[formData&appendPartWithFormData:&name:];
[formData&appendPartWithFileData:&name:&fileName:&mimeType:];第一种只需要传入表单名和文件流,源码也是根据文件流获得对应的文件名和文件类型,然后调用第二种方法。但是楼主遇到了使用第一种方法,提交后后台判断为非文件上传,无法获得文件流。还有如果后台是根据文件后缀文件类型,那么第一种也无法使用。AFNetworking是异步的,也可以使用同步的网络请求方法.(2).对sqlite数据库操作进行了封装,demo也比较简单。(3).也是iOS项目常用的一个组件,用于显示过渡效果的,比如网络请求之前显示loading,网络结束隐藏loading。建议封装在BaseViewController中,所有ViewController继承就能使用。(4).这个是李明杰老师的作品,自己的OC基础就是看他的视频半个周末就基本拿下了。MJRefresh主要用于刷新操作,提供了常用的刷新操作,还有刷新动画,用着很好用。建议把方法封装在BaseViewController中,这样修改刷新操作时,就只需要改动一份。(之前用的旧版MJRefresh,只支持普通的刷新,不支持动画,后来更新后版本变化比较大,旧的方法已经不推荐使用了,所以还是封装基类中使用比较好,方便以后修改)(5).也是iOS最常用的一个组件,用户加载网络图片,可以缓存到本地。大概原理时,第一次加载后,会根据url加密作为文件名缓存在本地,如果再次加载图片时,就直接从本地加载。用着也比较简单。这里也分享遇到的一个问题,先从网络加载一张小图,然后小图作为占位图,再从网络加载一张大图。[imageView&sd_setImageWithURL:[NSURL&URLWithString:imageURLString]&placeholderImage:DefaultPostPic];
[imageView&sd_setImageWithURL:[NSURL&URLWithString:_bigImageURLStringArray[i]]&placeholderImage:imageView.image&options:SDWebImageDelayPlaceholder&completed:^(UIImage&*image,&NSError&*error,&SDImageCacheType&cacheType,&NSURL&*imageURL)&{
}];(6).一个TabBar组件,可以方便设置底部菜单的文字图片,点击效果,小红点提示等。(7).类似android的toast提示效果,封装在BaseViewController中,需要的地方进行提示。(8).iOS唯一的xmpp类库,作者在去年8月份添加了xep-0198协议支持(流管理,用于xmpp断线重连),但是通过pod进行更新时,无法下载到最新版本,可能0198还没有完善好,无法作为正式版。(9).用户键盘弹出自动计算高度,进行屏幕滚动操作。(10).做即时通讯的音频处理,目前我们的即时通讯使用的录音文件是m4a,便于web端的音频播放。(11).用于做富文本视图控件显示,用于即时通讯的表情显示,以及资源评论的富文本显示。(12).用作即时通讯文本框和评论文本框使用,可以显示多行输入。(13).也是李明杰老师的作品,用于json转model进行使用,有点类似于java中谷歌的Gson。转换效率据说也很高,使用也比较简单,只要前后台约定好,json直接就转成了model。一个工作多年的iOS朋友说,一个项目主要的是对model层的管理,他推荐的是Mantle。不过MJ这个更轻量级点,用着也更加简单。3.工具和插件介绍XcodeiOS开发的官方工具,也没别的选择。有些功能做的确实挺帅的,比如StroyBoard的拖拽事件绑定。不爽的地方就是没有代码格式化,另外点击方法,可能跑到另外一个类中了!!另外左边的目录也不会自动发生变化,定位到对应文件,需要command+shift+jSimPholders2可以快速找到模拟器对应的沙盒目录,启动后右侧顶部工具栏有个类似关闭按键的按钮,显示最近的几个应用,点击就进入到了对应的沙盒目录。xcode工具,///生成注解模板,xcode这功能都不给集成,唉。其他的基本就不用介绍了,有的也不怎么好用。SVN可以使用Cornerstone,Git可以使用SourceTree,sqlite可以使用SQLite Professional(不过是收费的,免费的只能查看),还可以用火狐浏览器的sqlite插件。4.集成友盟,提供了App和运用的一站式解决方案。公司上个移动项目用到了友盟的推送服务,这个项目中, 还使用了分享,第三方登录的功能,自己也亲自参与到了相关集成。友盟的开发者文档还算是比较全的,遇到问题可以联系客服或者到友盟的论坛找解决方案。(1).关于推送iOS推送分为本地推送和远程推送,本地推送是指本地自己弹出信息,另外一个就是远程推送,当应用未启动时,也能收到相关推送信息。我们项目没有使用本地推送,使用的都是友盟的远程推送。包括消息(聊天)和通知(用户信息通知)中。用户在聊天过程中,手机除了发送即时通讯以外,也调用后台接口,发送友盟推送。另外用户的帖子,评论,关注,点赞等都会由后台调用友盟的推送。(另外一个域名)包括单播,列播,和广播,其中广播限定次数每天3次,可以和友盟申请提高次数,其他不限定次数,目前来看单播速度还是挺快的。使用友盟推送,需要在苹果开发者账号中,新建两个推送证书,提交给友盟(友盟有详细的文档,可以参考)。可以在友盟后台,把测试设备的deviceToken加到友盟推送的后台,从友盟后台发起推送。(需要64位token,需要通过方法进行计算,直接在xcode或者ituns中拿到token不行)推送的大概流程就是,手机在第一次启动app的时候开启推送服务,手机在启动app的时候,注册友盟服务,同时把deviceToken提交到自己的后台,后台可以在需要的时候拿着deviceToken调用友盟的推送接口,友盟再去发起苹果的推送服务,使对应的设备收到远程推送信息。(2).关于第三方登录和分享这块儿都在友盟的社会化分享中,里面提供了比较全面的文档。建议第三方分享模块不用自己特殊设计,可以使用友盟的默认分享模块(我们项目的分享模块自己进行了设计,包括了收藏,所以整块都需要自定义写UI和写分享代码)。关于友盟的第三方登录和分享需要注意的时,QQ和微信登录分享,都需要手机上安装应用,appstore审核会卡这点,所以需要判断手机是否安装应用,隐藏没有安装应用的图标,这块儿友盟的sdk已经有相关的判断方法(应该是友盟集成了QQ和微信sdk,QQ和微信sdk提供了判断方法)。第三方登录分享需要到相关的平台注册开发者账号。微信开发者账号(注意不是订阅号)第三方登录需要交钱才能开通,可以支持微信和朋友圈分享。QQ开发者账号可以支持QQ和QQ空间分享(QQ微博好像需要微博开发者账号)。新浪微博需要微博开发者账号。QQ分享开发阶段需要把测试账号加成开发者账号的好友才能测试,微博也类似。第三方登录自己遇到了QQ提示不是最新版的文本,在中找到了。第三方登录,我们项目集成了QQ,微信,新浪微博登录。三个平台都能获得用户的screen_name(用户名称),以及对应的平台唯一的id,其中QQ和微信都是openid,新浪是userid。第三方分享,文档提供了分享图片,视频,语音。如果是分享url,需要设置对应平台的分享地址,参考解决方案,比如[UMSocialData&defaultData].extConfig.qqData.url&=&shareU
[UMSocialData&defaultData].extConfig.qzoneData.url&=&shareU
[UMSocialData&defaultData].extConfig.wechatSessionData.url&=&shareU
[UMSocialData&defaultData].extConfig.wechatTimelineData.url&=&shareU另外分享到QQ空间,必须指定一张图片,否则不能分享成功。第三方分享建议封装到一个类中,我们项目是几个详情页都有分享,评论,举报,收藏,点赞等功能。封装在一个BaseDetailViewController中的,相关页面继承,同时传入对应的资源类型,只用维护一份代码。5.即时通讯即时通讯网上有第三方的解决方案,比如环信,融云等。我们是自己搭的xmpp服务器,服务器使用的tigase,之前写过相关的博客,自己去年也做了对应的webim。前段时间看了环信webim的sdk,使用的也是strophe的js类库,相关实现跟我们的差不多,但是自己搭建xmpp会遇到了不少问题,比如丢消息!所以如果想比较快速的实现im,推荐使用第三方的解决方案。移动端的丢消息大概是这个样子。A和B通讯,A发了一条消息给服务器,服务器发给B,但是B网络不好掉线了,而服务器却不知道B退出了(B正常退出会给服务器发下线通知),所以消息丢失了。XMPP中有xep-0184协议(消息回执),A给B发消息,消息体中带一行代码(要求消息回执),当B收到消息后发送一条回执,证明我收到了。后来XMPP又有了xep-0198协议(流管理),断线后快速重链,同时判断一定时间收不到消息,就把消息写离线消息,减少丢消息情况。但是可能网络情况复杂,加上各种不确定因素,还会出现丢消息的问题。目前比较靠谱的方法就是存所有的聊天记录,由手机端根据时间点去数据库拉消息,只要别人发出的消息就不会丢。这次即时通讯模块进行了相关改动,也是参考了之前开发人员的一些建议。比如用户返回home的时候,断开xmpp连接(iOS进入后台后,只有5秒的处理时间,特殊方法可延长到10分钟,如果内存不够,应用随时就被杀死了)。所以返回home时就断开,进入应用再连接。同时应用使用状态下,有心跳检测,判断是否保持连接。考虑到iOS的特殊性,我们采取了xmpp和远程推送都走的方法,推送的自定义消息体和xmpp消息体一样,消息的处理方法一样。用户聊天发送xmpp消息的同时也调用我们的消息推送接口调用友盟push(push可以设置过期时间,避免特殊情况,推送延时,聊天结束了才收到推送)。一是解决iOS应用未启动时的推送接收,二是解决xmpp丢消息的问题。关于推送,AppDelage中有两个方法,一个是使用中收到推送,不会提示,会直接处理推送信息。另外是程序非使用状态,收到推送,会进行提示,可以点击推送消息进入应用,获取这一条推送消息的推送消息(需要注意,点击推送启动应用拿到信息时view还没有加载,消息不能立刻处理)。android端因为是真后台,可以后台一直保持运行,无论收到xmpp消息还是友盟推送,都可以自己进行处理,然后自己弹一个本地推送(也有弊端,如果android程序杀死,就无法接受消息和推送)。iOS端因为后台不可控,所以推送使用远程推送,进入应用连接xmpp再收全部离线消息(不保证友盟推送能否保证及时)。当然大部分都还是正常情况,网络情况比较好的条件下,就实时收到了xmpp的消息或者远程推送。我们又不是QQ和微信,只要保证用户看到的数据能保持一致性就行了(所以QQ和微信就是diao啊)。根据测试反馈的情况,iOS这个应用的丢消息情况比上个应用有一定改善。具体情况再进一步观察把。我们的即时通讯也包括语音和图片,采用的是http的解决方案(xmpp也支持二进制的传输,但是估计没人那样用)。具体流程就是先把附件传到附件服务器拿到附件服务器的地址,再封装到消息体。接收方收到消息解析的时候,再从附件服务器拿到对应的资源,加载到本地。 同时屏蔽,取消屏蔽等一些实时操作也都会发xmpp,第一时间双方更新状态。6.项目总结目前项目已经接近尾声了,再过不到半月就要上线了。自己算是项目的主要负责人了。项目前期iOS和android有一周多前期准备和框架搭建,另外就是我根据页面原型,定义接口文档开发计划,协调开发。可能大家项目经验也都不多把,框架和接口或多或少都会有点问题,随着经验慢慢积累肯定都会越来越好的。关于iOS的总结下:框架搭建的时候,要考虑好App中各功能点的实现方案。设计好相关文件目录,封装相关类文件。封装整理相关方法,比如BaseViewController中包括,基本ui,顶部导航条,左按钮,右按钮,标题,相关点击事件,显示/隐藏loading,网络请求失败统一处理方法,上拉/下拉刷新绑定,刷新显示/隐藏。分析项目中的功能相同模块,封装对应操作,相同功能代码维护一份。考虑好刷新机制,比如A页面进入B页面,B更新后,返回后A页面的刷新,如果采用block/delegate的方法,可以统一进行设计。或者多个页面之间的数据刷新,采用通知的方式(KVO),进行更新操作。尽量开发阶段,就把可能出现的问题提前解决。确定是否进行相关页面统计,比如加友盟的页面统计,需要设置相关view的viewWillAppear和viewWillDisappear()ViewController中初始化view和数据请求后刷新view代码分离,封装整理好网络请求前和请求后的操作,考虑好下拉刷新页面和上拉加载更多的相关数据请求和处理。考虑有网状态下的数据缓存以及无网状态下的缓存数据加载提前做好相关页面的跳转,代码解耦,不断优化和重构代码。发现问题或者有更好的解决方案,尽量早期就进行修改,避免修修补补,方便后期维护和扩展。在可以接受的情况下,可以牺牲一些系能,保持逻辑简单,便于维护。通过代码写view计算坐标时,尽量参考上一个元素的坐标和宽高,这样当一个元素位置或宽高发生变化时,其他元素基本都能随着发生变化。数据处理能放在服务器端处理就由服务器端处理,前台就进行无脑显示。考虑程序的兼容性,32位和64位一些变量的值不同,注意值的越界问题。注意程序的内存问题,和使用过程中的内存变化。考虑信息的安全性,沙盒存储的信息可以被查看修改,重要信息请加密。续篇:
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量3430点击量3368点击量2749点击量2666点击量2080点击量1736点击量1646点击量1625点击量1590
&2018 Chukong Technologies,Inc.
京公网安备89}

我要回帖

更多关于 excel跨表格数据同步 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信