标签归档:ios

iOS工程师面试必会基础知识36题

这一篇是iOS基础知识,转自网友的的面试总结,希望对大家有帮助。

1、必须熟悉的关键字

@interface声明类,@implementation实现类。@protocol声明协议,@optional与@protocol配合使用,说明协议中的某个或者某几个方法可以不实现。@required与@protocol配合使用,说明协议中的某个方法或者某几个方法必须实现。@end与@interface ,@implementation,@protocol配合使用,代表声明或者实现结束。

2、id

id是指向Objective-C类对象的指针,它可以声明为任何类对象的指针,当在Objective-C中使用id时,编译器会假定你知道,id指向哪个类的对象。与void*是不同的是,void*编译器不知道也不假定指向任何类型的指针。

3、nil

定义为一个常量,如果一个指针的值为nil,代表这个指针没有指向任何对象。

4、self

在Objective-C中,关键字self与c++中this是同一概念,就是类对象自身的地址,通过self可以调用自己的实例变量和方法。

5、Super

当子类需要调用父类的方法时,会用到Super关键字. Super指向的是父类的指针,子类重写父类的方法时,调用父类的方法是一个比较好的习 惯。因为 当我们不知道父类在该方法中实现的功能时,如果不调用父类的方法,有可能我们重写的方法会失去该功能,这是我们不愿意看到的情况。

6、NSNull

NSNull是没有的意思,如果一个字典的值为NSNull,那说明与该值对应的Key是没有值的,例如Key为address,说明与address对应的是值是没有。

7、类方法 +

如果想声明属于类而不属于类对象的方法,用+。+用来修饰类的方法,使用+修饰的类方法,是整个类的方法,不属于哪一个类对象,这与C++中的static在类中使用的概念一样。

8、%@

在NSLog中,使用%@表示要调用对象的description方法。

9、类

是一种结构,它表示对象的类型,就像int与 char 一样,也可以声明类的变量(对像)。

10、实例化

为类的对象分配内存和初始化,达到可以使用该 类对象的目的。

11、对象(实例)

类的实例化后的产物。

12、消息

在Object-C中,类的对象执行的操作,是通过给该类或者该类对象发送消息实现,如:[object func];就是给object对象发送 func消息,类似C++中的方法调用。给object对象发送func消息后,object对象查询所属类的func方法执行。

13、方法调度

当向一个对象发送消息时(调用方法),这个方法是怎么被调用的呢?这就依赖于方法调度程序,方法调度程序查找的方法如下:

在本类的方法中,找被调用的方法,如果找到了,就调用,如果找不到被沿着继承路径去查找,从哪个类找到,就调用哪个类的方法,如果到最根上的类还是没有找到,那编译就会出错。

14、继承与复合

在Objective-C中支持继承,但只是支持单一继承(有且只有一个父类),如果想使用多继承的特性,可以使用分类和协议技术。继承是is-a,复合是has-a。复合是通过包含指向对象的指针实现的。

15、装箱与拆箱

由于NSArray,NSDirectory等类不能直接存储基本数据类型,所以要想在NSArray\NSDirectory中使用基本数据类型,就得使用装箱与拆箱。

在Objective-C中,可以使用NSNumber和NSValue来实现对数据类型的包装,NSNumber可以实现对基本数据类型的包装,NSValue可以实现对任意类型数据的包装。

将基本类型封装成对象叫装箱,从封装的对象中提取基本类型叫拆箱(取消装箱),其它语言如Java原生支持装箱与拆箱,Ojbective-C不支持自动装箱与拆箱,如果需要得需要自己来实现装箱与拆箱。(NSKeyedArchiver、NSKeyedUnarchiver)。

16、存取方法

在使用类对象的实例变量(成员数据)时,不要直接使用对象中的实例,要使用存以方法来获取或者修改实例,既setter和getter,在 Cocoa中, 存取方法有命名习惯,我们得符合这种习惯,以便于与其它团队成员合作。setter方法是修改或者设置实例值,命名习惯为set+实例名,例有一个类有 path实例变量,那setter命名为setPath,getter命名为Path,为什么不是getPath,因为get在Cocoa中有特殊的含 义,这个含义就是带有get的方法就意味着这个方法通过形参指针(传入函数的参数指针)来返回值。我们要遵守这个命名习惯或者说规则。

在Objective-C 2.0中加入了@property和@synthesize来代替setter和getter,这两个关键字为编译器指令。还有点表达式,存取类成员的值时,可以使用点表达式。

Object.attribute,当点表达式在=号左边时,调用的是setter方法,在=号右边时,调用的是getter方法。

17、@property 语法为:@property (参数) 类型 变量名.

在这里主要说明一下参数.

参数分为三种:

第一种:读写属性包括(readonly/readwrite/)

第二种:setter属性(assign,copy,retain),assign是简单的赋值,copy是释放旧成员变量,并新分配内存地址给成 员 变量,将传入参数内容复制一份,给成员变量。retain是将传入 参数引用计数加1,然后将原有的成员变量释放,在将成员变量指向该传入参数。

第三种:与多线程有关(atomic,nonatomic).当使用多线程时,使用atomic,在不使用多线程时使用nonatomic

18、对象创建与初始化

在Objective-C中创建对象有两种方法,一种是[类 new];另一种是[[类 alloc] init],这两种方法是等价的,但按惯例来讲,使用[[类 alloc] init];

