ios的widget的总结

前段时间在研究ios中的widget的实现。发现其中有不少的坑~现在widget的开发也告一段落了。那么把这些widget的坑拿出来分享下吧~

首先来说下widget,该功能是从ios8开始的。在通知栏下拉下来的页面中有“今天”和“通知”两个tab,其中widget的内容都是在“今天”里面。之前我也没怎么关注过“今天”里面的内容。自从要在自己的app中加入widget之后,发现其实很多的app都带有widget的功能,只不过大家不知道而已。比如微博,uc什么的都是有的,而且体验也还不赖。

在ios8的介绍中,widget其实又叫today,它是归属于app Extension里面的一项。主要widget这个词比较通用,在其他的设备上也是有widget这个东东,如果说today不要说非ios开发,就算是ios开发,也会愣住。那么下面都直接用widget吧。至于如何创建widget以及widget的一些基本的开发,我这边就不说了。这个只要一谷歌就会有大批量的文章出现,而且不用纠结选取哪一篇,因为基本上都是一样的=,=。
ok,那么省略过中间的无数关于widget的基础开发的等等。下面我就说下我写这个的中心思想吧。也就是widget的多奇葩,以及那些一不小心就会坑死你的坑。(当然将下面的前提是,我认为看官们已经了解了接触过ios上的widget或者说已经着手开始做widget了)

首先说下关于调试方面的:调试widget还是比较蛋疼的,因为经常性的你不管测试单个的widget,还是整个应用,widget部分的内容经常会不更新,也许我上面那句话不是很好理解,就是说你虽然在widget那边写了先的逻辑,但是他执行的仍旧是你修改前的那份代码逻辑。所以很多时候需要做的就是“退到桌面,长按app删除,再来!”。而我自己在调试的时候,一般是会选择写测试数据,调试单个的widget,等全部ok之后,直接打release的包来看测试,然后一般我比较相信打log的测试方法,所以经常性的出问题了会打log。当然这也做的前提是widget部分的代码逻辑并不是很复杂。

接下来要说的是关于widget处的ui以及交互上的问题:对于widget,官方是这么说的,一般用来呈现一些比较简单的,交互性不强的内容。但是对于官方的这个说法我只能“呵呵”。因为我们基本上对于这种东西,所用的思路都是和官方对着干的。大家想想app的启动页就可以了。所以呢,在widget上免不了会绑定各种点击事件。首先要说的是点击区域的问题。经过切身实际的体验发现,一般的按钮不过是图片的按钮,只靠图片大小的那么点点击区域肯定是不够的。所以我们需要扩大点击区域。恩!扩大点击区域设置UIEdgeInsets就可以了,这种方法在我们之前的开发中,屡试不爽,还特别的优雅。但是,发现在widget中并不管用。而且如果你创建一个控件,空设置他的frame,但是不设置里面的内容,或者背景色什么的,那么这个控件就算绑定了事件,也是响应不了的。具体的原因是什么,我没有深究。也许是widget这边的一个bug也许是人家故意设计的feature也说不定。不过,如果设置一张图的话,就算是透明的图,还是可以响应事件的。那么久有方法了,可以设置一张边上是透明的,中间有实际内容的图,就可以解决这个问题了。还有一点,其实和上面说的差不多,就是如果你在一个控件上加了手势判断,如果其中没有被内容(图片,文字)覆盖到的地方,就没方法响应。之前我看到有的博客说-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event可以用这个方法来响应,但是实际用了之后还是不行,也许可以用下一张透明的图来做估计是可行的,具体我是还没有实际运用,但是其实和上面所说的效果是一样的。

再说一点是关于内存的:也许对于ios开发来说,对于内存这块的考虑,并不需要像安卓开发那么考虑的这么多,然而在widget这一块,却会让我们吃到苦头。具体关于widget的内存的分配什么的我是没有做过具体的研究,我只是通过了一个实际的案例发现的。再拿我之前的widget项目来说吧。由于我们的widget中需要加入图片。然后加载了一张200k+的图片,结果整个widget就奔溃了(当然我这边说的widget只是我们app对于的widget插件,并非是设备的整个widget系统),后来换了比较小的图,就没有发生过这样的问题。不过我有一点怀疑的是widget这边的内存,好像对于图片这块的管理或者说分配会比较紧,因为只有在使用大图片的时候才会出现这样的问题。

