开发问题笔记(三)

2019-02-25  本文已影响0人  Kevin_wzx

目录

1.weakSelf与strongSelf的使用
2.copy与@property
3.工程添加icon到Images.xcassets
4.cell上的按钮的回调小结
5.动态cell的封装
6.表格视图Header(Footer)View的使用注意点
7.如下解析信息
8.接口处理
9.jason格式与表单form形式
10.模型嵌套模型的传参数形式
11.字符串相等的坑
12.身份证的*处理
13.创建控件的注意点
14.界面间传值保存
15.获取图片的自身大小
16.设置网页的字体大小的方法
17.数组去重
18.MVC的各个部分都有哪些技术来实现?
19.内存溢出和内存泄露?
20.获取项目根路径,并在其下创建一个名称为userData的目录?
21.几个变量的区别
22.如何从网络获取数据?
23.@class作用
24.链表和数组的区别在哪里?
25.如何优化代码?
26.回调机制
27.const和static和extern c
28.开发 常用工具(打电话、发短信、发邮件)
29.浅谈webView的JS一种用法.(去掉web显示页的广告)
30.App上传被拒绝之 “iOS 非公开API prefs:root=Privacy”

1.weakSelf与strongSelf的使用

#define WEAKSELF __weak typeof(self) weakSelf = self;

#define STRONGSELF __strong typeof(weakSelf) strongSelf = weakSelf;

在block中为了避免循环引用,常常会用weakSelf弱引用来代替self;但是如果需要多次使用(超过一次)weakSelf就改成用strongSelf,注意使用strongSelf时同时写上WEAKSELF与STRONGSELF,因为strongSelf在weakSelf基础上封装。相关链接:https://www.jianshu.com/p/a5dd014edb13

例子:

屏幕快照 2017-12-26 上午10.25.08.png

2.copy与@property

1.NSString、NSAttributedString、NSArray、NSDictionary、block:用copy
2.(字符串、数组..)带NSMutable:用strong
http://blog.csdn.net/Maybeyourdad/article/details/48469917

例子:NSMutableArray不能用copy,因为copy的那一份是不可变的,即copy的那份变成NSArray,原来那份不变。而我们是对copy的那份进行操作,所以原来的NSMutable的一些方法用不了,可能操作时会奔溃

3.工程添加icon到Images.xcassets

屏幕快照 2018-01-03 下午5.34.51.png

1.将切好的图标2X 3X一起选中拖进去就ok了
2.先将2X拖进去,然后再把3X拖到右上边Universal的3x标记的位置,注意不要拖到之前2X(左边图标库的地方),会认为是两张不一样的图,会有问题

屏幕快照 2018-01-03 上午11.07.45.png 屏幕快照 2018-01-03 上午11.09.38.png

4.cell上的按钮的回调小结

1.系统cell上添加按钮

在控制器页面创建的系统cell上直接加按钮,然后直接给按钮添加事件就OK了

2.在自定义的cell上添加按钮
屏幕快照 2018-01-31 下午3.24.05.png 屏幕快照 2018-01-31 下午3.24.52.png

调用block:

屏幕快照 2018-01-31 下午3.25.17.png

备注:写法二如下:

屏幕快照 2018-01-31 下午3.38.34.png 屏幕快照 2018-01-31 下午3.38.56.png 屏幕快照 2018-01-31 下午3.39.42.png 屏幕快照 2018-01-31 下午3.41.22.png

5.动态cell的封装

需求:校园直通车的车票列表(类似于做公交车,有途经点),根据实际选择的上下车来动态展示;如果有途经地就展示途径,没有就不展示,上下车地点间布局不同,下面有展位就显示,没有就不展示。思路是:通过模型来控制,封装在cell中去处理,外部控制器调用就好

屏幕快照 2018-01-19 下午4.38.36.png

1.在封装的cell中,更新布局及赋值的地方进行判断处理,如下:

屏幕快照 2018-01-20 下午3.01.08.png 屏幕快照 2018-01-20 下午3.01.59.png 屏幕快照 2018-01-20 下午3.03.43.png

self.campusBusTicketModel.isViaPlace == YES表示有途经地点,然后重新布局:

屏幕快照 2018-01-20 下午3.04.35.png