alloc操作是为对象分配内存空间,并将对象的数据成员都初始,int 为0,BOOL 为NO, float 为0.0等。

初始化,默认的初始化函数为init,init返回值为id,为什么回返回id呢,因为要实现链式表达式,在Objective-C中叫嵌套调用。

为什么要嵌套调用?因为初始化方法init返回值可能与alloc返回的对象不是同一个?为什么会发生这种情况?基于类簇的初始化,因为init可以接受参数,在init内部有可能根据不同的参数来返回不同种类型的对象,所以最会发生上面说的情况。

在初始化时,建议使用if (self = [super init])

19、便利初始化(下面解释太绕, 不用看了)

当一个类需要根据不同的情况来初始化数据成员时,就需要便利初始化函数,与init初始化不同的是,便利初始化函数有参数,参数个数可以有1到N个,N是类数据成员个数。

指定初始化函数:什么是指定初始化函数?在类中,某个初始化函数会被指定为指定的初始化函数,确定指定初始化函数的规则是初始化函数中,参数最多的为指定初始化函数,

其它未被指定为指定初始化函数的初始化函数要调用指定初始化函数来实现。对于该类的子类也是一样,只要重写或者直接使用父类的指定初始化函数。

20、自动释放池(深入了解看:《Objective-C高级编程》第一章)

内存管理是软件代码中的重中之重,内存管理的好坏,直接影响着软件的稳定性。在Cocoa中,有自动释放池,这类似于C++中的智能指针。

NSObject有一个方法是autorelease,当一个对象调用这个方法时,就会将这个对象放入到自动释放池中。

drain,该方法是清空自动释放池,不是销毁它。drain方法只适用于Mac OS X 10.4以上的版本,在我们写的代码中要使用release,release适用于所有版本。

自动释放池是以栈的方式实现,当创建一个自动释放池A时,A被压入栈顶,这时将接入autorelease消息的对象放入A自动释放池,这时创建一 个新的 B自动释放池,B被压入栈顶,创建完成后删除B,这个接收autorelease消息的对象依然存在,因为A自动释放池依然存在。

21、类别

什么是类别?类别是一种为现有类添加新方法的方式。

为什么使用类别或者说使用类别的目的是什么?有以下三点:

第一,可以将类的实现分散到多个不同的文件或多个不同的框架中。

如果一个类需要实现很多个方法,我们可以将方法分类,把分好的类形成类别,可以有效的管理和驾驭代码。

第二,创建对私有方法的前向引用。

第三,向对象添加非正式协议。

22、委托(下面的解释不好,可跳过。以后找机会专门总结一下这个知识点。我的软肋之一。)

委托的意思就是你自己想做某事,你自己不做,你委托给别人做。

在Ojbective-C中,实现委托是通过类别(或非正式协议)或者协议来实现。

举个例子:Apple要生产iPhone,Apple自己不生产(种种原因,其中之一就是在中国生产成本低,他们赚的银子多),Apple委托富士 康来生 产,本来富士康原来不生产iPhone,现在要生产了,所以他得自己加一个生产iPhone的生产线(类别,增加生产iPhone方法),这就是通过类别 来实现委托。

23、非正式协议(同上)

创建一个NSObject的类别, 称为创建一个非正式协议。为什么叫非正式协议呢?

也就是说可以实现,也可以不实现被委托的任务。

24、选择器

选择器就是一个方法的名称。选择器是在Objective-C运行时使用的编码方式,以实现快速查找。可以使用@selector预编译指令,获取 选择器 @selector(方法名)。NSObject提供了一个方法respondsToSelector:的方法,来访问对象是否有该方法(响应该消息)。

25、正式协议

与非正式协议比较而言,在Ojbective-C中,正式协议规定的所有方法必须实现。在Ojbective-C2.0中,Apple又增加了两个关键字,协议中的方法也可以不完全实现,是哪个关键字见关键字部份的@optional,@required。

26、什么是框架

框架是一种聚集在一个单元的部件集合,包含头文件,库,图像,声音文件等。苹果公司将cocoa,Carbon,QuickTime和OpenGL 等技术 作为框架集提供。cocoa的组成部分有Foundation和Application Kit框架。还有一个支持框架的套件,包含 Core Animation和Core Image,这为Cocoa增添了多种精彩的功能。

每个框架都是一个重要的技术集合,通常包含数十个甚至上百个头文件。每个框架都有一个主头文件,它包含了所有框架的各个头文件。通过使用#import导入主头文件,可以使用所有框架的特性。

27、OOP中得一些术语

类:类是一种结构,它表示对象的类型。对象引用类来获取和本身有关的各种信息,特别是运行什么代码来处理每种操作。

对象:对象是一种结构,它包含值和指向其类的隐藏指针。

实例:实例是“对象”的另一种称呼。

消息:消息是对象可以执行的操作,用于通知对象去做什么。

方法:方法是为响应消息而运行的代码。根据对象的类,消息可以调用不同的方法。

方法调度程序:是objective-c使用的一种机制,用于推测执行什么方法以响应某个特定的消息。

接口:接口是对象的类应该提供的特性的描述。接口不提供实现细节。

实现:实现是使接口正常工作的代码。

28、键/值编码 KVC

是一种间接改变对象状态的方式,其实现方法是使用字符串描述要更改的对象状态部分。

1)valueForKey与setValue:forKey:

这两种方法的工作方式相同。他们首先查找名称的setter(getter)方法,如果不存在setter(getter)方法,他们将在类中查找名为名称或_名称的实例变量。然后给它赋值(取值)。无需通过对象指针直接访问实例变量。