还要讲的一点是关于widget的更新的:这个更细的问题之前也是困扰了我好久,查资料也没查出什么结果来,所以我强烈的觉得这个是widget的bug,而不是feature。具体情况是什么呢,就是说你app的版本更新,其中widget的部分也做了更新,但是这时候你会发现你的widget并没有和app一样更新完,再重新打开就变成了最新版本。只有设备重启或者说删除app在重新安装才会更新,就算是widget移除在加入也是没有用的,我认为原因是整个widget系统的生命周期只有在关闭设备才会结束,而单个的widget也是在widget系统被销毁的时候或者说app删除的时候才会被销毁。其实我可以举一个栗子,对于某款app的一个widget应用,它非常的强盗,只要进入widget的页面就一直在跑循环,获取ssid的最新状态,我把这个widget从widget的显示处移除了,但是它还是一直在跑循环,只有重启设备之后才可以。所以我才会有上述的推断。甚至之前我还考虑过是不是说我把自己的widget搞crash了,它就可以重新加载最新的代码了,但是正如大家所知的,如果widget creash了那么让就不会再重新加载,除非重启widget,我觉得这一点苹果应该是在保护其他widget的利益吧。好了所以这一点,对于版本更新来说还是比较头疼的,毕竟现在重启手机的频率并不高。为了完美的解决这个问题,只能等苹果修复这个bug了。但是感觉希望渺茫,因为我走遍了各大论坛,发现对于这个问题的描述并不多,而且个人感觉苹果对于widget的热情也不高涨。

最后要说一点的是关于widget的兼容性方便的:众所周知widget是在发布ios8的时候提出的,那么当然widget最低支持的版本是ios8,但是这并不妨碍你的app最低的支持版本小于ios8。这样只是说小于ios8的用户享受不到widget那边分的插件而已。并不会造成ios8以下的用户闪退什么的。还有一点在app和widget之间肯定有数据的通信,或者说代码的重用什么的。在ios8的时候提出了动态链接库,当时我也很开心,把两边都需要用到的部分逻辑代码放到了一个framework中。结果在提交的时候发现瞎了,因为动态链接库这个最低支持的版本也是ios8!那么,那么就是说小于ios8的用户也没办法使用到这个framework,但是里面有部分逻辑代码是非widget也需要用到的(当然这个是我们的widget开发时候遇到的具体问题),又由于这部分的代码需要经常性改掉(比如说版本号什么的),这样也不方便做成静态的库什么的,所以最后还是用了比较low的方法,通过userdefault来传递。所以有时候在使用新技术的时候需要考虑到在低版本上会出现什么情况。

好了,以上的就是我在开发widget的时候遇到的一些问题以及一些想法吧算是。个人感觉widget还是蛮有用的。虽然之前一直没有打开设备上的widget,但是研究之后发现,有时候还是蛮方便的。只不过有些app的widget做的实在是不管恭维,还是说之前提到过的那个跑循环获取ssid的那个好了。它到好是直接打log的,所以我能够在控制台看到,如果把log隐藏掉了,一时半会儿我还真是不知道他做了这么强盗的事情。会出现这种的原因我觉得有两点:一个是由于这个widget可以说和app是相对来说比较分离的,意思说你widget干什么事情不管我app,就算crash了也和我app没关系,所以就乱来,还有一点就是很多人不知道这个widget这个功能,所以开发人员就更加乱来了,抱着反正没人用的心态在那边瞎搞。所以导致。。。

虽然ios上的widget的灵活度或者说可方法程度还不能和安卓的widget的相比较,但是我还是觉得这个widget还是很不错的,希望我能够有勇气打开更多app的widget~~~~