通过模型里的provider是否有值来判断有无展位,没有就隐藏相应的控件:

屏幕快照 2018-01-20 下午3.05.37.png

把以上的更新方法放在重写模型方法里,这样外边更新数据时就相应处理:

屏幕快照 2018-01-20 下午3.06.03.png

模型及关联如下:

屏幕快照 2018-01-20 下午3.07.03.png 屏幕快照 2018-01-20 下午3.07.20.png 屏幕快照 2018-01-20 下午3.07.45.png

控制器中数据请求+cell数据映射+cell高度控制分别如下图:

屏幕快照 2018-01-20 下午3.10.23.png 屏幕快照 2018-01-20 下午3.11.26.png 屏幕快照 2018-01-20 下午2.47.45.png

6.表格视图Header(Footer)View的使用注意点

1.在表格的Header和Footer地方可以展示请求回来的数据,可以正常刷新的
2.在用Header或者Footer的同时要进行自定义布局时,return返回的那个大view不需要给frame,创建即可,其他里面的子控件正常布局就ok;在设置高度的方法里如heightForHeaderInSection设置高度即可;如果直接在里面设置可能会出错

屏幕快照 2018-01-12 下午3.14.59.png 屏幕快照 2018-01-31 下午2.57.04.png 屏幕快照 2018-01-31 下午2.57.19.png

7.如下解析信息

出现<object returned empty description>这种原因是打断点调试的时候用的po输出的,字面意思就是返回了空的对象,如果要避免这种情况,用NSLog输出要测试的字符串就行了

屏幕快照 2018-01-12 下午1.08.25.png

8.接口处理

1.请求数据返回404,是后台接口问题,可能原因是接口还没有弄好,也可能是接口已经弄好了,还没有部署上去。404错误如下:

屏幕快照 2018-01-19 下午5.10.31.png

9.jason格式与表单form形式

如果后台的接口处理的是jason格式的话需要加上:contentType = @"application/json";
jsonBody = YES; 如果是表单形式的话就不需要加,普通的默认不写

屏幕快照 2018-01-16 下午7.44.27.png 屏幕快照 2018-01-31 下午2.30.34.png

10.模型嵌套模型的传参数形式

最外面是层模型,里面包含有passengers模型,passengers里面还包含有remark模型,里面有grade、otherInfo等字段,传参数的时候直接将remark模型嵌套在passengers里面,然后直接映射

屏幕快照 2018-01-17 上午10.53.22.png 屏幕快照 2018-01-17 上午11.13.50.png 屏幕快照 2018-01-31 下午2.14.01.png 屏幕快照 2018-01-31 下午2.15.15.png

传参数映射如下,注意需要加上mj的mj_keyValues方法;否则会转化错误造成程序奔溃

屏幕快照 2018-01-31 下午2.13.28.png

11.字符串相等的坑

isEqualToString 和 == 的区别,前面是正确的字符串比较相等方法,如:if([strA isEqualToString:strB]);后面的等号对比如:if ( strA == strB),这个strA, strB 是指针, 虽然字符串的内容是相同的, 但指向字符串的指针肯定是不同的,所以也不能相同啊。(为了更好地理解字符串,需要弄清楚指针的概念,内存的分配。 )

屏幕快照 2018-01-18 下午5.23.43.png 屏幕快照 2018-01-18 下午5.24.28.png 屏幕快照 2018-01-18 下午5.15.12.png 屏幕快照 2018-01-18 下午5.15.00.png

12.身份证的*处理

对身份证号码进行加*号处理,身份证号码主要有15、17、18三种

屏幕快照 2018-01-19 下午2.30.57.png

13.创建控件的注意点

少写了init造成初始化问题,造成野指针。运行程序崩溃

屏幕快照 2017-12-29 下午5.16.45.png

14.界面间传值保存

需求:点击添加备注按钮跳转到备注信息界面,填好以后,按确认按钮保存传回之前的控制器;然后再进入时还是保留之前所填的信息,不要清除

屏幕快照 2018-01-23 下午7.42.52.png 屏幕快照 2018-01-23 下午7.43.18.png 屏幕快照 2018-01-23 下午3.51.44.png 屏幕快照 2018-01-23 下午4.15.59.png 屏幕快照 2018-01-23 下午4.19.48.png 屏幕快照 2018-01-23 下午4.14.17.png

