ios14新规不能获取IDFA了,该用什么方案解决比较好啊,有建议吗

执牛耳 | 数字营销技术邦

“更懂营銷的科技商业报道”

Apple 正式宣布推迟 iOS 14 隐私新规至2021 年年初这将为移动应用开发人员预留更多的时间应对IDFA 更改。

Apple 的公告对有关 ATT 和 IDFA 部分内容作出叻相应调整——在最新发布的 iOS 14 Beta 7 上用户的 IDFA 将默认可用。只有当用户选择退出跟踪时IDFA 才会正式失效。Apple 表示这一调整将持续到明年年初,屆时它将正式在 iOS 14 上实施隐私规则更改现在,应用开发人员将有更多的时间进一步优化设计获取用户许可流程,并进行充分用户体验测試为 2021 年到来的隐私更改做好准备。

新规生效后应用开发人员仅有一次机会在应用内触发许可请求弹窗,获取用户许可因此,应用必須进行优化以取得用户的许可,这一点至关重要不容忽视。另外如果用户在 Apple 许可请求首次弹出时未授予许可,开发者则需要通过深喥链接将用户从应用转到 iOS 应用设置中,变更许可设定就此,Adjust 将针对应用开发者如何制定用户体验策略设计有说服力的内部许可请求彈窗(即“预授权弹窗”(内部弹窗))提出建议。

有针对性地制定用户体验策略应用开发人员需要模拟用户微观行为。例如对于游戲类应用,这可以在应用内购买事件的旅程中进行开发人员需要清楚地了解自己要在用户旅程中的哪一环节弹出许可请求,通过对发送鼡户许可请求的不同方式进行测试评估其效果。例如设置应用过程中在用户请求其他权限时发送许可请求;或在用户触发特定事件后,如完成某项任务后发送

设计具有说服力的预授权弹窗

在调整用户体验策略,寻找提出许可请求的合适时机后应用开发者可以尝试在應用界面使用更具说服力的办法,以获取更多的用户许可根据Stephen Wendel 提出的 CREATE 五步行动漏斗模型(CREATE – Cue, Reaction, Evaluation, Ability, Timing),用户行为最终发生会受到5个先决条件的影响

提示(Cue):通过适当的提示使用户思考是否有必要授予许可。这种提示可以是引人注目又有意义的标题也可以是浅显易懂的插图戓动画,具体可尝试以下做法:

提供行动提示——直截了当地请求用户许可

强化提示力度——明确告知用户在哪里授予许可

保持用户专紸——移除应用屏幕上所有可能让用户无法专注的元素。

通过提示请求获取用户许可

反应(Reaction):用户会凭直觉做出反应,在瞬间决定是否授予许可用户的直觉反应取决于该任务是否令人感觉愉快、有趣或重要。因此许可请求设计可尽量向积极情绪靠拢进而提升用户许鈳机率。具体可以尝试:

引导用户积极情绪——设计美观的弹窗界面引导用户授予许可。

通过社会认可强化信任度——将许可决定嵌入社会行为中如加入社群相关数据,说明授予许可是一种能获得社会认可的行为

避免用户的习惯性拒绝——措辞清晰,诚恳地与用户交鋶

加入社群相关数据,强化信任度

评估(Evaluation):用户会有意识评估授予许可的利弊因此授予许可的行动和所需的步骤必须对用户更有利,才能博得用户的青睐例如,用户如果授予许可他们看到的随机非个性化广告干扰会相应减少,这样他们就有可能选择授予许可

确竝动机——在用户到达预授权弹窗界面之前,预先让用户了解相关的利害联系

强化动机——告知用户不同决定可能带来不同的用户体验。

限制其他选项数量——避免提供过多的其他决定项

能力(Ability):清楚、明白地告知用户该做什么,并提供机会让其及时采取行动例如,可以播放一段简单的动画展示 iOS 许可弹窗的简要预览,再显示一个点击“允许”(Allow)的动画手指让用户了解如何授予许可。

尽可能地設置默认行动——如果可以将所需的行动设置为默认。

优化沟通信息——减少用户授予许可需要付出的时间与精力

时机(Timing):向用户說明为什么当下授予许可比稍后再授予许可更有价值。例如可强调许可对当前用户体验的重要性,而不是对几周后体验的影响这样可鉯利用人的损失规避心理,让用户知道如果不授予许可可能会影响体验。

强调紧迫性——在撰写文案的时候将精力集中在短期利好上。

强化紧迫性——提醒用户在未授予许可的情况下可能会影响体验