2)路径

键路径的深度是任意的,具体取决于对象图。

键路径不仅能引用对象值,还可以引用一些运算符来进行一些运算,例如获取一组值的平均值或返回这组值中得最小值和最大值。

例如:NSNumber *count;

count = [garage valueForKeyPath:@”cars.@count”];

NSLog(@”We have %@ cars”, count);

我们将路径“cars.@count”拆开,cars用于获取cars属性,它是来自garage的NSArray类型的值。接下来的部分是@count ,其中@符号意味着后面将进行一些运算。

和 cars@sun.mileage

最大值 cars@min.mileage

最小值 cars@max.mileage

3)整体操作

KVC非常棒的一点是,如果向NSArray请求一个键值,它实际上会查询数组中得每个对象来查找这个键值,然后将查询结果打包到另一个数组中并返回给你。这种方法也适用于通过键路径访问的对象内部的数组。

4)批处理

KVC包含两个调用,可以使用他们对对象进行批量更改。第一个调用是dictionaryWith-ValuesForKeys:。它接受一个字符串数组。该调用获取一些键,对每个键使用valueForKey:,然后为键字符串和刚才获取的值构建一个字典。

29、Object-C有多继承吗?没有的话用什么代替?cocoa 中所有的类都是NSObject 的子类

多继承在这里是用protocol 委托代理 来实现的,你不用去考虑繁琐的多继承 ,虚基类的概念.多态特性 在 obj-c 中通过委托来实现.

30、#import和#include的区别,@class代表什么?

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import

而#import比起#include的好处就是不会引起重复包含。

31、线程和进程的区别?

进程和线程都是由操作系统下的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一 个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程 序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

32、堆和栈的区别?

管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

申请大小:

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因 此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出

分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的.

33、为什么很多内置的类,如TableViewController的delegate的属性是assign不是retain?

避免循环引用。

34、tableView的重用机制?

查看UITableView头文件,会找到NSMutableArray* visiableCells,和 NSMutableDictionery* reusableTableCells两个结构。visiableCells内保存当前显示的 cells,reusableTableCells保存可重用的cells。

TableView显示之初,reusableTableCells为空,那么 tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都 是通过 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的次数。

比如:有100条数据,iPhone一屏最多显示10个cell。程序最开始显示TableView的情况是:

1.[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识)。并且10个cell全部都加入到 visiableCells数组,reusableTableCells为空。

2.向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。 cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。

3.接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的 cell,cellForRowAtIndexPath再次被调用的时 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。

35、怎么理解MVC,在Cocoa中MVC是怎么实现的?

Model: 代表你的应用程序是什么(不是怎么展现)。

Controller: 控制你的Model怎么展现给用户(UI逻辑)。

View: Controller的奴隶。

1 Model,Controller,View相互通讯的规则:

Controller可以直接和Model通信。

Controller也可以直接和View通信。

Model和View永远不能直接通信。

iOS中View和Controller的通信是透明和固定的,主要通过outlet和action实现。

View使用Delegate接口和Controller同步信息。

View不直接和数据通信,使用dataSource接口从Controller处获取数据。

View的delegate和dataSource一般就是Controller。

Controller负责为View翻译和格式化Model的数据。

Model使用Notification & KVO的方式分发数据更新信息,Controller可以有选择的监听自己感兴趣的信息。

View也可以监听广播信息,但一般不是Model发出的信息。

一个完整的App就是很多MVC的集合。

36、delegate和notification区别,分别在什么情况下使用?

Delegate:

消息的发送者(sender)告知接收者(receiver)某个事件将要发生,delegate同意,然后发送者响应事件,delegate机制使得接收者可以改变发送者的行为。通常发送者和接收者的关系是直接的一对多的关系。

Notification:

消息的发送者告知接收者事件已经发生或者将要发送,仅此而已,接收者并不能反过来影响发送者的行为。通常发送者和接收者的关系是间接的多对多关系。

1. 效率肯定是delegate比nsnotification高。

2. delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要关注返回值,也就是delegate方法 的结果。比如-windowShouldClose:,需要关心返回的是yes还是no。所以delegate方法往往包含should这个很传神的词。 也就是好比你做我的delegate,我会问你我想关闭窗口你愿意吗?你需要给我一个答案,我根据你的答案来决定如何做下一步。相反 的,notification最大的特色就是不关心接受者的态度,我只管把通告放出来,你接受不接受就是你的事情,同时我也不关心结果。所以 notification往往用did这个词汇,比如NSWindowDidResizeNotification,那么nswindow对象放出这个 notification后就什么都不管了也不会等待接受者的反应。

1)两个模块之间联系不是很紧密,就用notification传值,例如多线程之间传值用notificaiton。

2)delegate只是一种较为简单的回调,且主要用在一个模块中,例如底层功能完成了,需要把一些值传到上层去,就事先把上层的函数通过 delegate传到底层,然后在底层call这个delegate,它们都在一个模块中,完成一个功能,例如 说 NavgationController 从 B 界面到A 点返回按钮 (调用popViewController方法) 可以用delegate 比较好。

2015非官方的iOS APP全方位设计指南

有时候为iOS设计app并不是一件简单的事,但是如果你能找到正确的最新的苹果设备信息,并按照正确的方向,那么为iOS设计app或许会变得简单容易些。

关于这些指南

