• iOS 开发小记 (六)


    这一篇是最近开发遇到的问题:

    一,善用Category 实现功能分块与重用

    UIViewController+UIImagePickController,实现了选择照片的功能。

    一个APP中选择照片的地方有很多,用category实现后,使用时每个地方就只需一行代码。

    至于选中后的回调,考虑了Block、delegate、notify,最终还是选择了notify。

    原因是category存属性的问题,不知道objc_setAssociatedObject 放进去block和delegate之后,ARC会发生怎样的变化。

    把选中的图片,用objc_setAssociatedObject存储,再发出notify,完成catgory实现的选择照片功能。

    2,图片浏览功能

    APP中需要浏览大图的地方很多,网上也有很多开源的第三方图片浏览器,在网上看了下,很多功能用不到,于是决定自己弄一个。

    功能:查看大图、放大缩小、有删除返回功能。

    最后实现的方案:

    新建一个controller,view上放置一个scrollview,scrollview上放置UIImageView。controller通过push 的形式调用,这个调用同样用category封装起来。

    几个精妙的地方:

    UIImageView放在scrollView里面后,要设置宽度、高度大于等于view(controller的view),图片显示是center;这样的好处是,当显示一个图片的时候,默认是放在view正中间,而且是图片的原大小。

    通过scrollview的zoom来实现放大缩小,直接在IB里面填入最大最小的倍数,就可以实现放大缩小。

    回调功能,删除的时候通过block回调删除方法。这里一开始采用的是notify,后来发现notify 的时候需要传参数,而且很多地方需要的参数都不一样,如果一一通过notify设置,会很复杂,于是改用block。

    三,OC的继承关系

    假设有类Parent,其中有方法methodA,里面有调用[self methodB];

    有类Child继承Parent,同时也重写methodA,methodB。

    这时候,就会出现问题:当Child调用methodA的时候,[super methodA]里面的[self methodB],调用的是Child的methodB。如果Child在methodA里面也调用了methodB,那么就会出现子methodB调用了两次,而parent的methodB没有调用到。

    实际开发的场景中,Parent是BaseViewController,Child是childViewController,methodA是viewdidload,methodB是customView。

    当child再viewdidload的函数中调用[super viewDidLoad] 和 [self customView]的时候,就会发生child的customView调用了两次,而parent的customView一次都没有调用到。

    解决方案:1,不要用一样的名字,child的改成customChildView;

    2,在child的customView中调用, [super customView]。同时child不要调用customView。

    (这个也是self和this指针的不同,如果是c++的话,在[super viewdidLoad]的函数中,调用的 customView应该是parent的customView。

    四,MVVM架构中的model与viewModel

    viewModel的生命周期随着controller,而model一般是整个app的生命周期。

    个人的开发习惯是,把model当成一个持久化数据库。network请求写在viewModel中,请求成功数据后,把数据update给model存起来。

    如果是遇到有很多viewModel 需要做同一个请求的,把请求放在model,而model直接向model请求。

    谈到网络请求,不得不说异步回调的问题。

    APP通过网络加载数据,必然伴随着加载完毕的回调。

    解决方案:

    1,RACObserve Viewmodel中的属性或者model的属性(不太建议对model中使用RACObserve)

    2,把请求封装在RACSignal里面,通过subscribeNext或者subscribeCompleted来进行回调。

    个人是两个一起用,1用来观察常变的值,通常是绑定一个viewModel和View时使用;

    2常用于用户操作后进行网络请求,回调后进行刷新,通常是reloadData的形式。

    五,Websocket的实用

    开发中遇到一个功能,需要用到服务器向客户端发送消息和保持长连接,同时又是一个http服务器,于是用到了websocket。

    地址是ws: 或者 wss:开头,wss需要证书,这次用的是ws:。

    用的是开源的SocketRocket,非常简单。使用时通过open连接服务器,如果失败,有fail。连接后收到消息有didRecive,断开连接有close。

    这个地方使用一个静态的viewModel来存储webSocket,保证app生命周期不会重复创建。把服务器返回来的status放置到viewModel,controller通过RACObserve来观察这些status。很完美实现了这个功能。

    六,删除功能与刷新功能

    一个APP框架要和需求、功能相适应,这样当产品提出一个合适的需求的时候,不至于手忙脚乱。

    最近做的这个APP,有一个功能是删除一个动态,这个动态在很多列表都会出现。这里可以采用监听者模式,删除的controller通过notify发出事件,而需要更新的controller自己监听这个事件,从而更新视图。

    同时,这个在列表中用左滑删除的功能(用户侧滑删除 -- 后台请求服务器删除 -- 删除返回 -- 内部删除数据 -- UI动态显示删除)  用ReactiveCocoa来实现非常方便。

    七,修改Pods第三方的代码

    功能需要修改第三方的代码,这个问题比较麻烦。

    1,通过podfile 把pods的路径加一个 => "github...." 定位到自己的github。

    2,工程导入形式, pod "../../test"   直接修改工程文件。

    3,复制代码到工程,直接修改。

    用的是第二种方法,一开始尝试直接在pods里面添加文件失败。在导入的工程修改完后,再运行一个pods Install。发现.xib没有导进来,应该是自己对pods的理解还不够深。

    八,测试

    单元测试:对本地一些自定义方法进行测试。

    UI测试:可以点录制,点击模拟器,然后生成UI测试代码(几乎不可用)。

    异步测试:

    1,自己实现。用runMode等待,轮询判断是否完成。

    2,execption。自带的异步测试功能。

    九,图片压缩

    从系统中选择照片后,图片都很大。压缩成宽高 不超过一定数目。

    UIGraphicsBeginImageContext 和 UIGraphicsGetImageFromCurrentImageContext , 配合UIImageJPEGRepresentation解决了问题。

    图片压缩:前面两个函数是缩,后面一个函数是压。

     

    十,视图跳转

    APP中经常有页面的跳转,遇到一个需求是在TabA的页面中,需要跳到TabB的页面,同时要push一个新的页面。

    一开的时候经常遇到log打出来的warning。思考了一下,发现是自己的操作太连贯了。

    当跳转TabB的时候,rootController还没显示,就开始push新的页面。

    解决方案:延迟0.1s进行push操作。

    (最后还有一个warning,是关于UISearchController的,在stackoverflow找到答案:在dealloc中把searchController的view removeFromeSuperView。)

     

     

    这次就先写十点吧,下次接着写,还有关于推送、IM聊天、地图、自动布局、发布测试等等。

  • 相关阅读:
    mysql改为mysqli几项注意
    修改链接服务器地址提高下载速度
    果然最适合码农的博客还是博客园
    mysql
    php 检测字符集
    Internet Download Manager has been registered with a fake Serial Number
    SVN图标不见了
    理解createTrackbar函数
    程序块结构
    数组初始化
  • 原文地址:https://www.cnblogs.com/loying/p/5113273.html
Copyright © 2020-2023  润新知