RyukieDev
  • 关于我-AboutMe
  • 我的作品-MyApps
    • 「梦见」账本
      • 「梦见」账本(Umemi):极致的记账体验
      • 隐私协议:Privacy Policy
      • 服务协议:Terms of use
      • 外观预览:Preview
        • 赛博朋克-Cyberpunk
        • 樱-Sakura
        • 初恋-FirstLove
        • 永生-Eternal
        • 菲尼克斯-Phoenix
        • 报丧女妖-Banshee
        • 九霄-NYXL
        • Dream
        • 猕猴桃-Kiwi
        • 蜂蜜-Hachimitsu
        • DC
    • Elic-扫雷无尽天梯
    • 隐私访问记录
      • 03.如何分析iOS15隐私访问记录
      • PrivacyPolicy
      • FrameWorks
    • 醒词
      • PrivacyPolicy
      • TermsOfUse
    • 一色
      • PrivacyPolicy
    • 醒诗
      • PrivacyPolicy
    • 醒词键盘
      • PrivacyPolicy
    • 中文数字键盘
      • PrivacyPolicy
  • 独立开发
    • 产运
      • 01.没钱推广?这忘了这100美元
      • 02.在个人站点配置app-ads
      • 03.应用图标圆角
      • 04.iOS独立开发者注册公司到App备案上架.md
    • iCloud
      • 01.基于iCloud构建用户体系
      • 02.基于iCloud构建游戏内排行榜
  • Swift
    • 01.纯Swift路由方案探究
    • 02.使用Carthage替代CocoaPods
    • 03.逃逸闭包和非逃逸闭包
    • 04.向下向上取整
    • 05.Copy-on-write
    • 06.OC老项目Swift混编的一些坑
    • 07.OC项目中加入Swift混编
    • 08.Optional实质
    • 09.R-Swift-安全的资源组织方案forSwift
    • 10.Struct与Class
    • 11.Swift5新特性
    • 12.Swift性能分析
    • 13.SwiftPackage使用
    • 14.String与Substring
    • 15.Array,Set,Dictionary
    • 16.For-in跳跃遍历
    • 17.Switch元祖
    • 18.循环的标签控制
    • 19.Protocol与静态派发、动态派发
    • 20.Swift位移枚举
    • 21.Swift轻量级网络封装:SwiftyServiceProtocol(适用于混编或纯Swift项目)
    • 22.open与public
    • 23.Swift项目编译速度优化
    • 24.[译]编写高性能Swift代码-Writing High-Performance Swift Code(2022.8.25版)
    • 25.Swift编译流程
    • 26.Swift方法调度
  • SwiftUI
    • 01.Form
    • 02.Navigation
    • 03.ViewBuilder参数10个限制
    • 04.UIKit混编时Dismiss掉HostController
    • 05.如何在SwiftUI中使用ImagePicker?
    • 06.从some看Swift不透明类型
    • 07.TabView使用
    • 08.openURL
    • 09.Search
    • 10.SwifUI中使用WKWebView
  • DeepLearning
    • 基础知识
      • 01.感知机与神经网络
      • 02.线性可分
    • TensorFlow
      • 01.Anaconda
      • 02.JupyterNotebook
      • 03.安装TensorFlow
  • iOS
    • 底层
      • 01.alloc与字节对齐
      • 02.结构体内存对齐
      • 03.对象本质探究与isa
      • 04.ISA与Class
      • 05.深入探索Class的结构
      • 06.WWDC20-runtime优化
      • 07.深入探究属性
      • 08.isKindOfClass的底层实现
      • 09.slowpath和fastpath
      • 10.Class-cache_t
      • 11.源码解读objc_msgSend
      • 12.类的实现与初始化源码解读
      • 13.动态决议与消息转发
      • 14.iOS应用启动(一):dyld与main函数
      • 15.iOS应用启动(二):环境配置与runtime初始化
      • 16.iOS应用启动(三):镜像文件的读取和加载
      • 17.iOS应用启动(四):分类的加载
      • 18.关联对象源码解析
      • 19.MethodSwizzing方法交换的坑
      • 20.详解KVC
      • 21.KVO几个被忽视的细节
      • 22.KVO底层原理
      • 23.多线程原理与atomic
      • 24.任务与队列的几个面试题
      • 25.dispatch_once单例实现原理
      • 26.栅栏函数
      • 27.信号量
      • 28.锁|性能分析
      • 29.锁|@synchronized
      • 30.锁|递归锁
      • 31.锁|NSConditionLock
      • 32.关于Block你所该知道的一切
    • 内存管理
      • 01.从一个面试题看TaggedPointer
      • 02.Retain&Release
      • 03.SideTable和weak底层实现
      • 04.Timer优化
      • 05.自动释放池与Runloop
      • 06.dealloc
    • 编译器
      • 01.LLVM
    • 杂项
      • 01.堆栈的深度问题
      • 02.使用TTF字体
      • 03.为什么选VIPER
      • 04.项目路由方案
      • 05.隐藏导航栏下面的线
      • 06.源代码到IPA
      • 07.iOS重签名调研
      • 08.load与-initialize
      • 09.NSTimer与GCD
      • 10.NSURLConnection-和-NSURLSession
      • 11.Storyboard中UnwindSegue的使用
      • 12.UI调试-UIDebuggingInformationOverlay
      • 13.UIWebView和WKWebView
      • 14.UIWebView自适应高度
      • 15.weak实现原理
    • Runloop
      • 01.RunLoop
      • 02.autoreleasepool
    • Runtime
      • 01.基本操作
      • 02.实现NSCoding的自动归档和自动解档
      • 03.消息机制
      • 04.重写description打印对象信息
      • 05.MethodSwizzling的问题
    • 优化
      • 01.Apple官方资源瘦身方案ODR(一):初见
      • 02.Apple官方资源瘦身方案ODR(二):践行|换肤系统改造
      • 03.二进制重排实践
      • 04.iOS截屏防护方案
      • 05.提高编译速度
      • 06.图片格式-WebP
      • 07.App启动速度优化
      • 08.IDL自动化埋点
      • 09.渲染原理及优化
      • 10.「利用 Metrics 和 Diagnostics 提高性能」网络研讨活动
      • 11.离屏渲染
      • 12.一键搞定iOS16横竖屏切换
    • 多线程
      • 01.合适的线程数量
      • 02.死锁
      • 03.为什么用dispatch-once实现单例
      • 04.iOS多线程方案
      • 05.iOS多线程技术对比
    • Database
      • 01.数据库主键和外键
      • 02.FMDB-死锁问题
      • 03.FMDB与WCDB
      • 04.SQLite数据库修复
    • 架构
      • 01.组件化
  • 逆向
    • 01.寄存器
    • 03.iOS应用签名原理
    • 04.利用Xcode进行重签名与调试
    • 05.dylib注入
    • 06.MachO文件
    • 07.dyld
    • 08.Hook
    • 09.深入理解动态库与静态库
    • 10.通过符号表找到符号
    • 11.fishhook原理
    • 12.去符号与恢复符号
    • 13.反HOOK防护(一):基于Fishhook
    • 14.反HOOK防护(二):Monkey
    • 15.Inlinehook:Dobby
    • 16.LLDB
    • 17.虚拟内存
    • 18.Chisel工具
    • 19.DS.LLDB工具
    • 20.Cycript工具
    • 21.Cycrupt用法
    • 22.Logos
    • 23.应用砸壳
    • 24.实战人人视频破解
    • 25.解密被加密的数据库文件
  • Flutter
    • 01.初见Flutter
    • 02.Layout
    • 03.状态管理
    • 04.BottomNavigationBar
    • 05.MaterialApp
    • 06.android资源配置
    • 07.Positioned与Container嵌套无法充满容器
    • 08.Cell点击跳转
    • 09.代码规范
    • 10.通过联系人Cell看断言
    • 11.有状态Widget初始化重写&链式调用&排序
    • 12.索引条:手势及clamp函数
    • 13.ListView滑动到指定位置
    • 14.悬浮菜单列表
    • 15.Mock数据小技巧
    • 16.第三方库导入与网络数据异步请求与展示
    • 17.请求数据保留
    • 18.异步编程之Future
    • 19.Future&Microtask
    • 20.Dart异步编程:Isolates和事件循环
    • 21.Widget的生命周期
    • 22.Widget树&Render树&Element树
    • 23.Key
    • 24.调用原生相册
    • 25.iOS原生嵌入FlutterModule
  • 网络
    • 01 网络分层的优点
    • 02 网络理解
    • 03 iOS-网络安全之HTTPS
    • 04 POST和GET
    • 05 SSL-TLS四次握手
  • 直播技术
    • 01 直播技术相关
    • Socket-Little-Endian-Big-Endian
  • 知识点梳理
    • 01 面试算法题记录01
    • 02 面试题记录-C语言
    • 08 一套iOS底层试卷
    • 03 知识点梳理:iOS底层
    • 04 知识点梳理:网络
    • 05 知识点梳理:多线程
    • 06 知识点梳理:计算机基础
    • 07 知识点梳理:算法数据结构
    • 09 知识点梳理:HTML和浏览器
    • 10 知识点梳理:JavaSctipt
  • Framework
    • 01 CodeReading-01-YYModel
    • 02 RYImagePicker-iOS图片视频选择器
    • 03 RYImagesScroller-iOS高度自定义的图片轮播器
    • 04 RYPhotosBrowser
  • Issue
    • 01 使用KVC设置UIAlertAction按钮颜色的Crash
    • 02 iOS-常见崩溃分析
    • 03 UICollectionView的一些问题
  • OpenGL ES
    • 01.顶点着色器与片元着色器
  • 数据结构与算法
    • 剑指Offer-Swift
      • 03.找出数组中重复的数字
      • 04.二维数组中的查找
      • 05.替换空格
      • 06.从尾到头打印链表
      • 07.重建二叉树
      • 12.矩阵中的路径(回溯法)
      • 13.机器人的运动范围
      • 14.I.剪绳子
      • 14.II.剪绳子
      • 15.二进制中1的个数(含一个拓展问题)
      • 16.数值的整数次方
      • 18.删除链表的节点
      • 21.调整数组顺序使奇数位于偶数前面
      • 22.链表中倒数第k个节点
      • 24.反转链表
      • 25.合并两个排序的链表
      • 26.树的子结构
      • 27.二叉树的镜像
      • 28.对称的二叉树
      • 29.顺时针打印矩阵
      • 30.包含min函数的栈(容易被误导的一题)
      • 31.栈的压入、弹出序列
      • 32.I.从上到下打印二叉树
      • 32.II.从上到下打印二叉树II
      • 32.III.从上到下打印二叉树III
      • 32.从上到下花式打印二叉树
      • 33.二叉搜索树的后序遍历序列
      • 34.二叉树中和为某一值的路径
      • 35.复杂链表的复制(无Swift用例)
      • 36.二叉搜索树与双向链表
      • 37.序列化二叉树
      • 39.数组中出现次数超过一半的数字
      • 40.最小的k个数
      • 41.数据流中的中位数
      • 42.连续子数组的最大和
      • 43.1~n整数中1出现的次数
      • 44.数字序列中某一位的数字
      • 45.把数组排成最小的数
      • 46.把数字翻译成字符串
      • 47.礼物的最大价值
      • 48.最长不含重复字符的子字符串
      • 50.第一个只出现一次的字符
      • 52.两个链表的第一个公共节点
      • 53-I.在排序数组中查找数字
      • 53-II.0~n-1中缺失的数字
      • 54.二叉搜索树的第k大节点
      • 55-I.二叉树的深度
      • 55-II.平衡二叉树
      • 56-I.数组中数字出现的次数
      • 56-II.数组中数字出现的次数II
      • 57.和为s的两个数字
      • 58-I.翻转单词顺序
      • 58-II.左旋转字符串
      • 59-I.滑动窗口的最大值
      • 59-II.队列的最大值
      • 60.n个骰子的点数
      • 61.扑克牌中的顺子
      • 62.圆圈中最后剩下的数字
      • 63.股票的最大利润
      • 64.求1+2+…+n
      • 65.不用加减乘除做加法
      • 66.构建乘积数组
      • 67.把字符串转换成整数
      • 68-I.二叉搜索树的最近公共祖先
      • 68-II.二叉树的最近公共祖先
    • 技巧
      • 01.前缀和
      • 02.同余性质
      • 03.快速幂
      • 04.快速排序
      • 05.深度优先&广度优先
      • 06.冒泡排序
      • 07.摩尔投票
      • 08.优先队列
    • 数据结构