这些指南描述了如何遵守苹果的iOS 人机交互指南来设计app,而不是讲用自定义控件可以做成什么样的设计,有时候打破规则也很重要。该文档的目的并不是为一些复杂的设计问题提供解决方案。该文档是非官方的,将会定期更新和扩充内容,最近一次更新是2014年11月11日。

分辨率和显示屏规格(Resolutions和Display Specifications)

Points 和Pixels的区别

Pixels(像素)是数字显示屏上我们可控制的最小物理元素,在一个特定屏幕尺寸中可以有多个像素,PPI(pixels-per-inch)越高,则渲染的内容会越清晰。

Points用以衡量分辨率。根据屏幕的像素密度,一个point可以包含多个像素(比如在常规的retina屏上,1pt包含2 x 2的像素)。

当你针对多个显示屏类型进行设计时,你应该以points进行思考,但以pixels进行设计。这意味着你仍需要以3种不同的分辨率来输出设计资产,不管你针对哪个分辨率设计应用程序。

iPhone 6+缩减像素取样

在iOS上渲染像素和物理像素(physical pixels)是等同的,只有一个例外:iPhone 6 Plus的Retina HD显示屏。由于它屏幕的像素分辨率要低于一个常规的@3x分辨率,所以被渲染内容会自动调整为原始尺寸的87%(从2208*1242像素来适应为1920*1082像素的显示屏分辨率)

iPhone 5S, 6 以及6+显示屏区别的详细信息可参看:The Ultimate Guide To iPhone Resolutions

App Icons

自动应用效果

多尺寸的应用程序icon通常被添加到应用程序包中,当在设备上渲染时,iOS会将效果应用在应用程序icon上。

(1)圆角

圆角半径值已经不存在了。从iOS 7开始,app icon已经使用了超椭圆的形状。由于苹果没有发布该形状的官方模板,所以你得精确地使用非官方的模板。

圆角的图形不应该包含在最终的输出资产中,但如果你想要添加和应用程序icon拐角对齐的描边和阴影效果,那你可能还会用到圆角图形。

提醒:因为你想将应用效果和icon拐角对齐,所以如果你正使用超椭圆的形状对icon资产进行蒙版(遮罩),那要确保在遮罩外的区域不能使用任何透明的图形。应用程序icon不支持透明度,相反作为纯黑色进行渲染。如果你的遮罩不是百分百精确,那用户将会在圆角边缘看 到黑色的锯齿。推荐将canvas的背景设置成和app icon一样的背景。

(2)边框描边(某些情况下)

如果你使用的app icon有白色的背景,那么将会应用1pixel的灰色边框,以便更容易地识别icon的边缘。这只能在设置app和App Store中进行。

(3)后续问题(iOS 6 和之前的版本)

在旧的iOS版本中,这些效果会自动应用:可以被禁用的圆角(和iOS 7+中使用的icon不同)、主屏幕上的阴影效果以及关泽效果等。

栅格系统

苹果开发了具有黄金分割比例的栅格系统,可用以正确地调整和对齐icon上的元素。不过,甚至是苹果设计师的原生app icon也没有完全严格地遵守栅格系统。所以如果你的icon上的元素在没有严格遵守栅格系统的情况下能更好地展示,那你可以考虑下打破一些固有的规则。

字体排版

所有的iOS版本中默认字体都是Helvetica Neue。从iOS 7开始,苹果使用了稍作修改的字体,但是在你的设计过程中使用原始的Helvetica Neue是极好的。除了默认字体外,你还可以使用很多可选的字体,你可以在此查看完整的预置字体列表。

自定义字体

从技术角度讲,True Type Font (.ttf)可以被用在iOS app中,但要注意许可问题。一般来说,使用完全免费或者商业化的字体是安全的。MyFonts最大数量地包含了可用在app中的许可字体。

调色板

iOS 7以后,苹果在操作系统和预装app中使用了更有生机和活力的调色板。虽然你可以使用上边默认的iOS调色板,但你也可以使用自己的颜色(如果你想与众不同,当然要使用了)。

图标

在iOS app中,icon一个很好的用法是使用视觉化的关系来支持文本标签,从而执行一些操作或者完全取代文本(最常用的比如”New”、”Delete”等)。通常,我们使用icon来区分导航栏、工具栏以及标签栏。

各种”栏”的按钮icon

各种”栏”中的按钮icon应该有两种状态:默认状态下的1或者1.5pt笔画宽度的轮廓样式,以及纯色填充的活跃状态。

不要在按钮icon上添加任何额外的效果,比如下拉阴影或者内阴影,因为这些是iOS 7之前版本中的用法。按钮icon应该在一个透明背景上以一种纯色进行绘制–icon的形状作为遮罩,颜色将会以编程形式应用。

活动视图图标

活动视图(通常指分享弹出视图)中的icon以轮廓样式设计,但苹果在iOS 8以后回归到白色背景上的实体填充icon风格。

常用设计元素

iOS提供了很多不错的现成的视图和控件,可帮开发者快速构建页面。开发者可以将一些元素自定义到某个级别,但是也有一些元素不能或者不应该进行自定义。当为iOS设计应用程序时,你应该知道一些工具集的使用,只要是可能,就应该坚持下去。但在一些情况下,可能需要设计一些自定义控件,因为你需要一个更加定制化的界面或者想要改变现有控件的功能(有点危险)。几乎任何一件事情都是有可能的,而有时候你需要打破既有的规则,不过需要三思。