15.获取图片的自身大小

16.设置网页的字体大小的方法

BOOL _fontOn;
- (void)rightButtonClicked:(UIButton *) sender{
    _fontOn = !_fontOn;
    if (_fontOn) {
        [sender setImage:[UIImage imageNamed:@"font_off"] forState:UIControlStateNormal];
        //改变webview的字体
        [_detailWebView stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '70%'"];
        
    }
    else {
        [sender setImage:[UIImage imageNamed:@"font_on"] forState:UIControlStateNormal];
         //改变webview的字体
        [_detailWebView stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '100%'"];
    }
}

17.数组去重

屏幕快照 2017-01-16 上午11.16.23.png 屏幕快照 2017-01-16 上午11.16.29.png

例如专车中用到了:

屏幕快照 2017-01-16 上午11.17.50.png

18.MVC的各个部分都有哪些技术来实现?

MVC是Model-View-Controller的简写;是模型、试图、控制开发模式,对于iOS SDK,所有的View都是视图层的,它应该独立于模型层,由视图控制层来控制。所有的用户数据都是模型层,它应该独立于视图。所有的ViewController都是控制层,由它负责控制视图,访问模型数据
1.M代表业务逻辑层(通过JavaBean,EJB组件实现)
2.V是视图层(由JSP页面产生)
3.C属于控制层(一般可以用基础的Servlet实现,也可用Struts等开源框架实现)
通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用

链接:MVC & MVP & MVVM 区别http://www.jianshu.com/p/eedbc820d40a

19.内存溢出和内存泄露?

  • 内存溢出: 即out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;也就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。memory leak会最终会导致out of memory!举个例子: 一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了,这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出.
  • 内存泄露:即 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。它是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。

检测内存泄露使用工具如图

QQ图片20160505155210.jpg

工具的具体使用方法待进一步总结中......

20.获取项目根路径,并在其下创建一个名称为userData的目录?

// 获取根路径
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:];
// 创建文件系统管理器
NSFileManager *fileManager = [[NSFileManager alloc] init];
// 判断userData目录是否存在
if(![fileManager fileExistsAtPath:[NSString stringWithFormat:@"%@/userData", documentsDirectory]]) {
// 不存在,创建一个userData目录
[fileManager createDirectoryAtPath:[NSString stringWithFormat:@"%@/userData", documentsDirectory]withIntermediateDirectories:false attributes:nil error:nil];}

21.几个变量的区别

屏幕快照 2017-01-16 上午10.32.58.png

22.如何从网络获取数据?

1.创建一个统一资源定位符对象NSURL
是否带参数?
是否需要中文转换成对应的百分号编码
2.创建一个请求对象
第一个参数: 统一资源定位符
第二个参数:缓存策略
第三个参数:请求超时时间
3.通过连接对象发送请求
同步请求 阻塞式(代码会在此阻塞知道服务器完成响应或超时) 一般不用,会造成用户体验差
异步请求 非阻塞式 (代码会往下执行 当收到服务器数据通过Block回调处理服务器返回数据) 牺牲空间换取时间
4.解析数据
使用YYModel

5.刷新的界面如何在主线程中执行?

// 模型对象准备就绪后就可以刷新表格视图
            // 苹果官方规定: 刷新界面的代码要在主线程中执行
            // 否则界面可能无法刷新(时候可以下拉刷新出现) 因此下面的代码要回到主线程执行
            // 写法一: GCD (支持多线程编程的函数)
            dispatch_async(dispatch_get_main_queue(), ^{
                [myTableView reloadData];
            });
        // 写法二: NSOperation和NSOperationQueue
        // 创建一个操作对象封装要执行的代码
        NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
            [myTableView reloadData];
        }];
        // 将该操作添加到主队列(主队列的操作在主线程中执行)中
        [[NSOperationQueue mainQueue] addOperation:op];
    }

23.@class作用

答:在头文件中, 一般只需要知道被引用的类的名称就可以了。 不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。 而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
• @class的作用是告诉编译器,有这么一个类,用吧,没有问题
• @class还可以解决循环依赖的问题,例如A.h导入了B.h,而B.h导入了A.h,每一个头文件的编译都要让对象先编译成功才行
• 使用@class就可以避免这种情况的发生