Powered by GitBook
On this page
  • 一、前言
  • 2.1 自己开发
  • 2.2 LeanCloud
  • 2.3 GameCenter
  • 2.4 iCloud
  • 三、什么是CloudKit
  • 四、CloudKit存储数据的方式
  • 4.1 基础数据单元:CKRecord
  • 4.2 数据存储空间:Zone
  • 4.3 数据表结构:RecordTypes
  • 4.4 数据索引:Indexs
  • 五、QA
  • 5.1 存在iCloud安全么?
  • 5.2 要是用户抓包改数据呢?
  • 5.3 破解?
  • 5.4 访问速度
  • 5.5 运维成本
  • 5.6 跨平台
  • 5.7 容量
  • 5.8 资源存储 CKAsset
  • 七、总结
  • 八、参考

Was this helpful?

  1. 独立开发
  2. iCloud

01.基于iCloud构建用户体系

一、前言

这个md文档一月份就创建了,一直没填坑。

虽然应用本身不是什么成功的应用,但是自己感觉在做的过程中还是有挺多收获的。

注意: 本文不会非常详细的说明具体类的使用方法,代码具体怎么写,这些官方文档比任何人都说的清楚。

目的在于对于个人开发者提供一个思路。

大多个人开发者,比如我自己,资源时间精力有限,但是想法很多。