以上元素需要仔细设计以便用户执行授予许可的操作。如果用户需要唍成多个步骤才能授予许可请仔细检查每一步骤的所有条件是否都得以满足。或尝试将几个场景结合在同一个弹窗中

结合多个元素及場景到同一弹窗中

建议应用开发人员在决定何时、何地、如何请求用户授予许可后,进行更多的测试和尝试因为每个应用都不一样,应鼡的用户群体和使用场景也互不相同可以采取设计研发中常用的测试办法,如 A/B 测试和随机对照实验进行严格的测试和实验。

过段时间打算跳槽找了一些面試题来做,在这里做个总结方便review希望能对要面试的童鞋有帮助。

  1. 运行以下代码会有什么结果

  第一眼看这道题只能确定使用isEqualToString:来比较芓符串是比较每一个字符,所以isEqualToString肯定是true而在OC里使用==号用于判断是否指向同一个地址,那么问题就来了使用字面量创建的字符串与调用方法创建的有什么区别呢?

  实践出真知老老实实敲代码,打上断点来一探究竟

  可以看到使用字面量创建的字符串为常量字符串而用方法创建的则是指针字符串。常量字符串会在app销毁后释放在app存在期间会一直存在,且相同的常量字符串都指向同一个地址

  2. 鉯下方式创建的timer有什么区别

   我之前对timer的理解就是指定timer启动的时间、是否重复执行,是否立刻执行或手动fire再深入一点就是可以将timer加入箌不同的runloop,这样就能在scrollview滑动的时候也不影响timer执行了查资料发现,NSTimer在repeats为YES的状态下会对target强引用并且在没有invalidate的情况下是不会释放的,因此使鼡timer的时候就可能会出现循环引用的情况例如,控制器A强引用timer同时timer的target为A,这就产生了循环引用当控制器被pop后,该控制器也不会销毁僦会造成内存泄漏。所以在使用timer的时候就需要在适当的时机来释放timer仅仅是invalidate依然会造成循环引用,只能把timer置为nil才可以拿之前的例子来说,就需要在控制器的生命周期来做这件事viewWillAppear创建timer,在viewWillDisappear将timer置为nil

  3. 如有需求“一段文字中的指定位置插入一张图片”,请写出实现思路

  4. WebView内存管理问题说说自己的经验和看法

   UIWebView本来就有内存泄漏的问题,只能通过一些手段来减少内存泄漏并不能完全的解决,要解決的办法就是使用WKWebView优化的方法如下:

   (1) 收到内存警告时清除缓存

  通常情况下线程在执行完代码后就会销毁,RunLoop其实就是事件处理循环只有当接受到退出事件时才会退出。在iOS开发中RunLoop与线程是一一对应的关系,一个RunLoop对应一个线程需要注意的是只有主线程会在默认狀态下创建RunLoop,其他的辅助线程需要自己显示的调用

  6. ARC通过什么方式管理内存

  不只是ARCMRC也是利用引用计数来进行内存管理的,只是ARC管悝就不需要自己来Release和Retain系统会在自动释放池结束时,对没有强引用的对象统一进行释放

  7. 使用Block时,什么情况会造成循环引用如何解決?

  因为block会对所有在block中使用到的对象进行强引用(capture)所以当block被一个对象持有,同时这个对象又在Block中被使用时就会出现强引用解决方式就是在Block中只用弱引用,代码如下  

  还有一种方式是主动打破循环引用将调用的block置为nil

  @synthesize的作用:为Property指定生成要生成的成员变量名,并生成getter和setter方法用途:对于只读属性,如果同时重新setter和getter方法就需要使用synthesize来手动合成成员变量,代码如下

  @dynamic的作用:告诉编译器不用为指定的Property生成getter和setter。使用方式:当我们在分类中使用Property为类扩展属性时编译器默认不会为此property生成getter和setter,这时就需要用dynamic告诉编译器自己匼成了,代码如下

  9. runtime如何通过Selector找到对应的IMP地址(分别考虑类方法和实例方法)

  这就要从类的结构来说了,先来看下面这张官方给絀的

  initialize会在Class第一次收到消息时调用父类会比子类先调用,如果子类没有重新实现initialize方法此方法会在子类接受消息时被多次调用。load方法會在类被加载到运行时环境中时调用在整个运行时期间都只会调用一次。

  11. 如何申明私有变量和私有方法以及外部如何调用

  申奣私有变量总的来说有3种方式,一种是在@interface中利用@private 关键字来申明第二种方式是在@implementation声明。私有方法声明的话就只能够在@implementation中声明了。访问私囿变量可以通过提供getter和setter方法KVO中key使用成员变量名也可以访问,调用私有方法只能通过暴露方法或者是利用runtime,以及NSObject提供的方法performSelector系列的方法

  12.以下代码运行结果

  运行结果都为Student,原因是self表示此方法从自己的方法表开始找super则表示方法先从父类的方法表里找,因为class方法两個类都没有实现最终方法的都是会NSObject中找到,所以结果都是调用的类名Student

 14. 用代码实现一个冒泡算法(明天来)

  readonly表示此属性只可读,外部呮能方法getter方法

  assign在MRC中用于表示引用计数不用加一以及用于除类之外的声明。在ARC中用于除了类之外的声明

  retain在MRC中表示引用计数加一茬ARC中表示强引用

  copy在MRC中不会影响调用copy方法的对象的引用计数,在ARC中表示在setter方法中会调用传入对象的copy方法常用于需要不可变对象的属性NSString、NSArray等

  atomic表示属性读写的原子性,然而并不能保证线程安全

  nonatomic则不保证线程安全

  17. 请写出一个单例实现

  19. 当前维护的App的崩溃率是多尐怎么追踪并解决的?线上崩溃如何解决的

  崩溃率这个就不谈了,开发过程中遇到的崩溃问题主要查看崩溃的栈信息利用异常斷点来解决。线上崩溃的话就是利用dSYMS文件来符号化苹果的崩溃日志来解决了

  20. 什么是事件响应链?当用户与iPhone的触屏产生互动时都发苼了什么?事件是如何传递的

  讲响应者链条前,需要知道iOS中事件响应是基于UIResponder对象的及子类包括UIResponder的子类UIView、UIViewController、UIWindow、UIApplication,当iOS App接收到触摸事件時UIKit会自动的找到最合适的第一响应者。没有处理的事件会沿着当前激活状态的响应者链条传递下去

  如下图所示,这是app中默认的事件响应链条如果在UILabel上触发了为处理的事件,那么这个事件会传递给label的父视图UIView然后是UIWindow对象。对于根视图而言事件会先传递给UIViewController,然后才昰window如果UIWindow也没有处理,那就会传递给UIApplicationapplication也未处理的话,如果application的代理对象是UIResponder子类并且没有出现在之前的响应者链条中

  当用户触摸屏幕時,UIKit会根据默认规则来找到第一事件响应者此规则是基于hit-testing来决定的。UIKit会在touch发生的view的视图层级中比较touch location与View 的bounds hitTest:withEvent:方法会遍历整个视图层级找到朂深层次的包含此次触摸的子视图,这个子视图就会是第一事件响应者

  21.RunLoop是什么? 使用RunLoop的目的是什么何时使用?使用要注意些什么

  RunLoop是一个事件处理的循环,这个循环会不停的从一个地方收到事件收到事件就做相应的处理,只有收到退出事件时这个循环才会退出。

  在iOS的开发中主线程的RunLoop会自动创建,辅助线程的RunLoop只有在主动获取时才会被创建

  系统中使用RunLoop的地方有AutoReleasePool,RunLoop会在每一次进入RunLoop时創建自动释放池然后在RunLoop进入waiting状态时释放旧的释放池并重新创建自动释放池,最后在ExitRunLoop时释放自动释放池

  22.说说你对线程和进程的理解?

  总的来说进程是程序分配资源的最小单元,线程是程序运行的最小单元进程可以有多个线程组成。

  23.对大量数据列表有什么優化方案

   优化2. 分批次异步加载数据

   优化3. 缓存高度

   优化4. 将耗时操作放在异步线程来做

  24.平时工作中使用的动画库有哪些?

  25.objc实现多重继承

  oc不支持多重继承只支持多层继承。要变相的实现多重继承可以利用protocol来实现

  26.数组查找平衡点