24.链表和数组的区别在哪里?

二者都属于一种数据结构

  1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
  2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素
  1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小
  2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦

25.如何优化代码?

列出在编码中哪些编码习惯有助于提高代码质量、软件性能和健壮性,减少程序崩溃?

1.使用严格的命名规则(如匈牙利命名法)能够避免不必要的类型转换错误。

2.在编码前先设计好流程图或使用伪代码,清晰化整个设计意图。

3.对自己的代码进行严格的单元测试(unit testing)。
单元测试是指对软件中的最小可测试单元进行检查和验证。如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

4.异常的处理
首先不要轻易使用异常的捕获,其次要尽可能捕获具体的异常。对于异常的处理最好能够采用封装的方式,大家统一使用。这样可以保证异常处理的一致性也可以保证当异常出现时性能的稳定。

  • 使用内省的方法检查方法的输入
    5.采用增量式的编程方式。
    采用增量式编程和测试,会倾向于创建更小的方法和更具内聚性的类。你应该经常评估代码质量,并不时的进行许多小调整,而不是一次修改许多东西。在写了几行代码之后,就应该进行一次构建/测试。在没有得到反馈时,你不要走的太远。
    6.使用工具(如Instrument)来帮助检查内存泄漏、过早释放内存、CPU使用效率等问题。
    7.消除所有的编译警告,警告就是错误。
    8.写防御性的代码,使用内省的方法检查传入的参数。

26.回调机制

iOS中有哪些回调机制,并作简单的比较。
各种回调机制的比较:
1)目标动作对:当两个对象之间有比较紧密的关系时,如视图控制器与其下的某个视图。
目标-动作机制
答:目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见"插座变量"部分) 的形式保有其动作消息的目标。
动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。
2)代理:也叫委托,当某个对象收到多个事件,并要求同一个对象来处理所有事件时。委托机制依赖于某个协议定义的方法来发送消息。
3)通告机制:当需要多个对象或两个无关对象处理同一个事件时。
4)Block:适用于回调只发生一次的简单任务。

27.const和static和extern c

const int a;
int const a;
const int *a;
int * const a;
int const * a const;
1.前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

2.结论:关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果 你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清 理的). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

3.欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初 始化,因为以后就没有机会再去改变它了;(2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指 定为 const

4.在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值; (4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量; (5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。

5.关键字volatile有什么含意?并给出三个不同的例子。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

6.下面是volatile变量的几个例子:
并行设备的硬件寄存器(如:状态寄存器)
一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
多线程应用中被几个任务共享的变量
一个参数既可以是const还可以是volatile吗?解释为什么。
一个指针可以是volatile 吗?解释为什么。

7.下面是答案:
是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

8.static关键字的作用:
(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值; (2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内;
(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。

9.extern "C"的作用:
(1)被 extern "C"限定的函数或变量是 extern 类型的;
extern是 C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
(2)被 extern "C"修饰的变量和函数是按照 C 语言方式编译和连接的;
extern "C"的惯用法
(3)在 C++中引用 C 语言中的函数和变量,在包含 C 语言头文件(假设为 cExample.h)时,需进 行下列处理:
extern "C" { #include "cExample.h" }
而在 C语言的头文件中,对其外部函数只能指定为 extern 类型,C语言中不支持 extern "C"声明, 在.c 文件中包含了 extern "C"时会出现编译语法错误。
(4)在 C 中引用 C++语言中的函数和变量时,C++的头文件需添加 extern "C",但是在 C 语言中不 能直接引用声明了 extern "C"的该头文件,应该仅将 C 文件中将 C++中定义的extern "C"函数声明为 extern 类型。

28.开发 常用工具(打电话、发短信、发邮件)

屏幕快照 2017-01-16 下午2.26.11.png

http://www.jianshu.com/p/0bac60cb6f38

29.浅谈webView的JS一种用法.(去掉web显示页的广告)

http://www.jianshu.com/p/c3204ed25b68

30.App上传被拒绝之 “iOS 非公开API prefs:root=Privacy”

被拒绝之 “iOS 非公开API prefs:root=Privacy”

解决的办法:https://www.jianshu.com/p/3f86cfc9b387

上一篇下一篇

猜你喜欢

热点阅读