而iCloud是我遇到最合适用来构建起用户体系,以及拓展功能需求的工具了。

自己已经独立做了两款应用,都是基于iCloud建立起来的,欢迎体验反馈,要是再来个五星好评是对我最大的鼓励~

-

扫雷Elic 无尽天梯

梦见账本

下载

哎,没有设计师自己整UI终究还是不太好看啊~TAT~

下面会以扫雷项目中的例子来做一些说明

二、独立项目用户体系技术方案选型

2.1 自己开发

也不是没考虑过,但不是自己所擅长的。而且需要考虑的问题太多,技术、运维、安全都是需要考虑的。

当然如果有大佬这些都能搞定的话,这是最好的方案了。

2.2 LeanCloud

早期有用这家的服务写过Demo,所以选型的时候也有考虑他家的服务,毕竟后期拓展到不同的平台没有障碍。

但是收费限制多,具体可以自行去查看。Pass

2.3 GameCenter

很早以前有研究过一下,就如其名苹果系统内部的一套游戏用户体系。

包含了用户、排行榜、成就点之类的比较基础的功能。

虽然很多游戏都有接入,但是存在感实在不高。

就我对GameCenter浅薄的了解来说,要拓展功能业务的话,只依靠CameCenter的话是很难支撑起来的,依旧需要另一套东西来承载。