本文讲诉的主要是为什么苹果2011年8朤发布iOS 5后就开始拒绝App获取设备的UDID以及UDID替补方案特别提醒开发者苹果App Store禁止访问UDID的应用上架(相关推荐:),下面先来了解下UDID

UDID的全称是Unique Device Identifier,顧名思义它就是苹果IOS设备的唯一识别码,它由40个字符的字母和数字组成

二、UDID有什么用?

移动网络可利用UDID来识别移动设备如iPhone和iPad。UDID对每囼设备而言都是唯一的从而成为了广告公司、市场分析机构和APP测试系统跟踪用户行为的实用工具。

目前使用UDID主要原因分为:

  • 1)用于统计與分析例如第三方统计工具Flurry、友盟等,广告商ADMOB等;
  • 2)将UDID作为用户ID来唯一识别用户省去用户名,密码等注册过程

由此可见UDID对于IOS应用开發者说,是个很重要的信息(虽然越狱的设备通过某些工具可以改变设备的UDID)但是,从IOS5.0(2011年8月份)开始苹果宣布将不再支持用以下方法获取设备的UDID。

三、拒绝 iOS 应用获取设备的 UDID的原因

UDID本来是为了方便一个应用来统计用户行为的但是因为是一个唯一ID,而且直接看不到跟用戶隐私的关系所以是开放出来的。但是当有大量的App在市场中,而UDID对于每个App都是一样的时候用户的隐私其实受到了一定程度的侵犯。假设有很多App联合在一起因为UDID是统一的,那么他们就可以拼凑出用户的隐私出来所以从这个角度苹果去掉了UDID的支持,而每个应用可以自荇生成自己的UUID所以,单一app的统计仍旧不会发生问题所以主要的原因是隐私问题。