状态栏

状态栏包含了基本的系统信息,比如运营商、时间、电池状态以及其他等,它在视觉上通常与导航栏联系在一起,并且使用相同的背景填充。为了匹配你的app的风格,并且易于阅读,状态栏的的内容一般有两种不同的风格:深色(黑色)和浅色(白色)。

你可以隐藏导航栏,但要思考清楚。比如在app下载web内容时,用户可能对设备是否连接上WiFi网络比较感兴趣,在app要求蓝牙连接第三方硬件时,用户可能会想知道应用是否启用了蓝牙。一个令人信服的隐藏状态栏的理由是你想移除对的那个元素的所有干扰信息,比如全屏展示内容,比如图片。

导航栏

导航栏包含在app多个视图间进行导航的控件,以及在当前视图中管理内容的选项。导航栏通常展示在屏幕的顶部,状态栏的底部。默认情况下,背景是半透明的,在导航栏下方还有模糊的内容。导航栏的背景可以是纯色的,渐变的或者是自定义的位图模式。

竖屏模式下的iPhone 6导航栏。

横屏模式下的iPhone 4S导航栏。导航栏的高度减了12pt,除了iPad。这也是常见的横屏模式下隐藏状态栏的方法。

元素应当遵循特定的对齐模式:

1.返回按钮通常居左对齐。

2.当前视图的标题应当居中展示在bar中。

3.Action按钮通常居右对齐。如果可能的话action按钮应当限制在一个主要操作行文,以避免错误点击,并维持其简洁性。

工具栏

工具栏包含用于管理或者操作当前视图中内容的一些操作。在iPhone上,它通常出现在屏幕的底部,但在iPad上也能出现在屏幕的顶部。

和导航栏类似,工具栏的背景填充也能调整,默认情况下工具栏本身是半透明的,在其下方还有模糊的视图内容。

当一个特定视图要求三个以上主要活动,但放在导航栏上又显得凌乱时,你可以使用工具栏。

搜索栏

搜索栏默认有两种风格:突出的和最小化的。两种类型的搜索栏在功能上是一样的。

1.只要用户没有输入文本,搜索栏中会展示占位符文本,而书签icon则可用来访问最近或者保存的搜索。

2.键入搜索项目后,占位符消失,一个清晰的删除按钮会出现在搜索栏的右侧。

搜索栏可以利用一个提示–一个短句来介绍搜索的上下文环境。比如”键入某个城市、邮政编码或者机场”

不使用提示和使用提示两种风格

最小化搜索栏类型

想要提供对检索词条的更多控制,可用scope bar(范围栏)限制搜索栏,scope bar会使用和搜索栏一样的风格,当搜索结果有清晰的定义类别时,这种方法比较有用。比如,在一款音乐类app中,搜索结果可以按照专辑和歌曲再次过滤。

标签栏

用户可使用标签栏在app的单个视图间快速导航,并且标签栏也只能用于这个目的。标签栏通常出现在屏幕的底部。默认情况下,标签栏是略透明的,并且向导航栏一样使用系统的模糊效果。

标签栏包含固定的最大数量的tabs,一旦标签数量超过其可容纳的最大数量,后边的标签将会展示在隐藏的”More-tab”列表中,并且有一个选项可重排标签顺序。

虽然iPhone上最多可展示5个标签,但是在iPad上最多可展示7个标签。

为了提醒用户视图上的新信息,有时候需要在标签栏按钮上使用标记数量。如果一个视图被临时禁用,那么相关的标签按钮不应当完全被隐藏,相反应当淡出视觉范围以表示其禁用状态。

表视图(Table View)

表视图以单列或者多列形式展示少数或者多个列表风格的信息,并有能将内容分组的选项。根据你展示的数据类型,通常可使用两种基本的表视图风格:

无格式的

无格式表视图包含的几行内容的顶部可以有页眉,最后一行后边可以有页脚。可以在屏幕右边缘展示垂直导航,以便在表中进行导航,这种情况适合展示以某种方式储存的大数据集的时候,比如按照字母降序排列。

分组样式

分组表视图允许用户对内容进行分组。每个分组可以有页眉(最佳用法是描述类组的上下文环境)和页脚(适用于帮助文本等)。一个分组的表视图至少需要包含一个类组,并且每个类组至少要包含一行内容。

对于以上两种表视图类型,可用几种风格来展示数据,以方便用户快速扫描、阅读和适当调整内容。

默认

默认的表视图有一个居左对齐的可选图片和标题。

带有副标题

在每行标题下展示小字号的副标题,适用于进一步的解释说明或者简短描述。

带有数值

带数值表类型可展示与行标题相关的特定数值。类似默认的类型,每行都有一个居左对齐的图片和标题。在该类型中,数值居右对齐,通常使用比标题淡一点的文本颜色。

模态视图、弹出视图以及提醒(警示)视图

iOS提供了多种风格的临时视图,可以某种方式在既定的情况下展示、编辑或者操作数据。虽然每种临时视图因某个非常特定的目的而存在,但外观上却大有不同,不过所有临时视图都有一个相同的地方:在展示时,它就是当前视图上最上方的图层,下方的内容被一个黑色的背景所覆盖。

活动视图(ACTIVITY VIEW)

活动视图用以展示特定的任务。这些任务可以是系统默认的任务,比如通过可用选项分享内容,或者是完全自定义的活动。当为自定义任务按钮设计icon时,你应当遵从活跃状态和栏按钮icon的一些设计指南–纯色填充、无任何效果、以及在一个透明背景上。

