zoukankan      html  css  js  c++  java
  • iOS开发

    文/Azen(简书作者)
    原文链接:http://www.jianshu.com/p/6d5327111511
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

    正文


    一、关于横向模块开发

    团队型项目开发中,往往是根据功能模块进行开发任务分工的,如:商品模块、社交模块、设置模块等等,但是模块与模块之间,往往存在着一些横向的、通用的小功能,如:日历选择、出发地选择以及本文要谈到的搜索控制器。
    做横向模块和封装框架是一样一样的,最最重要的,是接口的设计。如何增强模块的通用性、减少侵入性,让该模块的使用者用的爽,在设计接口的时候需要充分考虑的。

    • 所谓通用性,是指能在多大程度上让别人用。做的最好的应该是苹果的UITableView。UITableView被称为“SB控件”,因为他不用知道自己展示什么内容,不用知道自己需要展示多少行,一切差异化的东西,全部通过代理来获取,所以他能拥有极其强大的通用性,所有想要做表格型展示的人都能用。

      • 然而,通用性也有它的弊端,就是会额外增加使用该控件的开发人员的工作量。
      • 假设项目中用到的所有tableView,都有相同的tableHeaderView、相同的numberOfSection & numberOfRow。如果还是用官方原生的UITableView,那我们每次使用,都需要写相同的、重复的代码来设置。
      • 这个时候我们就应该通过二次封装的方式,主动降低通用性,来减少重复代码。
      • 所以,不管是产品还是技术,没有绝对好的方案,只有在一定范围内,最适用的方案。技术就是权衡。
    • 所谓侵入性,是指别人用了你的控件,一旦不想继续用了,要花费的调整代码的精力会不会非常大。推荐杰哥的MJExtension,这个神一样的框架基本上做到了零侵入性。

    OK,装B完毕,咱们来看看这个“搜索控制器”的需求。

    二、需求

    1. 不同板块相同需求
      1.1 右上角的“搜索”按钮title,没输入关键词,展示“取消”;输入了关键词,展示“搜索”
      1.2 没搜索到结果,关键词高亮现实

      统一:搜索无结果.gif

      1.3 搜索有结果,展示搜索结果
      1.4 请求数据时,转菊花
    2. 不同板块不同需求
      2.1 板块一

      板块一:刚进来没点搜索.gif

      2.2 板块二

      板块二:刚进来没点搜索.gif

      2.3 板块三

      板块三:刚进来没点搜索.gif

    三、思考

    问题:

    • UI层面,不同的元素如何如何处理?
      • 如:搜索框的placeHolder,是让使用者传字符串进来?还是传type进来,我们根据传进来的type,在控制器内设置不同placeholder?
    • 数据层面,请求数据的逻辑在搜索控制器内部写死?还是让外部把搜索结果传进来?

    • 其他

      • 接口方法设计为类似MBProgressHUD的“+ (void)showXXXXX”型,还是设计成普通的返回一个实例控制器,让使用者决定何时弹出该控制器?

    结论

    • UI层面的差异比较简单明了,不涉及到后续一些东西,在控制器内部设置比较方便,采用传入type方式
    • 数据层面的东西(包括网络请求和本地持久化),逻辑不那么简单直接,而且不同板块应该请求哪些接口、本地存储存在什么地方,显然负责做该板块的同学比我们更清楚,所以最好的办法是把请求数据之类的事情交给外部去做,我们只要提供一个方法,让外部能把请求好的数据转换成字符串数组传进来,我们负责展示就好。
    • "+ (void)showXXX"方法用起来显然更爽,而且我们不会把过多的细节暴漏给该控制器的使用者,可以限制使用者的权限,防止使用者进行一些不恰当的操作导致崩溃(顺便插一句,相对于window来说,mac OS 就是这样做的。不用关心什么杀毒软件、硬盘分区之类的破事儿,写代码就安心写代码,做设计就安心做设计,系统方面的东西可以不用关心...这也是macOS用起来更爽的原因之一)

    思路整理

    现在,咱们想做这样一个搜索控制器:

    1. 足够封闭,不把搜索控制器对象返还给使用者
    2. 有足够的通用性,请求数据、数据存储等事情交给调用者处理,我们的搜索控制器只负责数据展示
      1.1 这意味着,我们需要告诉调用者(数据逆传):

      • 什么时候应该请求网络数据(点击了搜索按钮)
      • 什么时候应该清空本地缓存(点击了清除按钮)
      • 用户点击了哪条搜索结果

      1.2 调用者需要告诉我们(数据顺传):

      • 请求回来的数据是什么
    3. 请注意,通常我们进行数据顺传的方式,是拿到某个控制器,点出来他的属性,并进行赋值;而咱们想要的效果,是最大程度限制调用者的权限,不让调用者拿到咱们的搜索控制器(意味着不能点出来)的同时,最好限制调用者只能通过咱们给定的方法告诉咱们搜索结果(不让调用者拿到搜索控制器的属性)。

    怎么办?有什么办法能不返还给调用者一个对象,只返还给调用者一个方法?答案是block。
    数据逆传方面,个人也还是非常喜欢block。因为相比于代理,block能够让代码实现“高聚合、低耦合”,不用跳来跳去的找代码,维护起来更方便。
    (下一篇:一个复杂的首页的独白中,咱们会用到将代理和数据源方法,全都变成block的tableView)

    四、上代码吧

    这篇文章主要讲的,其实还是接口设计。所以代码就只贴头文件吧,源码丢在Github上了嗯(源码传送门)...如果觉得还有那么点小启发的话,记得顺手点星哦^_^

     1 文/Azen(简书作者)
     2 原文链接:http://www.jianshu.com/p/6d5327111511
     3 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
     4 
     5 //
     6 //  AZXSearchController.h
     7 //  AZXSearchControllerDemo
     8 //
     9 //  Created by Azen.Xu on 15/12/5.
    10 //  Copyright © 2015年 Azen.Xu. All rights reserved.
    11 //
    12 
    13 #import <UIKit/UIKit.h>
    14 
    15 typedef NS_ENUM(NSInteger, AZXSearchControllerType) //  搜索控制器类型
    16 {
    17     AZXSearchControllerTypePartOne = 1 << 0,   //  板块一
    18     AZXSearchControllerTypePartTwo = 1 << 1,   //  板块二
    19     AZXSearchControllerTypePartThree = 1 << 2  //  板块三
    20 };
    21 
    22 typedef NS_ENUM(NSInteger, AZXSearchFunctionType)   //  点击事件类型
    23 {
    24     AZXSearchFunctionTypeClear = 1 << 0,    //  点击了"清除搜索历史"按钮
    25     AZXSearchFunctionTypeSearch = 1 << 1,   //  点击了"搜索"按钮
    26     AZXSearchFunctionTypeSearchArray = 1 << 2,    //  点选了搜索结果列表
    27     AZXSearchFunctionTypeHotArray = 1 << 3,       //  点选了热门搜索列表
    28     AZXSearchFunctionTypeHistoryArray = 1 << 4,   //  点选了历史搜索列表
    29     AZXSearchFunctionTypeCreatTagForDiscover = 1 << 5   //  点选了创建标签
    30 };
    31 
    32 typedef void(^AZXSearchCallBack)(AZXSearchFunctionType selectedType , NSInteger selectedRowIndex , NSString *resultString); //  点击回调 参数一:点击事件类型 参数二:选中行号 参数三:选中文字
    33 typedef void(^AZXSearchSetNewArrayHandle)(NSArray *newArray);   //  通过此block传递搜索结果字符串数组
    34 
    35 
    36 @interface AZXSearchController : UIViewController
    37 
    38 /**
    39  *  根据type创建不同展示样式的搜索控制器,返回搜索结果handleArray
    40  *
    41  *  @param fromController 来源控制器
    42  *  @param hotArray       热门搜索stringArray
    43  *  @param hisArray       历史搜索stringArray
    44  *  @param type           样式枚举
    45  *  @param calBack        回调 - 数据请求成功后请为handleStringArray重新赋值
    46  *
    47  *  @return 搜索结果handelArray
    48  */
    49 + (AZXSearchSetNewArrayHandle)showSearchControllerFromController :(UIViewController *)fromController
    50                                                withHotModelArray :(NSArray *)hotArray
    51                                                    hisModelArray :(NSArray *)hisArray
    52                                                             type :(AZXSearchControllerType)type
    53                                                         callBack :(AZXSearchCallBack)callBack;
    54 
    55 @end
    View Code
  • 相关阅读:
    git添加本地项目到git
    GitLab项目迁移到Gerrit
    flask一些资料
    openldap sshkey & 用户自定义属性
    openldap复制
    openldap主机访问控制(基于用户组)
    openldap主机访问控制(基于ip)
    openldap自定义schema
    openldap主机访问控制(基于hostname)
    openldap权限sudo
  • 原文地址:https://www.cnblogs.com/fengmin/p/5318593.html
Copyright © 2011-2022 走看看