所以Pass掉了。

2.4 iCloud

大家初步对iCloud的认识可能停留在可以备份同步照片文件的基础上。

这里建立用户体系依靠的是CloudKit,建议直接阅读官方文档,想知道的都有。

三、什么是CloudKit

Store structured app and user data in iCloud containers that all users of your app can share.

The CloudKit framework provides interfaces for moving data between your app and your iCloud containers. You use CloudKit to store your app’s existing data in the cloud so that the user can access it on multiple devices. You can also store data in a public area where all users can access it.

上面是官方文档中对CloudKit的说明,比较重要的一句 You can also store data in a public area where all users can access it.。

数据可共享是建立起用户体系的核心。

四、CloudKit存储数据的方式

进入DataBase,对核心的几块内容做一下说明:

4.1 基础数据单元:CKRecord

所有数据都是由CKRecord承载,存储在容器中的。

值得注意的是,只要用户开启啦iCloud及iCloudDrive服务。

支持的数据类型如下,这是官方注释里面的:

/// Acceptable value object classes are:
/// - `String`
/// - `Date`
/// - `Data`
/// - `Bool`
/// - `Int`
/// - `UInt`
/// - `Float`
/// - `Double`
/// - `[U]Int8 et al`
/// - `CKReference / CKRecord.Reference`
/// - `CKAsset`
/// - `CLLocation`
/// - `NSData`
/// - `NSDate`
/// - `NSNumber`
/// - `NSString`
/// - `Array` and/or `NSArray` containing objects of any of the types above
///
/// Any other classes will result in an exception with name `NSInvalidArgumentException`.
///
/// Field keys starting with `_` are reserved. Attempting to set a key prefixed with a `_` will result in an error.
///
/// Key names roughly match C variable name restrictions. They must begin with an ASCII letter and can contain ASCII letters and numbers and the underscore character.
/// The maximum key length is 255 characters.