活动(ACTIONS)

活动页面用来执行可用操作列表中的单项操作,并且强迫用户确认或者取消某个活动。

在竖屏模式下(以及尺寸比较小的横屏模式下),actions以按钮列表形式滑入,并呆在屏幕的底部。这种情况下,活动列表应该有一个取消按钮来关闭视图和执行任何列表中的action。

当有足够可用的空间时(比如iPad上),活动列表可在视觉上转为弹出视图。不过此时不一定非得有一个关闭按钮,用户点击弹出视图外的任何地方都能关闭弹出视图。

提醒视图

提醒视图的目的是用来通知用户一些关键性的信息,并有选择地迫使用户做出选择。

提醒视图通常包含一个标题文本(最好不要超过一行)、一个(纯信息提醒,比如”OK”)或者两个按钮(要求用户做出决定,比如”Send”或”Cancel”)。

你可以在提醒视图中添加消息文本,如果需要的话则可添加两个文本域,其中之一可以是蒙版的输入区,适合密码或者PINs之类的敏感信息。

编辑菜单(EDIT MENU)

用户可使用编辑菜单执行复制、粘贴以及剪切等操作。虽然你能控制用户可以选择哪个操作,但是编辑菜单的视觉外观是设定好的,不能重新配置,除非你设计一个完全自定义的编辑菜单。

弹出视图(Popovers)

当某项特定操作要求多个用户输入才能继续进行时弹出视图就非常有用了。在水平方向上,弹出视图可通过箭头指向展示下方相关的控件(比如按钮)。弹出控件的背景透明度稍有降低,可展示其下方的模糊内容,像iOS 7以后其他很多UI元素一样。

弹出视图是一种非常强大的临时视图,可包含类似导航栏、表视图、地图或者web视图等对象。随着弹出视图所包含内容和元素的增加,其窗口也能滚动展示。

模态视图

模态视图适用于需要多个命令和用户输入的情况,位于屏幕上所有内容的最上方。典型的模态视图通常提供:

1.描述任务的标题。

2.关闭模特视图的按钮,没有保存或执行任何其他操作。

3.保存或者提交任何已输入内容的按钮。

4.模态窗口主体中提供大量用户可输入的元素。

有三种可用的模态视图类型:

1.全屏模式:覆盖整个屏幕

2.页表模式:竖屏模式下,模态视图覆盖屏幕上的部分内容,仅在半透明的暗色背景上展示部分父视图的内容。横屏模式下,模态视图会像全屏模态视图那样展示。

3.表格页面模式:竖屏模式下,模态视图出现在屏幕的中间。模态视图范围之外,父视图内容展示在半透明背景之下。当需要展示键盘时,模态视图的位置会自动调整。横屏模式下类似全屏模态视图。

控件(Controls)

iOS为基本上任何类型的输入需求提供了各种各样的控件。以下列出的是最常用的控件,但想要看详细的完整的可用控件列表,请在iOS Developer Library中查看。

按钮

最常用的控件可能是按钮。iOS 7以来,默认的按钮设计看起来更像一个纯文本链接。按钮控件支持高度自定义。按钮可以有几种不同的状态,可以使用视觉语言传达:默认、突出、选择以及禁用等。

选择器(PICKERS)

选择器用来在一个可用值列表中选择某个值,和Web上的下拉选框功能类似。选择器的扩展版本是日期选择器,允许用户滚动日期和时间列表来选择一个月、日以及具体时间。

左:表视图中的日期选择器,右:选择器作为键盘

除了背景色外,不可能更改其视觉风格或者尺寸。很多时候,选择器位于屏幕的底部,像键盘一样展示,但不能用在其他地方。

分段控件(SEGMENT CONTROLS)

分段控件包含一组至少两个以上的分段,可用来过滤内容或者为清晰分类的内容创建标签。

不带icon与带icon的分段控件

每个分段可包含一个文本标签或者一个图片(icon),但不能同时包含两者。另外,不建议在一个分段控件中混合使用不同的分段风格,比如文本和图片。每个分段的宽度会基于分段的数量自动调整(两个分段各占50%,5个分段各占20%)。

滑杆(SLIDERS)

滑杆控件允许用户从允许值范围中选择一个特定的值。由于使用滑杆选择一个值的操作非常流畅,并且无需额外的步骤,所以建议在选择预估值的时候使用滑杆,而不是选择精确的值。比如滑杆可以很好地用来设置音量,用户可以听到和看到音量大小的不同,而通过输入文本来设置精确的dB值是不切实际的。

不带icon与带icon的滑杆控件

可以为最小值和最大值设置icon,icon会展示在滑杆控件的开始和末尾两端,从而在视觉上加强滑杆的目的。

进步器(STEPPER)

当用户从一个有限的值范围中(比如1-10)键入准确的值的时候,可使用进步器。进步器通常包含两个分段按钮,一个是降低当前值,一个是增加当前值。

进步器的视觉外观支持高度自定义:

1.可使用自己的icon作为进步器按钮;

2.当想维持iOS原生的外观时,你可以自定义进步器边框、背景以及icon的颜色。

3.如果你更进一步使用自定义,那你可以为进步器的按钮和分割符使用完全自定义的图片。

开关(SWITCH)

用户可使用开关在”ON”和”OFF”两种状态间切换。设计师可自定义两种状态的颜色,但是开关按钮的外观和尺寸是设定好的不能更改。