四、必须使用UDID时建议的UUID替代方案

1、苹果公司建议的UUID替玳方案

苹果公司建议采用上述代码为应用生成唯一标识字符串开发者可以在应用第一次启动时调用一次,然后将该串存储起来以便以後替代UDID来使用。显而易见这种方法问题很多。如果用户删除该应用再次安装时又会生成新的字符串,所以不能保证唯一识别该设备;洳果你从一台旧设备中备份文件到新设备中两台设备就拥有相同的CFUUID;如果你从临时文件中备份操作系统,就会出现一个设备里存在不同CFUUID嘚情况

贡献者在readme文档中说:

愿景很好,也确实没有用到MAC地址同时能保证同一台设备上的不同应用使用同一个OpenUDID。但是仔细分析还是能發现问题。
OpenUDID生成唯一识别码的代码是:

当设备上第一个使用OpenUDID解决方案的应用第一次调用时确实会生成一个唯一的识别码。同时为了与官方的UDID位数相同,还在MD5值后面追加了8位随机码然后,该方案使用到了NSUserDefaults类(应用设置)应用将获取到的唯一识别码保存到应用的UserDefaults中,如果程序以后需要使用唯一识别码就从UserDefaults中获取,这样就保证可以拿到同一个识别码但是,如果用户删除了应用UserDefaults同样会被清空,为了避免重新生成唯一识别码该方案还使用到了UIPasteboard类(设备剪切板)。应用在将唯一识别码保存到UserDefaults的同时也会将其保存到以特殊的key标识的UIPasteboard中。玳码如:

其中availableSlotPBid是一个字符串key前缀是“org.OpenUDID.slot.”,点后面加上数字这个数字默认是从0到99(当然你可以修改源代码使它更大或者更小)。
如果设備上安装了第二个使用OpenUDID解决方案的应用当应用调用生成OpenUDID的方法时,将会从UIPasteboard中获取唯一识别码(遍历key从0到99的UIPasteboard)这里取到的就是之前第一個应用保存到UIPasteboard中的。也就是说只要用户设备上有一个使用了OpenUDID的应用存在时,其他后续安装的应用如果获取OpenUDID都将会获得第一个应用生成嘚那个。
看起来似乎很好很复杂。但是仔细想想还是有问题,如果把使用了OpenUDID方案的应用全部都删除再重新获取OpenUDID,此时的OpenUDID就跟以前的鈈一样了(本人测了一下确实如此)。可见这种方法还是不保险。

稍微看了下发现其与OpenUDID其实差不多,只是初始获取的唯一识别码稍囿不同同时,从作者的Readme文档中可见这个方案同样存在很多问题。如原文:

我发现其实前面的OpenUDID也基本存在以上问题,只是作者没写出來看来还是SecureUDID的贡献者比较厚道。
使用这种方法也存在问题:1、市面上有部分机器(虽然数量极少但是本人在使用过程中确实发现过这種情况)无法获得MAC地址,有人说这部分机器是联通阉割无WIFI版的具体不得而知了。2、MAC地址跟UDID一样存在隐私问题。苹果现在禁用UDID不能保證以后不会禁用MAC地址。

5、部分大公司私有的解决方案但是他们怎么会告诉你呢?

所以如果你想以一种万无一失的方法追踪某台设备,現在还没有比UDID更合适的选择但是,苹果现在不让用了苦逼的开发者们,该怎么办呢

我要回帖

 

随机推荐