CKRecord本身包含了一些基础字段比如创建者id、创建时间、修改时间、记录id等。

当然我们也可以自定义字段,读写起来就和使用字典类似。具体可以点进CKRecord文件查看,这里就不再多说了。

4.2 数据存储空间:Zone

这里就是三个不同访问权限的数据库,通过CKContainer访问。

a.Public

  • 默认所有用户可读,所有者可修改

  • 可设置权限,只能在后台进行调整,不可通过API修改

  • 开发者可以通过后台查看

  • 不占用所有者的iCloud储存空间

  • 占用App的iCloud存储空间

扫雷用的是这个数据库,因为包含了排行榜,需要所有用户都可以访问。

下面是相关的两段官方说明:

 *  Records in a public database
 *  - By default are world readable, owner writable.
 *  - Can be locked down by Roles, a process done in the Developer Portal, a web interface.  Roles are not present in the client API.
 *  - Are visible to the application developer via the Developer Portal.
 *  - Do not contribute to the owner's iCloud account storage quota.

This database is available regardless of whether the user’s device has an iCloud account. The contents of the public database are readable by all users of the app, and users have write access to the records, and other objects, they create. The public database’s contents are visible in the developer portal, where you can assign roles to users and restrict access as necessary. Data in the public database counts toward your app’s iCloud storage quota.

b.Private

  • 默认只有所有者可读写

  • 开发者在后台也无法访问

  • 占用所有者的iCloud存储空间

这个适合做一些私密性较强的应用,比如密码管理应用。

 *  Records in a private database
 *  - By default are only owner readable and owner writable.
 *  - Are not visible to the application developer via the Developer Portal.
 *  - Are counted towards the owner's iCloud account storage quota.

c.Shared

  • 只对通过CKShare授权的合作者可见

  • 开发者在后台也无法访问

  • 占用组织者的iCloud储存空间

这个没具体用过,先不深入探讨。

 *  Records in a shared database
 *  - Are available to share participants based on the permissions of the enclosing CKShare
 *  - Are not visible to the application developer via the Developer Portal.
 *  - Are counted towards the originating owner's iCloud account storage quota.

4.3 数据表结构:RecordTypes

User是默认就存在的一张表,无须自己创建。如果用户安装了你的应用,你去获取用户对象的时候CloudKit后台会自动生成一条记录。是不是很方便?