键盘(KEYBOARDS)

有多重键盘类型可为特定的文本输入提供最好的键盘。虽然你可以使用自己完全自定义的剑兰,但默认的键盘无需调整风格和尺寸,很多时候更加方便一些。

HTML head 头标签属性详解

HTML head 头部分的标签、元素有很多,涉及到浏览器对网页的渲染,SEO 等等,而各个浏览器内核以及各个国内浏览器厂商都有些自己的标签元素,这就造成了很多差异性。移动互联网时代,head 头部结构,移动端的 meta 元素,显得更为重要。了解每个标签的意义,写出满足自己需求的 head 头标签,是本文的目的。

DOCTYPE

DOCTYPE(Document Type),该声明位于文档中最前面的位置,处于 html 标签之前,此标签告知浏览器文档使用哪种 HTML 或者 XHTML 规范。

DTD(Document Type Definition) 声明以 <!DOCTYPE> 开始,不区分大小写,前面没有任何内容,如果有其他内容(空格除外)会使浏览器在 IE 下开启怪异模式(quirks mode)渲染网页。公共 DTD,名称格式为注册//组织//类型 标签//语言,注册指组织是否由国际标准化组织(ISO)注册,+表示是,-表示不是。组织即组织名称,如:W3C。类型一般是 DTD。标签是指定公开文本描述,即对所引用的公开文本的唯一描述性名称,后面可附带版本号。最后语言是 DTD 语言的 ISO 639 语言标识符,如:EN 表示英文,ZH 表示中文。XHTML 1.0 可声明三种 DTD 类型。分别表示严格版本,过渡版本,以及基于框架的 HTML 文档。

  • HTML 4.01 strict
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  • HTML 4.01 Transitional
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
  • HTML 4.01 Frameset
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
    
  • 最新 HTML5 推出更加简洁的书写,它向前向后兼容,推荐使用。
    <!doctype html>

在 HTML中 doctype 有两个主要目的。

  • 对文档进行有效性验证。

它告诉用户代理和校验器这个文档是按照什么 DTD 写的。这个动作是被动的,每次页面加载时,浏览器并不会下载 DTD 并检查合法性,只有当手动校验页面时才启用。

  • 决定浏览器的呈现模式对于实际操作,通知浏览器读取文档时用哪种解析算法。如果没有写,则浏览器则根据自身的规则对代码进行解析,可能会严重影响 html 排版布局。浏览器有三种方式解析 HTML 文档。

charset

html5 声明文档使用的字符编码,

<meta charset="utf-8">

html5 之前网页中会这样写:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

lang属性

简体中文

<html lang="zh-cmn-Hans">

繁体中文

<html lang="zh-cmn-Hant">

为什么 lang="zh-cmn-Hans" 而不是我们通常写的 lang="zh-CN" 呢,请移步阅读: 页头部的声明应该是用 lang=”zh-cn” 还是 lang=“zh-cmn-Hans”

优先使用 IE 最新版本和 Chrome

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

360 使用Google Chrome Frame

<meta name="renderer" content="webkit">

360 浏览器就会在读取到这个标签后,立即切换对应的极速核。 另外为了保险起见再加入

<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">

这样写可以达到的效果是如果安装了 Google Chrome Frame,则使用 GCF 来渲染页面,如果没有安装 GCF,则使用最高版本的 IE 内核进行渲染。

百度禁止转码

通过百度手机打开网页时,百度可能会对你的网页进行转码,脱下你的衣服,往你的身上贴狗皮膏药的广告,为此可在 head 内添加

<meta http-equiv="Cache-Control" content="no-siteapp" />

相关链接:百度SiteApp 转码说明及如何取消转码

SEO 优化部分

  • 页面标题<title>标签(head 头部必须)
    <title>your title</title>
    
  • 页面关键词 keywords
    <meta name="keywords" content="your keywords">
    
  • 页面描述内容 description
    <meta name="description" content="your description">
    
  • 定义网页作者 author
    <meta name="author" content="author,email address">
    
  • 定义网页搜索引擎索引方式,robotterms 是一组使用英文逗号「,」分割的值,通常有如下几种取值:none,noindex,nofollow,all,index和follow。
    <meta name="robots" content="index,follow">

viewport

viewport 可以让布局在移动浏览器上显示的更好。 通常会写

<meta name="viewport" content="width=device-width, initial-scale=1.0">

content 参数:

  • width viewport 宽度(数值/device-width)
  • height viewport 高度(数值/device-height)
  • initial-scale 初始缩放比例
  • maximum-scale 最大缩放比例
  • minimum-scale 最小缩放比例
  • user-scalable 是否允许用户缩放(yes/no)
  • minimal-ui iOS 7.1 beta 2 中新增属性,可以在页面加载时最小化上下状态栏。这是一个布尔值,可以直接这样写:
    <meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
    

而如果你的网站不是响应式的,请不要使用 initial-scale 或者禁用缩放。

<meta name="viewport" content="width=device-width,user-scalable=yes">

适配 iPhone 6 和 iPhone 6plus 则需要写:

<meta name="viewport" content="width=375">
<meta name="viewport" content="width=414">

大部分 4.7~5 寸的安卓设备的 viewport 宽设为 360px,iPhone 6 上却是 375px,大部分 5.5 寸安卓机器(比如说三星 Note)的 viewport 宽为 400,iPhone 6 plus 上是 414px。