根据扫雷Elic的需求场景,我创建了这些表

  • User(default):用户

  • AvatarSpace:头像

  • EndLessRank:无尽模式排行榜

  • GameHistory:游戏记录

  • AppConfig:应用配置

  • ZenRank:“禅”模式排行榜

添加自定义字段

点进对应Type后就可以看到表结构了,上面一半是默认的数据结构。在下方点+可以添加自定义的字段,并选择数据类型。

需要注意的是:在测试环境下,新增的字段可以删除掉。一旦发布线上后,就不能删除了。只能新增。

4.4 数据索引:Indexs

  • QUERYABLE

    • 可查询

  • SORTABLE

    • 可排序

  • SEARCHABLE

    • 可搜索

根据需求进行设置,不设置的话会读不到数据的。

  • 比如无尽模式排行榜,需要根据时间和等级进行的排序,就把level & duration 设置了SORTABLE

效果:

五、QA

5.1 存在iCloud安全么?

虽然没有绝对的安全,但对比市面上的云存储服务。苹果的还是相对让我放心的。

关键是便宜啊!

5.2 要是用户抓包改数据呢?

我试过抓包,直接连不上容器了。感兴趣的可以尝试一下。

5.3 破解?

写到这里了我掏出了我的越狱机。。。说干就干,砸一个出来重签。

好家伙,直接崩了,挺安全的了吧?

当然我并没有深究能不能跳过系统这一步的验证,等萨尔有下了再来研究下。

我也还没做防Hook,有兴趣破解一下的也可以找我交流哈,十分欢迎。

5.4 访问速度

说不上非常快,但是够用。主要还是要合理设计表结构,要是在列表的数据结构里直接包含资源文件的话,那请求速度和用户体验就惨不忍睹了。

5.5 运维成本

几乎谈不上运维,咱也做不了什么。作为开发者能做的就是把应用逻辑和数据结构设计得合理一些。

一些基础的运维数据在后台也是可以看到的。

5.6 跨平台

只做iOS平台还好,要是以后想拓展到不同平台的话,是不是就用不成了?难道还要单独搞一套,甚至迁移用户?

具体没研究,看起来是可以做跨平台的。

5.7 容量

1PB够用不?

抱歉,我刚看到这个单位的第一时间没反应过来。

就是1024TB,真没想到。

不是一下子就有1P,随着你用户的量级来的。

开发者需要关心的只有Public database所占用的大小。

5.8 资源存储 CKAsset

CloudKit提供了CKAsset这个数据类型用来保存一些资源文件,可以放在CKRecord中进行保存。

看起来挺方便。

问题

如扫雷的排行榜功能,是需要显示头像的。

这里如果将头像直接添加为User表中,那么实际拉取用户的时候会很慢,因为这里会把图片资源一起带下来。而不是我们平时的Url的形式。

如果将图片传到图床上然后添加图片Url的字段也是ok的,但近年来感觉图床限制越来越多了,不方便使用。

这里我后面单独键了张表用来存头像资源,然后封装了一个加载、缓存CKAsset图片资源的工具,方便在排行版中使用。

七、总结

iCloud对于个人开发者来说是个好东西,可以低成本的构建用户体系。

只要发挥想象力,很多功能都是可以可以做的。

这里我用到的只是CloudKit的一部分,还有很多没用过。也许还存在很多的发掘空间。

八、参考

PreviousiCloudNext02.基于iCloud构建游戏内排行榜

Last updated 3 years ago

Was this helpful?

官方文档:

推荐苹果的官方文章,根据自身场景,选择合适的接入方案

1

想了解砸壳请移步:

放心,苹果贴心的提供了API

CloudKit
「Determining If CloudKit Is Right for Your App」
CloudKit控制面板
应用砸壳
CloudKit JS
Build Apps Using CloudKit
CloudKit
Designing apps using CloudKit.
Build Apps Using CloudKit
CloudKit JS
「Determining If CloudKit Is Right for Your App」
AppStore
AppStore
1
1
1
1
1
1
1
1
1
1