ios 设备

添加到主屏后的标题(iOS 6 新增)

<meta name="apple-mobile-web-app-title" content="标题"> <!-- 添加到主屏后的标题(iOS 6 新增) -->

是否启用 WebApp 全屏模式

<meta name="apple-mobile-web-app-capable" content="yes" /> <!-- 是否启用 WebApp 全屏模式 -->

设置状态栏的背景颜色

<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <!-- 设置状态栏的背景颜色,只有在 `"apple-mobile-web-app-capable" content="yes"` 时生效 -->

只有在 “apple-mobile-web-app-capable” content=”yes” 时生效

content 参数:

  • default 默认值。
  • black 状态栏背景是黑色。
  • black-translucent 状态栏背景是黑色半透明。 如果设置为 default 或 black ,网页内容从状态栏底部开始。 如果设置为 black-translucent ,网页内容充满整个屏幕,顶部会被状态栏遮挡。

禁止数字识自动别为电话号码

<meta name="format-detection" content="telephone=no" /> <!-- 禁止数字识自动别为电话号码 -->

iOS 图标

rel 参数: apple-touch-icon 图片自动处理成圆角和高光等效果。 apple-touch-icon-precomposed 禁止系统自动添加效果,直接显示设计原图。 iPhone 和 iTouch,默认 57×57 像素,必须有

<link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png" /> <!-- iPhone 和 iTouch,默认 57x57 像素,必须有 -->

iPad,72×72 像素,可以没有,但推荐有

<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/apple-touch-icon-72x72-precomposed.png" /> <!-- iPad,72x72 像素,可以没有,但推荐有 -->

Retina iPhone 和 Retina iTouch,114×114 像素,可以没有,但推荐有

<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/apple-touch-icon-114x114-precomposed.png" /> <!-- Retina iPhone 和 Retina iTouch,114x114 像素,可以没有,但推荐有 -->

Retina iPad,144×144 像素,可以没有,但推荐有

<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144x144-precomposed.png" /> <!-- Retina iPad,144x144 像素,可以没有,但推荐有 -->

IOS 图标大小在iPhone 6 plus上是180×180,iPhone 6 是120×120。 适配iPhone 6 plus,则需要在中加上这段

<link rel="apple-touch-icon-precomposed" sizes="180x180" href="retinahd_icon.png">

iOS 启动画面

iPad 的启动画面是不包括状态栏区域的。

iPad 竖屏 768 x 1004(标准分辨率)

<link rel="apple-touch-startup-image" sizes="768x1004" href="/splash-screen-768x1004.png" /> <!-- iPad 竖屏 768 x 1004(标准分辨率) -->

iPad 竖屏 1536×2008(Retina)

<link rel="apple-touch-startup-image" sizes="1536x2008" href="/splash-screen-1536x2008.png" /> <!-- iPad 竖屏 1536x2008(Retina) -->

iPad 横屏 1024×748(标准分辨率)

<link rel="apple-touch-startup-image" sizes="1024x748" href="/Default-Portrait-1024x748.png" /> <!-- iPad 横屏 1024x748(标准分辨率) -->

iPad 横屏 2048×1496(Retina)

<link rel="apple-touch-startup-image" sizes="2048x1496" href="/splash-screen-2048x1496.png" /> <!-- iPad 横屏 2048x1496(Retina) -->

iPhone 和 iPod touch 的启动画面是包含状态栏区域的。

iPhone/iPod Touch 竖屏 320×480 (标准分辨率)

<link rel="apple-touch-startup-image" href="/splash-screen-320x480.png" /> <!-- iPhone/iPod Touch 竖屏 320x480 (标准分辨率) -->

iPhone/iPod Touch 竖屏 640×960 (Retina)

<link rel="apple-touch-startup-image" sizes="640x960" href="/splash-screen-640x960.png" /> <!-- iPhone/iPod Touch 竖屏 640x960 (Retina) -->

iPhone 5/iPod Touch 5 竖屏 640×1136 (Retina)

<link rel="apple-touch-startup-image" sizes="640x1136" href="/splash-screen-640x1136.png" /> <!-- iPhone 5/iPod Touch 5 竖屏 640x1136 (Retina) -->

添加智能 App 广告条 Smart App Banner(iOS 6+ Safari)

<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL"> <!-- 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari) -->

iPhone 6对应的图片大小是750×1294,iPhone 6 Plus 对应的是1242×2148 。

<link rel="apple-touch-startup-image" href="launch6.png" media="(device-width: 375px)">

<link rel="apple-touch-startup-image" href="launch6plus.png" media="(device-width: 414px)">

Windows 8

Windows 8 磁贴颜色

<meta name="msapplication-TileColor" content="#000"/> <!-- Windows 8 磁贴颜色 -->

Windows 8 磁贴图标

<meta name="msapplication-TileImage" content="icon.png"/> <!-- Windows 8 磁贴图标 -->

rss订阅

<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" /> <!-- 添加 RSS 订阅 -->

favicon icon

<link rel="shortcut icon" type="image/ico" href="/favicon.ico" /> <!-- 添加 favicon icon -->

移动端的meta

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection"content="telephone=no, email=no" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" /><!-- 删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" /><!-- 设置苹果工具栏颜色 -->
<meta name="format-detection" content="telphone=no, email=no" /><!-- 忽略页面中的数字识别为电话,忽略email识别 -->
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">
<!-- 适应移动端end -->