ios入门攻略 04篇 C语言基础【分支结构之if语句】

分支结构有两大类语句:一种是if  一种是switch

 

一、

if语句

 

1.*种形式:

 

语法:if(表达式){
语句块;

}

 

语义:如果表达式的结果为真,则执行语句块,否则不执行语句块

 

 

第二种形式:

 

语法:

if(表达式){
语句块1;

}else{
语句块2;

}

 

语义:如果表达式的结果为真,则执行语句块1,否则执行语句块2

语句块1或者语句块2,至少会有一个被执行

 

 

第三种形式:

if语句的嵌套

 

简单来说:就是if语句里面还可以有任意的if语句

 

 

 

第四种形式:

 

语法:

if(表达式1){
语句块1

 

}else if(表达式2){
语句块2

 

}else if(表达式3){
语句块3

}

……………………

else if(表达式n){
语句块n

 

}else{
语句块n+1;

}

 

语义:先判断表达式1,如果成立则执行语句块1,后面的都不执行了,否则继续判断表达式2,如果成立,则执行语句块2,后面的都不执行了,如果不成立则判断语句块3,如果成立则执行语句块3,否则继续往下判断,直到else上面的条件都不满足,就执行语句块n+1;

 

而且我们的这种语法格式是一个整体,上面判断过的内容如果不成立,那么下面判断时已经做了过滤

if语句需要注意的地方:

 

1.if语句后面不要加分号

 

2.if语句的大括号,其实是可以省略的!

 

3.if语句里面可以写任意条语句(必须要有大括号)

 

4.非0的数就是真,0就是假,避免让你的表达式是永真或永假

 

5.if语句里面定义的变量只能在它语句块里面访问

 

6.if语句小括号里面的表达式可以写任意表达式

ios入门攻略 03篇 C语言基础【运算符

一、关系运算符:

>:判断左边表达式是否大于右边表达式,如果大于结果为1,如果小于结果为0

1>3 结果为0   3>1 结果为1

<:判断左边表达式是否小于右边表达式,如果小于结果为1,如果大于结果为0

3<1 结果为0   1<3  结果为1

==:判断左边表达式是否等于右边表达式,如果等于结果为1,如果不等于结果为0

int num1=10,num2=10;  num1==num2; 结果为1

20==10;结果为0

!=:判断左边表达式是否不等于右边表达式,如果不等结果为1,如果等于结果为0

int num1=10,num2=10;  num1!=num2; 结果为0

 

>=:判断左边表达式是否大于或等于右边表达式,如果大于或等于结果为1,否则结果为0

 

<=:判断左边表达式是否小于或等于右边表达式,如果小于或等于结果为1,否则结果为0

 

 

 

二、逻辑运算符:

 

&&:逻辑与 读作并且  左右两边表达式都为真,结果才为真

口诀:1假则假

 

||:逻辑或 读作或者  左右两边表达式有一个为真,结果就是真

口诀:1真则真

 

!:逻辑非  读作取反

口诀:真变假,假变真

 

C语言中非0都为真,0为假

 

例: !5;结果为0

【特别注意】

断路:

右边的表达式不会执行,叫断路

 

断路发生在逻辑运算中:||、&&

 

&&:在左边的表达式为假的时候,发生断路

||:在左边的表达式为真得时候,发生断路

优先级:

!*高 -> 算数运算符 -> 关系运算符 -> &&和|| -> =

 

 

sizeof运算符:

 

计算类型、常量、变量所占的内存空间字节数

ios入门攻略 02篇 C语言基础【常量、变量、scanf函数、算术运算】

一、常量:

固定不变的量

 

两种表示方法:

1.字面量表示法

直接写值就是字面量常量

10;

20 + 10; //常量表达式

 

2.名字表示法

语法:

const 类型 名字 = 值;

 

例:  const int num = 10;

 

num = 30; //会报错!

 

const int num;  //完全可以,垃圾值

num = 40; //这样就会报错。

 

二、 变量:

值可以发生改变的量就叫变量

 

声明变量的方法:

 

1.在声明的就初始化

类型 变量名 = 值;

例:int num = 10;

num = 30; //不会报错,因为变量可以改变

 

2.先声明,后赋值

类型 变量;

变量 = 值;

 

int num;

num = 30;

 

 

变量的命名规范:

1.起名要有意义

2.只能以字母、下划线、美元符号开头,后面接任意的数字、字母、下划线、美元符号(Mac里面可以用中文)

3.不能用关键字作为变量名

4.遵守驼峰命名法:*个单词的首字母小写,后面的每个单词首字母大写

 

 

printf的具体用法:

 

语法:

printf(“格式化字符串”,值列表);

 

常见的格式化控制符:

%d:要输出一个int类型的数据

%ld:要输出一个long类型的数据

%u:输出一个unsigned int类型的数据

%lu:输出一个unsigned long类型的数据

%f:要输出一个float类型的数据

%lf:要输出一个double类型的数据

%c:要输出一个char类型的数据

 

unsigned 修饰的代表无符号的一个整数,不能保存负数,只能存正数

unsigned 可以修饰float double吗?不可以!

unsigned 可以修饰char 吗?           可以! char本身就是正数

 

%d:

重点:

%0md:m代表占用多少位,不足位用0代替.

如果实际位数 >= m ,那么就以实际位数输出,不会添加任何的0

 

%md: m代表占用多少位,不足位用空格代替

如果实际位数 >= m ,那么就以实际位数输出

m为负数就代表在后面添加空格

 

%f:

重点:

%.nf:n代表保留小数点后几位。n是一个整数

 

例:如果要保留小数点后3位

%.3f

 

%m.nf: m代表一共多少列,n代表保留小数点后几位

m<实际位数 就按实际输出(以n为准)

 

不足位用空格代替

 

三、转义符:

改变原来某个字符的原来意义的符号就叫转义符

 

例:%d  \n

所有的格式化控制符

 

\n:换行

\t:水平制表符 空格

\\:输出\

\”:输出”

%%:输出%

 

 

四、scanf函数:

语法:scanf(“格式化控制符”,地址列表);

例:

scanf(“%d”,&int类型的变量);

scanf使用注意

1.可以同时接收多个输入:可以输入的时候以空格区分

2.如果想改变他们的输入方式,就在两个格式化控制符之间加符号,那么输入的时候也必须按这个格式来输入

3.*好不要输入一个数字后立刻接收输入字符

4.如果想用两句scanf来先接收一个数字,再接收一个字符,那么为了防止字符吸收到回车或空格,我们可以在格式化控制符之前加一个空格,或者把缓冲区里的字符全部吸收掉

5.如果scanf需要接收一个数字,那么不管你按多少次回车或者空格,都没用

 

scanf的原理:

1). 用户从控制台输入的数据是先存储在1个叫做缓冲区地方

2). 当scanf函数准备为变量赋值的时候.先看看缓冲区中有没有数据

如果缓冲区中没有合适的数据 才会暂停程序让用户从控制台输入

如果缓冲区中有合适的数据  直接将缓存区中的数据拿出来赋值给变量

 

 

五、算数运算符:

 

+:跟数学一样

-:跟数学一样

*:跟数学一样

/:如果两个操作数都是整数,那么结果一定是整数(就是数学中算得多少只取整数部分),如果操作数有一个是浮点数,那么结果一定是浮点数

%:就是取余数,什么叫余数?除不尽,余下的数就叫余数。

取余的正负性:只取决于左边的那个操作数是正还是负

取余不能用在浮点数

 

 

优先级:

有括号先算括号,先乘除后加减

 

如果同级:从左往右依次运算

 

 

复合运算符:

+=:在原来的值的基础上相加

-=:在原来的值的基础上相减

*=:在原来的值的基础上相乘

/=:在原来的值的基础上相除

%=:在原来的值的基础上取余

 

例: int num = 10;

num += 12;

num %= 12;

 

自增和自减:

 

++和–

 

在原来的值的基础上+1

 

不能对常量进行自增和自减

 

 

前缀的自增(自减)以及后缀的自增(自减)

 

前缀:先自增(自减)再参与运算

后缀:先用原来的值参与运算,后自增(自减)

 

 

补充:同时声明多个变量,用逗号隔开

 

int num1,num2; //int num1; int num2;

 

int num3=10,num4=20;

 

逗号表达式:

语法:

(表达式1,表达式2,………………表达式n);

 

语义:从左往右每个表达式都会执行,但是总体的表达式的值,只取*后一个表达式的结果

iOS入门攻略 01篇【电脑基本知识+快捷键+终端命令+Xcode+C语言数据类型】

一、电脑的基本知识:

电脑是由硬件和软件组成的

 

硬件:看得见摸得着的具体东西

cpu、内存、硬盘、显卡、主板、声卡、网卡等等

 

软件:看不见的,必须要开机以后才能见到及用到

操作系统:windows linux unix mac os iOS

应用软件:QQ、快播、酷狗

 

主要三大件:

 

cpu:主要是处理运算的,相当于大脑

内存:连接cpu和硬盘上的数据

硬盘:存储数据的,永久存储

执行程序或者处理任何数据都是先由硬盘读取到内存,再由内存交给cpu处理

为什么不直接由硬盘交给CPU去处理?因为速度太慢!

 

显卡:负责处理图形运算

声卡:处理声音

网卡:处理网络

iOS:是苹果针对iPhone、ipad、ipod的操作系统

 

iOS开发:在iOS系统上开发它的app

二、快捷键

Command+Control+空格   弹出emoji表情

Command+W                     关闭窗口

Command+Q                      退出程序

Command+空格                 切换输入法

Command+delete                移到废纸篓

Control+空格                       打开搜索

 

Xcode常见的快捷键:

Command + /                    快速注释

Command + option + “←”    折叠代码

Command + option + “→”    展开代码

Command + R        运行

Command + .         停止

Command + ~         同一程序内,不同页面切换

Control + i               按格式化排列代码

Command+shift+z  重做

三、终端命令

Control+空格:打开搜索,输入:“终端”,回车进入

touch 文件名.文件格式:创建一个文件

open  文件名.文件格式:打开一个文件

cd 文件夹路径:进入到一个文件夹

pwd:显示终端当前进入到得路径
./:代表当前所在路径

举例:怎样在屏幕上,显示一句“哈哈哈哈哈”呢?

解决:

现在桌面新建123的文件夹

cd Desktop/ 123:   进入桌面的123文件夹

1.新建一个文本文件,格式为.c

2.打开这个文件,并输入以下代码 #include <stdio.h>

 

int main(){

printf(“哈哈哈哈哈\n”);

return 0; }

3.在终端输入跳转到这个文件所在路径,然后输入

 

cc 文件名.c -c

敲完上面的命令后我们发现在这个.c文件的同目录下出现了一个同名的.o文件

 

4.再然后我们继续在终端输入

 

cc 文件名.o,

 

会发现同目录下又多出来一个 a.out的文件

6.在终端运行这个a.out文件即可发现效果 ,输入

 

./a.out

分析:

#include<stdio.h> 代表引入一个系统头文件,这个头文件名字叫stdio.h

这个头文件里包含一些输入/输出的信息

int main(){ }

这是一个主函数,作用是:告诉系统你的程序代码的执行顺序。程序里面有且只能有一个 main函数

printf(” 哈哈哈哈哈\n”);

这句代码是让屏幕输出一句话,这句话的内容叫“哈哈哈哈哈”

写代码特别注意:

1.不要忘记导入头文件 #include <stdio.h>
2.main函数只能有一个,而且必须要有
3.语句后面千万要记得加分号,必须是英文(;) main函数里面的叫语句
4.main函数后面的大括号一定要成对出现,而且是英文的
5.return o 可以省略,一定要放在*后,否则后面的代码不能被执行
6.\n是换行的
注释://单行注释,/*多行注释*/(写在开头,表达这个文件总体实现什么样的功能)

四、C语言转化为机器语言

源代码:程序员自己写代码,.c文件就是C语言的源代码文件 (称之为源文件) 编译:把源代码翻译成0、1,

生成一个 .o  目标文件

调用编译器命令为:cc xxxx.c -c     ->>>编译步骤

链接:把目标文件和库函数进行整合生成一个 .out  可执行文件

调用编译器命令为:cc xxxx.o         ->>>链接步骤

五、用Xcode编写程序

1.运行Xcode,在接下来的图片中点击

 

选择create a new Xcode project,然后选择OS X中的Application,再选择Command Line Tool

点击Next,然后来到下个界面 ,填写,再然后找到main.c文件,编写代码

直接运行程序

2.注释:

 

1、单行注释:

//注释的内容

功能://符号右边的一行内容被编译器忽略(按了回车才算换行)

快捷键:Command + /  快速注释

2、多行注释:

/* 注释的内容 */

功能:/* */符号里面的所有内容都被编译器忽略

六、C语言中的数据类型

1.整型:用于准确地表示整数,根据表示范围的不同分为以下三种:

短整型(short) <整型(int) < 长整型(long)

 

2.实型(浮点型):用于标识实数(小数)根据范围和精度不同分为以下两种:

单精度浮点数(float) <双精度浮点数(double)

 

3.字符型:用来

iOS基础教程:记录从零开始到APP发布过程

目录

写在前面

本来是做 Android 开发、兼职 Unity 开发,公司有业务需求要做 iOS,还好需求比较简单:做一个 WebView + AR 的 App。WebView 感觉比较简单,AR 的话就用 EasyAR 吧,免费无水印值得推荐。

但是。。。

做完后要改需求,原因是有人告知单纯的 WebView App 发布的时候审核不会通过。为了不蹚浑水还是直接重做吧:首页是一个全屏 Banner,内容是日历加下方的图片,点击到 AR 页面扫描首页的图片可以看到视频。

作为一只程序猿要有各种东西都能做,各种代码都会码的觉悟,仗着有点代码基础(Java C#)就直接开搞。

一. 准备工作

  • 硬件:一台 Mac,Mac Mini 也凑合(公司就几台Mini)…测试机若干,测试 AR 必须用真机。顺手的鼠标键盘鼠标垫…
  • 软件:XCode (我这里的是Version 9.1),CocoaPods(用于引用第三方库)
  • 账号和证书:
  1. 想要发布一个 iOS App,首先需要一个开发者账号,个人级的价值 $99。也就是大家常说的 99美元账号:

ios苹果开发者账号申请流程(2017)

  1. 有了账号就可以申请证书,有证书才能在真机上调试你的 App。顺带提一下,没有付钱的或者过期的账号是没有证书等选项的…别问我是怎么知道的。证书的申请也是一大串的事情要做,不过仔细看教程一步一步来很好理解的。

*新的 iOS 申请证书与发布流程(2016.12)

二. 基础知识

  • 基础语法:
    语法还是蛮重要的,本人没有看语法直接上的。开始写代码全靠猜和 Copy,走了很多弯路,现在看来还不如老老实实看看语法。不过看归看,本着效率优先建议看个大概,用的时候再回来仔细找相关的研究。

Objective C 基础知识 | 菜鸟教程

十分钟让你明白Objective-C的语法(和Java、C++的对比)

  • 视频教程:
    这个视频教程比较基础,像我这样的纯小白看的很开心。

iOS8 App开发快速入门

下面这个就比较全面了,但是也有许多我没用上的知识。

iOS开发全套教程(享精品公开课)

所以综合一下,建议是不需要全部看完,根据项目需求来学习相关知识,毕竟先做出项目才是王道。

三. HelloWorld

因为 EasyAR 提供 iOS 版本的示例代码,所以在现有的代码基础上进行二次开发,接下来根据项目需求来一步一步进行开发。

3.1 建立 WebView

*版的 App 首页就是个 WebView,本小白刚开始做的时候直接在 Main.storyboard 里面拖放 UIWebView,现在看来是 Low 上加 Low…

首先来说,不建议在 storyboard 直接做事情,因为使用 storyboard 编程比较适合一个人开发,而且维护性不高。全部用代码则会显得一目了然,代码阅读性比较高。但是 storyboard 也有很多优势,同时有很多团队支持使用 storyboard 开发。所以我们要根据具体情况使用合适的方法来完成一个优雅的项目。

再者,UIWebView 是比较老的一个控件,而比较新的 WebView 控件则是 WKWebView,无论从内存占用和使用体验来说都优于 UIWebView。

下面是我找到使用简单,代码清晰,而且带前进后退和进度条的 WKWebView 使用实例,还有源码哦。使用的时候根据需求修改各个控件的位置和大小就可以了。

iOS WKWebView添加网页加载进度条

3.2 添加标题 View

%title插图%num

titleBar

项目需求 WebView 上面需要一个标题栏,一个光秃秃的 WebView 确实也不甚好看,标题栏是一个简单的图片,用 UIImageView 就可以啦。

  1. // 状态栏(statusbar)
  2. CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
  3. // 当前view的宽和高
  4. CGFloat w = self.view.bounds.size.width;
  5. CGFloat h = self.view.bounds.size.height;
  6. // 添加title
  7. UIImageView *titleImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, rectStatus.size.height, w, 60)];
  8. [titleImage setImage:[UIImage imageNamed:@”ic_title”]];
  9. [self.view addSubview:titleImage];

代码很好理解,首先获取手机状态栏的属性,因为它的高度需要用到。然后获取当前 App 显示区域的 View 的宽和高,*后添加标题栏的icon。短短的一段代码包含了很多信息:

  • CGRect:简单的理解为包含了某 View 的原点和 Size 的属性,上文代码中是获得了状态栏的这个属性。
  • CGFloat:只是对float或double的typedef定义,看作是数据类型就好,代码中是储存了当前View的宽和高。

OC 获取iOS屏幕尺寸大小

  • UIImageView:基础控件使用,不再多说。
  • CGRectMake:实例化某控件时来定义视图的起点坐标以及宽度和高度等属性的参数。上面代码中 titleImage 的 CGRectMake:
    CGRectMake(0, rectStatus.size.height, w, 60)
    *个参数 0,说明该 View 起点 x 轴为 0,也就是屏幕*左侧。
    第二个参数 rectStatus.size.height 这个是状态栏的高度,说明 titleImage 的 y 轴起点为状态栏高度那一行,与 x 轴的点结合起来就确定了 titleImage 的起点。
    第三个参数是 View 的宽度,我希望它铺满屏幕,所以是屏幕宽度 w。
    第四个参数是 View 的高度,自己指定。

iPhone开发中Cocoa中的CGRectMake具体用法

  • 指定 UIImageView 的图片资源:
    [titleImage setImage:[UIImage imageNamed:@"ic_title"]];
    资源存储在 Assets.xcassets 资源文件夹,图片名称为 ic_title。

3.3 添加 UIButton 的点击和返回

上面的 titleBar 有左右两个按钮,左边的按钮用于跳转到当天时间的页面,右边的跳转到 AR 界面,没有美工啊…暂时先实现功能吧,按钮的点击响应什么的,以后再说。

  1. – (void)viewDidLoad {
  2. [super viewDidLoad];
  3. UIButton *todayButton = [[UIButton alloc] initWithFrame:CGRectMake(0, rectStatus.size.height, w*0.18, titleHeight)];
  4. //设置按钮点击触发动作跳转
  5. [todayButton addTarget:self action:@selector(goToday:) forControlEvents:UIControlEventTouchUpInside];
  6. [self.view addSubview:todayButton];
  7. UIButton *arButton = [[UIButton alloc] initWithFrame:CGRectMake(w-w*0.18, rectStatus.size.height, w*0.18, titleHeight)];
  8. //设置按钮点击触发动作跳转
  9. [arButton addTarget:self action:@selector(goAR:) forControlEvents:UIControlEventTouchUpInside];
  10. [self.view addSubview:arButton];
  11. }
  12. – (void)goToday:(UIButton*) sender
  13. {
  14. }
  15. – (void)goAR:(UIButton*) sender
  16. {
  17. // 实例化要跳转的 ViewController
  18. ViewController *subView = [[ViewController alloc] init];
  19. // 设置跳转动画类型
  20. [subView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
  21. // 执行跳转
  22. [self presentModalViewController:subView animated:YES];
  23. }

代码比较简单,实例化两个按钮分别绑定不用的方法,goToday() 聊不到所以省略掉。goAR() 注释写的比较明白,这种跳转比较简单不需要 Navigationbar,而从 AR 界面跳转回来是这样的:

  1. – (void)viewDidLoad {
  2. [super viewDidLoad];
  3. UIImage * buttonImage = [UIImage imageNamed:@”ic_back”];
  4. self.backButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 30, 30, 30)];
  5. // 设置按钮的标题文字以及颜色
  6. //[self.backButton setTitle:@”返回” forState:UIControlStateNormal];
  7. //[self.backButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  8. // 设置按钮背景图
  9. [self.backButton setImage:buttonImage forState:UIControlStateNormal];
  10. //设置按钮点击触发动作跳转
  11. [self.backButton addTarget:self action:@selector(backToView:) forControlEvents:UIControlEventTouchUpInside];
  12. [self.view addSubview:self.backButton];
  13. }
  14. – (void) backToView:(UIButton*) sender
  15. {
  16. [self dismissViewControllerAnimated:YES completion:nil];
  17. }

与其说是跳转回来,不如说是把当前的 View 隐藏更为贴切,更多关于界面跳转可以参考下文或自行度娘:

iOS ViewController跳转界面的几种方法简单总结

3.4 iOS 消息传递与小菊花

需求:扫描识别到图片之后要播放视频,但是视频文件比较大,所以在识别到图片的时候开始旋转小菊花并在线缓存视频,开始播放视频或者离开识别图隐藏小菊花。
找到的资料是这样的:

IOS中消息传递的8种方式

  • Notification 传递消息
    这么多方法对于我这样的小白来说是一脸懵逼的,*后用了比较简单的 Notification (盲通信) 来做。Notification 的思路很简单:A 要接收 B 的消息,那么让 A 来设置监听,A 销毁时移除监听。等有消息需要传递的时候 B 直接发送,A 就能收到并调用具体方法。

Class B 发现识别图开始发送消息

  1. – (void)onFound
  2. {
  3. // 发现识别图发送消息显示并播放小菊花动画
  4. [[NSNotificationCenter defaultCenter] postNotificationName:@“showIndicator” object:nil];
  5. if (prepared) {
  6. // 视频马上就要播放,隐藏小菊花动画
  7. [[NSNotificationCenter defaultCenter] postNotificationName:@“closeIndicator” object:nil];
  8. }
  9. }

Class A 设置监听并根据发来的消息展示和隐藏小菊花

  1. – (void)viewDidLoad {
  2. // 注册观察者显示
  3. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showIndicator) name:@”showIndicator” object:nil];
  4. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeIndicator) name:@”closeIndicator” object:nil];
  5. }
  6. //接受消息显示小菊花
  7. – (void)showIndicator
  8. {
  9. dispatch_async(dispatch_get_main_queue(), ^{
  10. //do your UI
  11. [self.activityIndicator startAnimating];
  12. self.textView.text = @”Loading…”;
  13. });
  14. }
  15. //接受消息关闭小菊花
  16. – (void)closeIndicator
  17. {
  18. dispatch_async(dispatch_get_main_queue(), ^{
  19. //do your UI
  20. [self.activityIndicator stopAnimating];
  21. self.textView.text = @””;
  22. });
  23. }

为求方便直接注册监听两个方法,其实更好的写法是只监听一个方法,Class B 发送 Notification 时带参数,Class A 根据不同参数作不同的处理。

iOS NSNotification 消息通知的3种方式

  • 小菊花(UIActivityIndicatorView)的使用
    小菊花的用法比较简单,先创建需要显示的时候直接调用就好。
  1. // 创建全局变量
  2. @property (strong, nonatomic) UIActivityIndicatorView *activityIndicator;
  3. – (void)viewDidLoad {
  4. // 小菊花设置
  5. self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhiteLarge)];
  6. // 这个是用来设置小菊花的中心点,很多 View 也可以设置
  7. self.activityIndicator.center = CGPointMake(width/2,height/2-40);
  8. }
  9. // 显示小菊花
  10. [self.activityIndicator startAnimating];
  11. // 隐藏小菊花
  12. [self.activityIndicator stopAnimating];

自定义外观和更多使用方式可以参考文章:

iOS UIActivityIndicatorView用法(菊花旋转)

3.5 CocoaPods 以及第三方库的使用

主要功能和 WebView 做好之后要改需求,原因上文已经提到过,接下来要做一个全屏滑动、内容为 2018 年日历的 Banner,以及根据当前的日期跳转到指定的日历页面,用下面的代码获取日期后跳转到 Banner 的某一页就可以了。

  • 获取系统日期并转换格式
  1. //获取当前时间日期并返回 int
  2. – (int)getDate:(NSString *)dateType{
  3. NSDate *date=[NSDate date];
  4. NSDateFormatter *format1=[[NSDateFormatter alloc] init];
  5. if([dateType isEqualToString:@”mouth”]){
  6. [format1 setDateFormat:@”MM”];
  7. }else if([dateType isEqualToString:@”day”]){
  8. [format1 setDateFormat:@”dd”];
  9. }else{
  10. [format1 setDateFormat:@”MMdd”];
  11. }
  12. // @”yyyy-MM-dd hh:mm:ss”
  13. NSString *dateStr = [format1 stringFromDate:date];
  14. return [dateStr intValue];
  15. }
  16. // 获取日期并返回 NSString。可以返回具体周几
  17. – (NSString*) getAllDate{
  18. NSDate*date = [NSDate date];
  19. NSCalendar*calendar = [NSCalendar currentCalendar];
  20. NSDateComponents*comps;
  21. comps =[calendar components:(NSCalendarUnitWeekOfYear | NSCalendarUnitWeekday |NSCalendarUnitWeekdayOrdinal)
  22. fromDate:date];
  23. NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init] ;
  24. // [dateFormatter setDateFormat:@”YYYY-MM-dd EEEE”];
  25. [dateFormatter setDateFormat:@”MMM dd YYYY”];
  26. NSString *currentTimeString = [dateFormatter stringFromDate:date];
  27. return currentTimeString;
  28. }

然后就是 Banner 了,让我自己去写这样一个 Banner 是不太可能的,首先技术不到家而且也没啥时间去慢慢研究着写,所以使用第三方库是*合适的。于是在 GayHub 找各种 Banner 库,发现大家都在用 Pod 导入。

  • CocoaPods 安装

查了下发现 Pod 是用来导入第三方库的工具,全称 CocoaPods。虽然直接下载Library 放到项目里可以用但是保不齐第三方库又引用了其它库,难道都要一个一个 Copy 进项目?况且这种东西向来是学了不亏而且以后做 iOS 开发总要用到的,所以还是老老实实学着怎么安装和使用吧。

安装 CocoaPods 之前需要先安装 Ruby 运行环境,然后才能命令行安装 CocoaPods:

Ruby运行环境:如何在Mac OS X上安装 Ruby运行环境

接下来参考下文来安装 CocoaPods

CocoaPods:看一遍就会的CocoaPods的安装和使用教程

安装过程中可能会报各种各样的错误,不要着急,参考下方资料。如果资料不能解决你的问题,Google 或 度娘 你的报错Log。

*详细的CocoaPods安装教程附常见错误总结

安装完毕就可以使用 CocoaPods 了,多去 GayHub 转转,总有各种各样的惊喜等着你。

3.6 其它问题

  • App 启动图
    记录一个问题,本来好好的启动图,到了大屏手机忽然就不显示了。后来把 2X 3X 的都放进去就正常显示了…常识哇。
  • 状态栏文字主题
    某些设备默认状态栏文字是黑色的,加上下面的代码就可以改成白色字体。但是状态栏背景色修改起来问题颇多,这里提供一个小办法,在 storyboard 当前 ViewControler 界面顶添加一个的纯色背景,图片亦可,横铺满屏幕即可:
  1. //设置状态栏字体样式
  2. – (UIStatusBarStyle)preferredStatusBarStyle{
  3. return UIStatusBarStyleLightContent;//白色
  4. }
  • App Icon
    有很多网站提供自动生成 App Icon 的功能,扔进去 1024X1024 的图标就可以生成一套图标,很方便。类似的网站还有很多就不一一列举了。
    移动应用图标生成工具,一键生成所有尺寸的应用图标

四. App 发布

这里有一个很详细的教程:

iOS App上架流程(2016详细版)

跟着教程一步一步做终于是把 App 扔上去审核了,感觉比较难找的就是 iTunesConnect 放个链接标记一下。

到这里就完成了项目需求。文中引用了各种连接,就不一一提示引用了,感谢那么多前辈的无私分享,也祝大家都能完成一个完美的 App。

iOS开发60分钟入门

本文面向已有其它语言(如Java,C,PHP,Javascript)编程经验的iOS开发初学者,初衷在于让我的同事一小时内了解如何开始开发iOS App,学习目标包括:

  • 能使用Xcode IDE、模拟器
  • 能修改、调试已有iOS App
  • 能在已有应用内创建新模块
  • 能创建新应用
  • 能发布应用到App Store

本文不包含任何高级的iOS开发知识,已学会iOS开发的同学不要看,看完这篇文章学会了的同学也不用再看了。

不仅是学习一门新语言

有过脚本开发经验的人(如Javascript,PHP,Shell)在刚开始学习iOS开发的时候,会觉得iOS开发的学习曲线比脚本语言要高,是的,这种感觉是对的。因为学iOS开发,不仅是学习一门新语言,它包括:

  • 一门语言:Objective-C
  • 一个框架:Cocoa Touch
  • 一个IDE:Xcode

初学脚本语言通常不会来绘制图形界面、与人交互,iOS如果不做图形界面,像脚本语言一样处理文本操作数据库,就没啥意思了。

所以,过去我写别的新手入门教程,通常都是写《XXX入门15分钟教程》,而iOS就要花数倍的时间来写了。

环境准备

做iOS开发一定要有苹果的软件环境:Mac OS操作系统、Objective-C编译器、设备模拟器等,开发工具倒不一定要用Xcode,只要是个源代码编辑工具就行(vim都行,只是没Xcode那么多功能)。

Mac OS

拥有Mac OS环境*简单的方法是找一台苹果电脑,包括iMac, MacBook Pro, MacBook Air, Mac Mini,但不包括苹果的移动设备(iPod Touch, iPhone, iPad, iPad Mini,它们运行的是iOS系统,不是Mac OS),苹果电脑在出厂的时候就会预装Mac OS,目前*新版本是Mac OS X 10.8,主流的版本还有Mac OS X 10.6、Max OS X 10.7。

如果囊中羞涩,可以借一台,或者上淘宝买个二手的。

黑苹果

提到iOS开发入门,似乎没办法不说黑苹果。所谓黑苹果,就是把Mac OS改造后安装在非苹果的硬件上,这是违反DMCA法案的,黑苹果的更多资料,可以在维基上找到

苹果电脑价格高,国内软件开发者生存压力大,所以黑苹果在国内也有一些真实的存在,国外当然也有啦。

黑苹果基本可以胜任iOS开发,但有一些问题:

  • 安装黑苹果是非法的
  • 个人行为苹果公司一般不会追究,但会遭同行的鄙视
  • 黑苹果超级难装,挑硬件。即使完全相同的型号,相同的批次,也有可能A机器装上了,B机器装不上
  • 黑苹果系统多少都存在一些使用上的问题,像驱动Bug啦、待机恢复蓝屏啦、上网浏览有问题啦
  • 黑苹果不能随意升级,可能升级一次safari就导致整个系统崩溃了

上面这些虽然不会直接影响Xcode写代码、模拟器测试,但写着写着想上网查个东西的时候,safari不能翻页,确实挺影响心情的。所以,钱包允许的前提下,还是搞个苹果电脑省心一些。

Xcode 和 模拟器

Xcode可以在苹果官网免费下载:Xcode下载地址

安装Xcode时会自动安装iOS SDK和模拟器。

这么强大的IDE居然是免费的,还是挺让人开心的。

从改一个现成的应用开始吧

学一门新软件开发技能,能够*时间做出一个可运行的产品非常重要,有助于给自己正面激励,我上大学的时候,有很多次想学一门新语言,往往花了半个月,还沉浸在数据类型和语法字典里,连*个Hello World都没做出来。

这一次,就让我们从改一个现成的应用开始吧。

下载

首先,我们从苹果开发者中心下载一个示例代码回来。我选了ToolBarSearch。

在本文档的末尾,还有一些其它的网址可以下载开源iOS产品或者代码段,但我试了一下,还是Apple Sample Code*容易成功。

下载回来的zip文件*好保存在”下载”或者”文稿”目录里,因为在Mac OS 10.8以前,有些目录(例如/var/private/tmp)在Finder中是看不到的,要通过Finder的“前往 > 前往文件夹”功能才能进入。

打开

有三种方式可以打开一个iOS Project

双击project文件

打开Finder,进入刚刚下载解压的ToolBarSearch目录,找到ToolBarSearch.Xcodeproj文件,双击之,Xcode会自动启动,并打开这个项目

在Xcode里选择Project打开

  • 在Xcode没启动的情况下(如果Xcode已经启动了,就先按Command Q退出),启动Xcode,会弹出“Welcome to Xcode”的欢迎页,点击左下角的“Open Other”按钮,找到ToolBarSearch目录,双击ToolBarSearch目录,或者双击ToolBarSearch.Xcodeproj文件都可以
  • 如果Xcode处于打开状态,可以点击其菜单栏的File -> Open,或者File -> Open Recent,然后再选择要打开的项目

通过命令行打开

在Mac OS 10.8以前,有些目录(例如/var/private/tmp),在Finder和Xcode的File > Open对话框中,点击鼠标是找不到的,这时候就要通过命令行终端来打开了。

打开终端,执行:

  1. cd /ToolBarSearch的父目录/ToolBarSearch
  2. open -a Xcode

open -a是mac os的系统命令,除了iOS项目,别的项目也可以这样打开。

运行刚下载的应用

点击Xcode左上角的Run按钮(或者同时按下Comman和R键),Xcode会编译源码并在模拟器中运行这个应用。

编译成功会在屏幕上淡淡地显示“Build Succeeded”。反之,失败就显示“Build Failed”且不启动模拟器。

修改

在模拟器上看到“Performed search using…”了吧,下面我们改掉它。

  • 在Xcode左上角的Run按钮下方,有一排小按钮,从左到右第三个是一个放大镜图标,鼠标移上去会显示“Show the Search Navigator”,点一下它,打开搜索界面,在它下方出现的Find输入框中输入“performed”
  • 搜索结果只有一条:ToolbarSearchViewController.m,点文件名下方被高亮的“Performed”字串,右侧代码编辑区会自动打开这个文件,并滚动屏幕,使包含“Performed”的这一行出现在编辑区的中间。
  • 修改双引号里的字串,随便改成啥,然后按“Command S”保存。

当然,这些操作,你也可以在终端下通过grep和vim完成。

运行修改后的应用

按Command R运行,看看,是不是看到效果啦?

是的,修改一个应用就这么简单。

Objective-C

Objective-C是苹果应用软件(包括苹果电脑上的Mac OS App和移动设备上的iOS App)的开发语言。它是一种面向对象的编程语言。

苹果公司还提供了一个软件,叫Interface Builder,简称IB,用于可视化的界面制作,就像用Dreamweaver做网页,或者像Visual Basic做桌面软件一样。后来IB就整合进了Xcode,成了Xcode的一部分。这篇文档不讲IB,只讲Objective-C,因为:

  • 基本上,每一本讲iOS开发的书(纸质书、电子书),都有大量的截图一步一步教如何用IB开发iOS应用,而讲Objective-C开发应用的书却没有那么多。
  • IB可以用来直观方便地画界面、设置控件属性、建立代码与控件的联系,但后台的业务逻辑和数据处理仍然要靠Objective-C,可见,不管用不用IB,Objective-C都是绕不过去的。

C的超集

Objective-C扩展了ANSI C,是C的超集,也就是说:

  • 任何C源程序,不经修改,即可通过Objective-C编译器成功编译
  • Objective-C源程序中可以直接使用任何C语言代码

除了面向对象有语法是SmallTalk风格的(下面会讲到),其它非面向对象的语法、数据类型,与C完全相同,所以本文就不再赘述。 来看一个经典的Hello World示例吧:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, char *argv[]){
  3. @autoreleasepool{
  4. NSLog(@”Hello World!”);
  5. }
  6. return 0;
  7. }

是不是仿佛穿越回了大一学习C语言的时代,看起来和C几乎没有区别,是吧?是的,因为还没用到它的面向对象特性,哈哈!

SmallTalk的消息传递语法风格

Objective-C的面向对象语法源自SmallTalk,消息传递(Message Passing)风格。在源码风格方面,这是它与C Family语言(包括C/C++、Java、PHP)差别*大的地方。

在Java、C++世界,我们调用一个对象的某方法,在Objective-C里,这称作给类型发送一个消息,这可不仅仅是文字游戏,他们的技术细节也是不同的。

在Java里,对象和方法关系非常严格,一个方法必须属于一个类/对象,否则编译是要报错的。而在Objective-C里,类型和消息的关系比较松散,消息处理到运行时(runtime)才会动态决定,给类型发送一个它无法处理的消息,也只会抛出一个异常,而不会挂掉。

[obj undefinedMethod];

在代码里调用没定义的方法(这是Java世界的习惯说法啊,专业的叫法是,给obj对象传递它无法处理的消息),Xcode会警告,但编译能成功,运行的时候会出错。它会输出这样一个错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSObject undefinedMethod]: unrecognized selector sent to instance 0x8871710'

类似Java的OOP概念

Objective-C中一些面向对象的概念,也可以在Java中找到类似的实现(只能说是类似,不是完全相同),我的读者基本都是Java和PHP程序员,我会在下文中尽量用Java的概念来类比。

GoogleCode上有人整理了Java和Objective-C的概念、数据类型对应表,参见这里

字符串

Objective-C里有字符串是由双引号包裹,并在引号前加一个@符号,例如:

  1. title = @“Hello”;
  2. if(title == @“hello”) {}

PHP程序员要注意,在这里不能用单引号,即使只有一个字符也不能用。Objective-C与Java、C一样,双引号表示字符串。

函数调用

前文述及,不涉及面向对象时,它和C是完全一样的。以下是几个函数调用的示例:

不带参数

startedBlock();

带参数

  1. NSLog(@“decrypted string: %@”, str);
  2. CGRectMake(0,0,0,0);

传递消息给类/实例方法

不带参数

[obj method];

对应的Java版本

obj.method();

带一个参数:

[counter increase:1];

对应的Java版本

counter.increase(1);

带多个参数

对C Family程序员来说,这是*难接受的,*反人类的:

  1. – (void) setColorToRed: (float)red Green: (float)green Blue:(float)blue {…} //定义方法
  2. [myObj setColorToRed: 1.0 Green: 0.8 Blue: 0.2]; //调用方法

对应的Java版

  1. public void setColorToRedGreenBlue(float red, float green, float blue) {…}
  2. myObj.setColorToRedGreenBlue(1.0, 0.8, 0.2);

消息嵌套

UINavigationBar *bar = [[[UINavigationBar alloc] init] autorelease];

对应的Java版

UINavigationBar bar = UINavigationBar.alloc().init().autorelease();//Java没有指针,所以星号去掉了

接口和实现

Objective-C的类分为接口定义和实现两个部分。接口定义(Interface)放在头文件中,文件扩展名是.h,实现(implementation)放在实现文件中,文件扩展名是.m(也有.mm的扩展名,表示Objective-C和C++混编的代码)。

接口定义也可以写在.m文件中,但*好不要这么干

需要注意的是,与Objective-C的interface概念*接近的是C和C++里的头文件,它与implementation是成双成对出现的,作用是声明类的成员变量和方法。它与Java的interface概念完全不同:

  • Objective-C里,interface有且只有一个实现,Java的interface可以有0-N个实现
  • Objective-C里,interface可以定义成员属性,Java里不可以

在Objective-C里,和Java的Interface概念相似的是Protocol,下文会讲到。

请看示例:

Interface

  1. @interface MyClass {
  2. int memberVar1;
  3. id memberVar2;
  4. }
  5. -(return_type) instance_method1;
  6. -(return_type) instance_method2: (int) p1;
  7. -(return_type) instance_method3: (int) p1 andPar: (int) p2;
  8. @end

Implementation

  1. @implementation MyClass {
  2. int memberVar3;
  3. }
  4. (return_type) instance_method1 {
  5. ….
  6. }
  7. -(return_type) instance_method2: (int) p1 {
  8. ….
  9. }
  10. -(return_type) instance_method3: (int) p1 andPar: (int) p2 {
  11. ….
  12. }
  13. @end

接口和实现以@interface、@implementation开头,都以@end结束。“@”符号在Objective-C中是个很神奇的符号。

冒号也是方法名的一部分,method和method:是两个不同的方法名,不是overload,第二个带参数。

上述代码对应的Java版:

  1. public class MyClass {
  2. protected int memberVar1;
  3. protected pointer memberVar2;
  4. private int memberVar3;
  5. public (return_type) instance_method1() {
  6. ….
  7. }
  8. public (return_type) instance_method2(int p1) {
  9. ….
  10. }
  11. public (return_type) instance_method3andPar(int p1, int p2) {
  12. ….
  13. }
  14. }

私有方法和公开方法

写在.h头文件里的方法都是公开的,Objective-C里没有私有方法的概念(没有你说个蛋啊,哈哈哈哈)。

官方并没有提到Objective-C怎么实现私有方法,我查阅了stackoverflow,统一的答案是,要实现私有方法的效果只能借助Category,不过,根据我的测试,即使采用了Category,也不能阻止外部的代码调用这个“私有方法”,只是Xcode不支持“私有方法”的自动完成,并会有警告提示,运行的时候,还是会成功的。各位看官知道有这么回事就可以了,这里不深讲。

变量和属性

类方法和实例方法

类方法

类方法就是Java、PHP里的Static Method,不用实例化就能调。类方法有一个加号前缀。 示例:

类定义

  1. @interface MyClass
  2. +(void) sayHello;
  3. @end
  4. @implementation MyClass
  5. +(void) sayHello {
  6. NSLog(@“Hello, World”);
  7. }
  8. @end

使用

[MyClass sayHello];
实例方法

实例方法就是Java、PHP里的普通方法,必须实例化才能调。实例方法有一个减号前缀。 示例:

类定义

  1. @interface MyClass : NSObject
  2. -(void) sayHello;
  3. @end
  4. @implementation MyClass
  5. -(void) sayHello {
  6. NSLog(@“Hello, World”);
  7. }
  8. @end

使用

  1. mycls = [MyClass new];
  2. [mycls sayHello];

Selector

selector就是一个方法指针,类似PHP里的动态方法名:

  1. <?php
  2. class Hello {
  3. public function sayHello() {}
  4. public function test() {
  5. $fun_name = “sayHello”;
  6. $this->$fun_name();
  7. }
  8. }

在Objective-C里,selector主要用来做两类事情:

绑定控件触发的动作
  1. @implementation DemoViewController
  2. – (void)downButtonPressed:(id)sender {//响应“按钮被按下事件”的方法
  3. UIButton *button = (UIButton*)sender;
  4. [button setSelected:YES];
  5. }
  6. – (void)drawAnButton {
  7. UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
  8. btn.frame = _frame;
  9. btn.tag = 1;
  10. btn.backgroundColor = [UIColor clearColor];
  11. [btn addTarget: self
  12. action: @selector(downButtonPressed:)
  13. forControlEvents: UIControlEventTouchUpInside];//当这个按钮被按下时,触发downButtonPressed:方法
  14. }
  15. @end

延时异步执行

  1. @implementation ETHotDealViewController
  2. – (void)viewDidLoad {
  3. //获取数据源
  4. HotDealDataSource *ds = [[HotDealDataSource alloc]init];
  5. [ds reload];
  6. _items = ds.items;
  7. [self performSelector: @selector(refreshTable)
  8. withObject: self
  9. afterDelay: 0.5];//延迟0.5秒调用refreshTable方法
  10. }
  11. -(void)refreshTable
  12. {
  13. [self.tableView reloadData];
  14. }
  15. @end

这个例子中,获取数据源是通过ASIHTTP组件异步调用服务端HTTP接口,refreshTable要用到数据源返回回来的数据,如果不延迟0.5秒,就会立刻执行,执行的时候数据还在路上呢,页面就要变空白了。

继承

继承是写在Interface定义里面的。语法为:子类名在左,父类名在右,中间用冒号分隔。 示例:

  1. @interface MyClass : NSObject
  2. @end

对应的Java版本是:

  1. public class MyClass extends NSObject {
  2. }

协议(Protocol)

就是Java、PHP里的Interface。

协议的定义

协议的定义用@protocol关键字:

  1. @protocol Printable
  2. -(void)print:(NSString)str;
  3. @end

对应的Java版本是:

  1. publilc interface Printable {
  2. public void print(String str);
  3. }
协议的继承

协议本身也可以继承别的协议:

  1. @protocol Printable <NSObject>
  2. -(void)print:(NSString)str;
  3. @end

对应的Java版本:

  1. public interface Printable extends NSObject {
  2. public void print (String str);
  3. }
可选方法

协议可以包含可选方法,顾名思义,可选方法可以不被类实现:

  1. @protocol Printable
  2. @optional
  3. -(void)print:(NSString)str;
  4. @end

加了@optional关键字,一个类在implements这个协议时,便可以不实现print:方法。

Java里没有类似的实现,除了Collection里会有一些方法带有optional的注释,但Collection是个特例。

协议的实现

一个类实现某些协议是写在Interface定义里面的。语法为:协议名用尖括号包裹,多个协议名用逗号隔开,协议写在父类的右边(如果没有父类就直接写在子类右边)。

示例:

  1. @interface class MyClass : NSObject <Printable, Drawable>
  2. @end

Printable, Drawablw就是两个协议。

对应的Java版本是:

  1. public class MyClass extends NSObject implements Printable, Drawable {
  2. }

分类(Category)

分类可以给一个已经存在的类增加方法,而不用去改它的源码。Java和PHP中都没有类似的特性。

比如说,NSObject是一个Objective-C内置的系统类,我们想给它增加toJson方法,就像这样:

头文件:NSObject+Json.h

  1. @interface NSObject (Json)
  2. -(NSString)toJson;
  3. @end

实现文件:NSObject+Json.m

  1. @implementation NSObject (Json)
  2. -(NSString)toJson {
  3. //…
  4. }
  5. @end

使用的时候,只要包含NSObject+Json.h,实例化NSObject类,就可以使用toJson方法了:

  1. import “NSObject+Json.h”
  2. @implatementation XYZController
  3. -(void)test {
  4. NSObject *obj = [[NSObject alloc]init];
  5. NSString *str = [obj toJson];
  6. }
  7. @end

当然了,NSObject本来的那些方法依然还是可以用的,什么都没变,只是多了个toJson方法。看起来是不是和继承没太多差别呢(除了使用的时候实例化的是NSObject,而不是JsonObject)?再看一个继承实现不了的例子:

头文件:NSObject+Json+XML.h

  1. @interface NSObject (Json)
  2. -(NSString)toJson;
  3. @end
  4. @interface NSObject (XML)
  5. -(NSString)toXML;
  6. @end

实现文件:NSObject+Json+XML.m

  1. @implementation NSObject (Json)
  2. -(NSString)toJson {
  3. //…
  4. }
  5. @end
  6. @implementation NSObject (XML)
  7. -(NSString)toXML {
  8. //…
  9. }
  10. @end

使用:

  1. import “NSObject+Json+XML.h”
  2. @implatementation XYZController
  3. -(void)test {
  4. NSObject *obj = [[NSObject alloc]init];
  5. NSString *json = [obj toJson];
  6. NSString *xml = [obj toXML];
  7. }
  8. @end

Cocoa Touch

Cocoa是Mac OS App的开发框架,Cocoa Touch是iOS开发用的框架,Cocoa Touch和Cocoa大部分是一样的,只是Cocoa Touch多了一些移动设备特有的东西,如:触摸屏、加速度传感器、GPS定位。Cocoa中多任务、多窗口的特性,在Cocoa Touch中也是没有的(或者跟Cocoa不完全一样的)。

就像学了Java语言还要再学一些Spring、Hibernate、Struts(或者其它类似的Java类库)才能开始做J2EE应用一样,学过Objective-C语言之后,也要再学习Cocoa Touch框架才能顺利地开发iOS应用。

*常用设计模式之Delegate

Cocoa Touch大量使用Delegate(委派)设计模式。

常用控件:按钮、文本块、图片、输入框

TableView

WebView

导航条

Xcode

运行

快捷键:Comman R

搜索

搜索文本

搜索文件

新建文件/目录

推荐在Finder中新建好的再添加进来

断点

模拟器和真机测试

模拟器测试

在Xcode中打开你的项目,在Xcode顶部工具栏的Stop按钮(Run按钮右边那个黑色正方形按钮)右边,有个下拉菜单,显示着 “ToolBarSearch > iPhone 5.0 Simulator” (即 你的应用英文名 > 当前选中的调试 ),点击这个下拉菜单,选中iPhone 5.0 Simulator(这里的5.0是指iOS版本,不是iPhone5的意思,如果你的项目是iPad应用,请选iPad 5.0 Simulator),再按“Run”按钮,Xcode就会自动把当前正在编辑开发的应用编译并安装到模拟器上。

在模拟器上操作时,如果执行过程中遇到了你在Xcode里设置的断点,模拟器会暂停运行,并将当前活动窗口切换回Xcode,供你调试。

在Xcode里增加或者取消了断点,不需要重新编译和安装应用即可生效。

切换被模拟的设备

模拟器的“硬件”菜单,可以选择想要模拟什么设备,有iPad、iPhone可选。

  • Retina:表示视网膜屏,iPhone(Retina)代表iPhone4,iPhone4S
  • 4-Inch:表示4英寸的iPhone,iPhone(Retina 4-Inch)就是iPhone 5

切换模拟的iOS版本

在模拟器的“版本”菜单,可以选择要模拟什么版本的iOS。设备和版本是彼此独立的,iPhone 4S可以有5.0,5.1,6.1几种iOS版本,当然了,iPhone 5不可能有4.3的iOS版本。

触摸屏

用鼠标点击(不区分左右键)模拟器上的iPhone、iPad屏幕,就是在模拟用手指触摸iPhone,iPad的屏幕,可以实现一些触摸效果比如:

  • 鼠标单击 等于 手指轻触
  • 鼠标长按 等于 手指长按(例如你可以在模拟器上长按应用icon调出删除应用的确认框)
  • 鼠标按住拖动 等于 手指拖动
  • 双击和单击模拟器的Home键也等于双击和单击真机的Home键
多指手势

多指手势比较复杂,在白苹果笔记本上可以模拟简单的双指手势,白苹果的触控板天然支持多指触摸,但要定位到模拟器的区域再响应多指手势就需要借助一些额外的键啦:

  • 按住Option键,再用两个手指去操作触摸板,可模拟双指拖动、旋转
  • 按住Option+Shift,可模拟双指合拢

输入法和键盘

输入中文

手机上特有的输入法(比如九宫格输入法)不能模拟。模拟器默认的iOS软键盘只有英文输入,在测试应用的时候,我们要用到中文,有两个办法:

  • 使用剪贴板,在Mac OS里复制,再到模拟器运行的应用中的输入框上长按鼠标(模拟手指长按)3秒以上,等弹出“粘贴”的时候选择之,即可。
  • 在模拟器里,按Home键,找到Setting那个App icon(不是Mac OS顶部的模拟器菜单啊,那里没有Setting的),打开被模拟iOS设备的设置,依次点击”General – Keyboard – International Keyboards – Add New Keyboard…”,加个中文键盘,以后就可以使用被模拟iOS设备软件盘输入中文了,跟在iPhone/iPad真机上一样。

使用Mac电脑的键盘

如果要输入大量文本,使用模拟器里的软键盘效率太低,这时候可以使用物理键盘,方法是:在Mac OS顶部的模拟器菜单栏,点击”硬件”菜单,勾选下拉菜单中的“模拟硬件键盘”。以后再用模拟器运行iOS应用时,点击iOS应用中的输入框,软键盘就不弹出来了,可直接使用Mac电脑的物理键盘输入。

注意

  • 模拟器中的iOS接管了物理键盘输入,所以,调用的是模拟器iOS的输入法,不是你的Mac电脑的输入法。打个比方,你的Mac OS装的是搜狗五笔,模拟器中iOS加了个拼音输入法(Add New Keyboard),那么,在iOS应用中输入中文会调用拼音输入法。
  • 要切换模拟器中iOS的中英文输入法,也只能按iOS设备软键盘上的小地球图标,按Mac电脑上的Command+空格键是不行的。

地理位置

但Mac电脑没有定位用的硬件(GPS)和软件基础,因此模拟器不能自动获得当前的地理位置,不能用模拟器测试定位功能。(注意,虽然WiFi也可以独立定位——iPad WiFi版没有GPS也可以定位,但Mac电脑的WiFi不具备定位相关的软件)

要在模拟器里测试依赖地理位置的功能(如”我附近的xx”),可以手工指定一个经纬度给模拟器,方法:在Mac电脑顶部的模拟器菜单,点击”调试 – 位置 – 自定位置”,会弹出一个对话框,在弹出的框内填入经纬度即可。

如何获得经纬度? 上谷歌地图(ditu.google.cn),在地图上找到你想要的位置(比如你想知道杭州大厦的位置,就在通过搜索框找到杭州大厦),点击右键,选择“这儿是什么”,搜索框中就会出现这个位置的经纬度了,前面是纬度,后面是经度。咱们天朝的版图,都是北纬和东经。

摄像头

Mac电脑有摄像头,但Mac OS没有设计API给iOS模拟器调用,所以,不能用模拟器测试对焦闪光灯等功能。

要在模拟器上测试依赖照片的功能,可以在代码里做一个workaround,即当代码检测到摄像头不可用时,弹出一个照片选择器,让测试人员从相册里选择一幅照片,来进行后续的操作(如照片美化、人脸识别、条码扫描)。

真机测试

模拟器能验证你开发的iOS应用的大部分功能,但有些Mac设备上不具备的硬件,模拟器是不能模拟的。前文提到了一个绕过这些限制的办法,但获取当前位置、拍照、加速度感应这些是模拟不了的,一款应用发布给消费者之前,必须要在真实设备上验证过。

将未提交App Store审核通过的应用安装到iOS设备上测试,有三种办法:

  • 加入苹果的Developer Program,成为付费会员,有了这个付费会员资格,就可以直接在Xcode中点击”Run”将刚刚改过的代码编译打包安装到开发测试用的iOS设备上。在iOS真机上操作被测试的程序能激活Xcode中设置的断点。
  • 越狱iOS设备。将iPhone和iPad越狱后,可以通过SSH直接上传Xcode编译好的ipa包(一个iOS App本质上就是一个ipa包)。
  • 越狱的iOS设备,配合破解过的Xcode,甚至可以实现和付费开发者计划一样的功能:在Xcode上点击”Run”,就自动编译安装到iOS设备上去运行了
  • 企业部署方案。就像阿里巴巴的轩辕剑一样,用iPhone/iPad访问这个网址,点击里面的轩辕剑链接就可以安装轩辕剑这个应用了。

破解Xcode是违法行为(越狱是合法的),而且挑版本挑得厉害,不是所有Xcode版本都能破解,也不是所有Xcode的破解版都能和越狱的iOS配合好。越狱+SSH上传跟企业部署一样效率低(部署效率低,无法激活Xcode中的断点),只能用于QA验收,不适合开发自测。综上所述,*适合开发实时测试的就是*个正规途径了。下面重点讲这个:

拥有一个开发者账号

苹果的Developer Program分为个人开发者和公司开发者,分别是每年99美元和每年299美元,分别可以注册100台和500台苹果测试设备。这个台数限制在一个付费年度内不会清空,比如说,2013年4月1日付费成功的,付费会员资格在2014年3月31日之前有效,这期间,注册一台就少一个名额,哪怕这个设备注册进来用了之后一分钟马上又删掉了,减少的这个名额也不会回来。

在交钱之前,*好问一下,周围的同事,有没有已经交了钱的。如果有,你只需要注册一个免费的Apple ID(就是你在App Store安装软件用的Apple ID),请他发个邀请邮件给你,把你的Apple ID加入他的团队就可以了,苹果会认为你们两个人是一个团队的,你们分别用自己的账号,共享100台设备的限额,这是合法的。

安装证书和私钥

证书

不想看下面各种点击各种页面跳转的直接用浏览器访问证书管理,你要登录你就用Apple ID登录(前提是交过钱,或者找交了钱的人把你加入团队了)。

不嫌烦,或者想知道下次没我这个文档的时候怎么进证书管理吗?按这个步骤操作:

  • 进入 苹果开发者中心
  • 点击iOS Dev Center
  • 点蓝色“Login”按钮,用你的Apple ID登录,登录成功会跳到 开发者首页
  • 点击右上角的iOS Provisioning Portal(别找了,直接Command F搜索多好)
  • 点左侧菜单栏里的Certificates

页面上有一个“Your Certificate”区域,下方有个Download圆角按钮,这是你的个人证书,下载下来。再下面一行,有一句“If you do not have the WWDR intermediate certificate installed, click here to download now”,这个是苹果的公共证书,也下下来。

双击下载回来的证书,装证书时,会提示你输入密码,这是【钥匙串访问工具】在问你要你的Mac OS账号开机密码(相当于linux里面的sudo),不是Apple ID的密码,不要搞错了。

安装私钥

如果你是和其它同事公用的账号,让他给你一个私钥即可,就是一个扩展名为p12的文件,双击之,钥匙串访问会自动出来,需要你输入一个密码,这个密码问给你p12文件的人要,不是你的Mac OS系统开机密码,也不是你的Apple ID密码。

将设备注册到Provisioning Portal

  • 打开Xcode,从Xcode的Window菜单中找到Organizer,打开之(Shift Command 2)。
  • 把iOS设备连上电脑,Organizer会自动识别出你的设备,并显示在左侧边栏。
  • 在Organizer左侧边栏找到你的设备,右键,点击“Add Device to Provisioning Portal”,然后等Organizer提示你操作成功即可。(选中设备后,右边设备详情区域会显示一个按钮“Use for Development”,点它也可以)。

到iOS真机上运行测试版程序

回到Xcode主界面,在Stop按钮(Run按钮右边那个黑色正方形按钮)右边,有个下拉菜单,显示着 “ToolBarSearch > iPhone 5.0 Simulator” (即 你的应用英文名 > 当前选中的调试 ),点击这个下拉菜单,选中你的真机设备名,再按“Run”按钮,Xcode就会自动把当前正在编辑开发的应用编译并安装到真机上测试啦!

发布到App Store

打IPA包

IPA包本质上是一个ZIP压缩包,只不过它有着特殊的目录结构,扩展名是ipa,制作方法如下:

  • 在Xcode中Build项目,快捷键Command B
  • 在左侧项目导航器中,展开Products文件夹,找到你要打包的应用,你的应用名.app,右键,选择show in finder
  • 到Finder中Copy这个.app目录(选中,按Command C),复制到一个你新建的名为Payload(区分大小写)的文件夹中
  • 找到你的应用Logo,即一个512 * 512像素的PNG文件,copy到与Payload一起(与Payload并列,不要放进Payload了),并重命名为iTunesArtwork(区分大小写,没有扩展名)
  • 将Payload目录、ItunesArtwork文件打成一个zip包,并更改扩展名为ipa
  • 双击这个ipa文件,会用iTunes打开,如果打开成功,且在iTunes里有应用Logo显示,就成功了

批量自动打包

除App Store外,还有许多其它的iOS应用市场(如91助手,同步推等等),如果一个应用需要发布到很多个应用市场,且他们的代码略有不同(比如说,统计代码不同),按上述方法手工修改源码再打包,再还原,比较容易出错。好消息是,Xcode是有命令行的,我们可以写一个shell脚本,先用se自动修改源码,再调用Xcode的命令行来编译以得到your——app.app目录,*后调用zip、mv等命令把上一个章节讲的ipa打包动作自动执行。

阅读应用代码

从头新建一个应用:Hello World

其它

代码里的控件尺寸

iOS App里的控件尺寸和字体大小都是指Point,Retina设备(iPhone 4,4S,5;the new Pad)和非Retina设备(iPhone 3GS,iPad,iPad 2)的Point数是一样的,尽管iPhone 4的分辨率是3GS的2倍。比如说,10point在Retina设备里是20 pixel,在非Retina设备(iPhone 3G)上则是10 pixel。

项目成员间交流时,应使用Point,不要使用pixel。

SVN操作含有@符号的文件

iOS应用中经常出现xxxx@2x.png这样的文件名,它们是给retina设备用的高分辨率大图,用svn命令行操作它们的时候会被@符号干扰,解决方案是在svn命令末尾加上一个@符号,如:

  1. svn del icon@2x.png@
  2. svn info Default@2x.png@

如果一次移动了几十个png文件再svn commit的,可以用shell批处理:

svn status | awk '($1=="!"){print $2}' | grep -v @ | xargs svn del

上面这个命令是将文件名不包含@符号的,且已经不在硬盘上的文件从svn version controll中删掉

for file in `svn status | awk '($1=="!"){print $2}' `; do svn del $file"@"; done     

上面这个命令是将文件名包含@符号的,且已经不在硬盘上的文件从svn version controll中删掉

svn add同上, 如法炮制即可.

Xcode中的代码结构与操作系统上的文件系统并不一致

推荐在Finder里建好目录再到Xcode的Project Navigator中点击“Add Files to”添加到项目中

iPhone 5适配

iPhone 5与之前的iPhone不一样,采用了4寸Retina屏,所以它的Point数变成了320 * 568 points

开源代码

  • Apple官方的Sample Code
  • 维基百科上的开源iOS App
  • iOS Opensource –Domain Parking了,以前可以下载Twitter和Wordpress客户端的
  • code 4 app
  • UI 4 app, code4app的姐妹站

Objective-C教程

  • Apple官方教程
  • Cocoa Dev Center
  • 维基上的Objective-C语言简介 –中文,十分钟可读完,推荐

iOS批量自动打包和部署(Ⅲ)

本篇为这个系列的*后一篇,主要会讲重新签名和自动部署的问题。通过前面的步骤已经能够打包并签名了,现在回到系列开始时提到的问题:如何能够快速复制非常相似但又不同的包呢?其实,重新签名就能够做到!

重新签名和授权机制

我们知道苹果在打包的*后步骤就是进行签名,如果对于一个已经签名的包,我们还可以进行重新签名,签名的命令主要是codesign。例如(摘自代码签名探析):

  1. $ codesign -s ‘iPhone Developer: Thomas Kollbach (7TPNXN7G6K)’ Example.app 设置签名
  2. 如果你想为某一个 app 程序包重新设置签名,那么这个工具就很有用了。为了重新设置签名,你必须带上 -f 参数,有了这个参数,codesign 会用你选择的签名替换掉已经存在的那一个:
  3. $ codesign -f -s ‘iPhone Developer: Thomas Kollbach (7TPNXN7G6K)’ Example.app 重新签名
  4. $ codesign -vv -d Example.app 会列出一些有关 Example.app的签名信息 $ codesign –verify Example.app 会验证签名是否完好,若无任何输出则说明签名完好

除了重新签名的命令,还需要知道的是entitlements–授权机制。授权机制决定了哪些系统资源在什么情况下允许被一个应用使用,即沙盒的配置列表。授权机制也是按照 plist 文件格式来列出的,Xcode 会将这个文件作为 –entitlements 参数的内容传给 codesign ,这个文件内部格式如下:

  1. <?xml version=“1.0” encoding=“UTF-8”?>
  2. <!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
  3. <plist version=“1.0”>
  4. <dict>
  5. <key>application-identifier</key>
  6. <string>7TPNXN7G6K.ch.kollba.example</string>
  7. <key>aps-environment</key>
  8. <string>development</string>
  9. <key>com.apple.developer.team-identifier</key>
  10. <string>7TPNXN7G6K</string>
  11. <key>com.apple.developer.ubiquity-container-identifiers</key>
  12. <array>
  13. <string>7TPNXN7G6K.ch.kollba.example</string>
  14. </array>
  15. <key>com.apple.developer.ubiquity-kvstore-identifier</key>
  16. <string>7TPNXN7G6K.ch.kollba.example</string>
  17. <key>com.apple.security.application-groups</key>
  18. <array>
  19. <string>group.ch.kollba.example</string>
  20. </array>
  21. <key>get-task-allow</key>
  22. <true/>
  23. </dict>
  24. </plist>

在 Xcode 的 Capabilities 选项卡下选择一些选项之后,Xcode 就会生成这样一段 XML。 Xcode 会自动生成一个 .entitlements 文件,然后在需要的时候往里面添加条目。当构建整个应用时,这个文件也会提交给 codesign 作为应用所需要拥有哪些授权的参考。这些授权信息必须都在开发者中心的 App ID 中启用,并且包含在配置文件中,稍后我们会详细讨论这一点。在构建应用时需要使用的授权文件可以在 Xcode build setting 中的 code signing entitlements 中设置。

上面两段主要摘自《代码签名探析》,这是为了方便解释后面的重新签名脚本。

重新签名的实例

为了达到对一个app进行快速换皮的目的,我的设计思路如下图(本篇所有的Demo在这里)):

%title插图%num

先自动打包生成一个母包,然后跑脚本对母包进行重新签名得到一个个子包。继续前面的PackageExample例子,PackageExample的bundleid为com.vienta.packageExample,其作为母包,我又重新申请了两个bundleid,分别为com.vienta.packageExampleSoncom.vienta.packageExampleDaughter,作为重新签名后的子包。本例子主要通过通过换icon来反映”换皮”。

实例的Resign-ipa文件夹目录结构如下图:
%title插图%num

templates文件夹中存放的是和授权文件相关的配置文件,build文件夹主要存放*后被重新签名的包,module目录下存放重签名的配置文件、资源文件和描述文件等。这里的思路是遍历module文件夹下的内容,然后根据内容重新签名母包,将得到的包放到build,例子中是两个,实际如果版本非常多,只需要向module增加文件夹及配置内容即可。

resign.sh为重签名的脚本,内容也不算多:

  1. #!/bin/bash
  2. for file2 in `ls -a ./module`
  3. do
  4. if [ x$file2 != x“.” -a x$file2 != x“..” -a x$file2 != x“.DS_Store” ]; then
  5. echo $file2
  6. #Conf file
  7. CONF=./module/$file2/resign.conf
  8. echo $CONF
  9. #Datetime
  10. NOW=$(date +“%Y%m%d_%s”)
  11. #Load config
  12. if [ -f ${CONF} ]; then
  13. . ${CONF}
  14. fi
  15. #Temp
  16. TEMP=“temp”
  17. if [ -e ${TEMP} ]; then
  18. echo “ERROR: temp already exists”
  19. exit 1
  20. fi
  21. #Check app ID
  22. if [ -z ${APP_ID} ]; then
  23. echo “ERROR: missing APP_ID”
  24. exit 1
  25. fi
  26. echo ${APP_ID}
  27. #Create build dir
  28. if [[ ! -d ${BUILD_PATH} ]]; then
  29. mkdir ${BUILD_PATH}
  30. fi
  31. #Copy mother package
  32. if [[ ! -f “../Package/ipa/QA/packageExample.ipa” ]]; then
  33. echo “mother package not exists”
  34. exit 1
  35. fi
  36. cp ../Package/ipa/QA/packageExample.ipa ./module/$file2${ASSETS_PATH}/packageExample.ipa
  37. #Unzip the mother ipa
  38. echo “Unzip ipa”
  39. unzip -q ./module/$file2${ASSETS_PATH}${IPA_NAME}.ipa -d ${TEMP}
  40. #Remove old Codesignature
  41. echo “Remove old CodeSignature”
  42. rm -r ${TEMP}/Payload/${APP_NAME}.app/_CodeSignature” ${TEMP}/Payload/${APP_NAME}.app/CodeResources” 2> /dev/null | true
  43. #Replace embedded mobil provisioning profile
  44. echo “Replace embedded mobile provisioning profile”
  45. cp “./module/$file2${ASSETS_PATH}${PROFILE_NAME}.mobileprovision” ${TEMP}/Payload/${APP_NAME}.app/embedded.mobileprovision”
  46. #Change icon
  47. echo “Change icon”
  48. cp “./module/$file2${ASSETS_PATH}/icon_120.png” ${TEMP}/Payload/${APP_NAME}.app/AppIcon60x60@2x.png”
  49. cp “./module/$file2${ASSETS_PATH}/icon_180.png” ${TEMP}/Payload/${APP_NAME}.app/AppIcon60x60@3x.png”
  50. #Change Bundleversion
  51. if [[ ! -z ${APP_BUNDLE_VERSION} ]]; then
  52. /usr/libexec/PlistBuddy -c “Set CFBundleVersion ${APP_BUNDLE_VERSION} ${TEMP}/Payload/${APP_NAME}.app/Info.plist
  53. fi
  54. #Change CFBundleShortVersionString
  55. if [[ ! -z ${APP_BUNDLE_SHORT_VERSION_STRING} ]]; then
  56. /usr/libexec/PlistBuddy -c “Set CFBundleShortVersionString ${APP_BUNDLE_SHORT_VERSION_STRING} ${TEMP}/Payload/${APP_NAME}.app/Info.plist
  57. fi
  58. #Change Bundleidentifier
  59. /usr/libexec/PlistBuddy -c “Set CFBundleIdentifier ${APP_ID} ${TEMP}/Payload/${APP_NAME}.app/Info.plist
  60. #Create entitlements from template
  61. ENTITLEMENTS=$(<./templates/entitlements.template)
  62. ENTITLEMENTS=${ENTITLEMENTS//#APP_ID#/$APP_ID}
  63. ENTITLEMENTS=${ENTITLEMENTS//#APP_PREFIX#/$APP_PREFIX}
  64. echo ${ENTITLEMENTS} > ${TEMP}/entitlements.temp
  65. #Re-sign
  66. #这里注意命令参数的不同
  67. #/usr/bin/codesign -f -s “${CERTIFICATE_TYPE}: ${CERTIFICATE_NAME}” –identifier “${APP_ID}” –entitlements “${TEMP}/entitlements.temp” –resource-rules “${TEMP}/Payload/${APP_NAME}.app/ResourceRules.plist” “${TEMP}/Payload/${APP_NAME}.app”
  68. /usr/bin/codesign -f -s ${CERTIFICATE_TYPE}: ${CERTIFICATE_NAME} –identifier ${APP_ID} –entitlements ${TEMP}/entitlements.temp” ${TEMP}/Payload/${APP_NAME}.app”
  69. #Remove copyed mother package
  70. echo “Remove mother package”
  71. rm -rf ./module/$file2${ASSETS_PATH}packageExample.ipa
  72. #Re-package
  73. echo “Re-package”
  74. cd ${TEMP}
  75. zip -qr ${IPA_NAME}_resigned_${NOW}.ipa” Payload
  76. mv ${IPA_NAME}_resigned_${NOW}.ipa ../${BUILD_PATH}/${IPA_NAME}_${file2}_${NOW}.ipa
  77. #Remove temp
  78. cd ../
  79. rm -rf ${TEMP}
  80. fi
  81. done
  82. exit 0

代码中已经做了注释,做简单解释:

  1. *外面对module文件夹for循环
  2. 读取conf配置文件(这些配置文件均是自己配置,实际也可以是plist文件,也比较方便)
  3. 把母包从外面拷贝进来
  4. 对拷贝过来的包进行解压,移除CodeResources等,替换描述文件,替换icon,修改BundleId及版本信息,修改授权文件(授权文件也是需要注意的点,inhouse和develop也有一点点区别,但整体没变)
  5. 然后就是codesign命令,代码注释也指出了 --resource-rules参数的问题,我原本找到的是带这个参数的,但是现在用不到。具体原因《代码签名探析》这里说是:“伴随 OS X 10.10 DP 5 和 10.9.5 版本的发布,苹果改变了代码签名的格式,也改变了有关资源的规则。如果你使用10.9.5或者更高版本的 codesign 工具,在 CodeResources 文件中会有4个不同区域,其中的 rules 和 files 是为老版本准备的,而 files2 和 rules2是为新的第二版的代码签名准备的。*主要的区别是在新版本中你无法再将某些资源文件排除在代码签名之外,在过去你是可以的,只要在被设置签名的程序包中添加一个名为 ResourceRules.plist 的文件,这个文件会规定哪些资源文件在检查代码签名是否完好时应该被忽略。但是在新版本的代码签名中,这种做法不再有效。所有的代码文件和资源文件都必须设置签名,不再可以有例外。” 。简单的说,资源文件现在也必须重新签名了。
  6. 重新压缩包,并移动到build中。

整个流程走完后我们在build中得到了重新签名后的包,并且可以通过iTunes按照到设备上且能够正常打开,但是我们发现icon被换掉了,内部的bundleId、版本号信息等也被换了,于是乎,就这样轻轻松松的“换皮了”。我的手机上*后的截图如下:

%title插图%num

这样做的优势:

  1. 节省劳动
  2. 配置方便,例子中主要修改icon,其实还可以加一些配置文件来配置颜色啊字体啊文字啊等等
  3. 对于邪恶点的公司,申请很多app账号,然后用这个方法,快速换皮,app内部的内容接口根据bundleid等信息来配置,里面放放广告,对主版本进行导流量等。

自动部署

截止到目前为止,成功的导出了各种各样的包。离完全的自动化“只剩*后一公里“了,还可以继续的进行自动部署来完成这*后一公里。通过自动部署,我们可以直接将包发到AppStore、fir\蒲公英这样的第三方平台、以及自己的服务器上。这里重点推荐mattt大神的——SHENZHEN。

SHENZHEN的安装和使用

通过gem安装

$ gem install shenzhen

具体的用法可以参见这里,毕竟在中国,主要提下FIR和蒲公英已经上传AppStore的命令:

FIR

$ ipa distribute:fir -u USER_TOKEN -a APP_ID  

蒲公英 (PGYER)

$ ipa distribute:pgyer -u USER_KEY -a APP_KEY

USER信息到各自注册账号查找

iTunes Connect Distribution

$ ipa distribute:itunesconnect -a me@email.com -p myitunesconnectpassword -i appleid --upload

我们仍然是可以通过读取配置信息,来写个脚本跑部署,这部分就不再举例了,如果你不小心看到这个系列我觉得你应该会了,或者我们也可以相互商讨(毕竟我的blog人读的少 o(╯□╰)o)。实际上,我的同事已经实现了。

论持续化集成

虽然iOS好像能使用Jenkins进行持续化集成(好像我也用了一下Jenkins,貌似不是很好用,可能是我没有坚持用吧),但是通过这个序列的文章,其实我们自己就实现了一套持续化集成了。刚开始用蒲公英那会儿我把ipa包传给他们,他们就能放到平台给其他人测试,我觉得好神奇啊,后来想想,无非就是重新签名。持续化集成其实我的同事也实现了,我们用了一台服务器,定时的拉取代码,跑脚本,然后上传到测试服务器供人下载使用。只是公司内部推广不好,毕竟不是大厂也好像不是那么工程师文化,所以巴拉巴拉。

iOS 必备技术点

通过网络搜寻和自己总结经历找了一些IOS面试经常被问道的问题:

1.搞清楚touch事件的传递(事件的响应链)

事件的响应(responder chain)

 

只有继承了UIResponder的类才能响应touch事件,从上图的响应者链可以看出,优先是*上层的view响应事件,如果该view有视图控制器的话会是下一个响应者,否者就是该view的父视图,这样至上而下传递事件。直到单例UIWindow对象,*后是单例UIApplication对象以终止,UIApplication的下一个响应者是nil,已结束整个响应循环。事件在传递过程中视图可以决定是否需要对该事件进行响应。

事件分发(Event Delivery)

 

*响应者(First responder)指的是当前接受触摸的响应者对象(通常是一个UIView对象),即表示当前该对象正在与用户交互,它是响应者链的开端。整个响应者链和事件分发的使命都是找出*响应者。

UIWindow对象以消息的形式将事件发送给*响应者,使其有机会首先处理事件。如果*响应者没有进行处理,系统就将事件(通过消息)传递给响应者链中的下一个响应者,看看它是否可以进行处理。

iOS系统检测到手指触摸(Touch)操作时会将其打包成一个UIEvent对象,并放入当前活动Application的事件队列,单例的UIApplication会从事件队列中取出触摸事件并传递给单例的UIWindow来处理,UIWindow对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的视图(View),即需要将触摸事件传递给其处理的视图,这个过程称之为hit-test view。

UIWindow实例对象会首先在它的内容视图上调用hitTest:withEvent:,此方法会在其视图层级结构中的每个视图上调用pointInside:withEvent:(该方法用来判断点击事件发生的位置是否处于当前视图范围内,以确定用户是不是点击了当前视图),如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是要找的hit-test view。
hitTest:withEvent:方法的处理流程如下:
首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
若返回NO,则hitTest:withEvent:返回nil;
若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从*顶层视图一直到到*底层视图,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
若*次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。

 

2.fame,bounds,center,alpha,opaque,hidden

这些都是view的一些基本属性。frame是描述该view在其父视图中的一块区域。其坐标系是在其父视图中的坐标。我们在进行view的初始化时会经常使用到frame。bounds也是描述该view的大小,是其在自身的坐标系中的位置大小。center是描述其在父视图的中心位置坐标。我们在进行view的位置改变而不改变view的大小的时,会使用center。alpha是用来描述改view的透明度从0到1,0表示的是透明,1表示不透明。alpha支持动画(animation),alpha = 0 与 hidden = YES 效果一样都是看不到view,但是后者相比开销大。在alpha等于0时view接受touch事件,但是hidden则不接受。并且hidden和apaque 不支持动画。alpha并不影响镶嵌在其内部view行为,而hidden会影响。当把view设置为透明背景时,一般把opaque设置为NO,可以减少开销,优化内存.opaque影响图形绘制系统。设置为YES,会优化view的绘制。

 

3,nil,NSNULL,NULL区别

nil是指向obj-c中对象的空指针,是一个对象,在o-c中ni对象调用方法不会引起crash。

Nil是指向obj-c中的类的空指针,表示的是一个空类。

NULL是指向任何类型的空指针(如c/c++中的空指针),在objective-c中是一个数值。

NSNULL用于集合操作,在集合对象中,表示一个空值的集合对象。

 

4.KVC and KVO

KVC(key-value-coding)键值编码,是一种间接操作对象属性的一种机制,可以给属性设置值。通过setValue:forKey:和valueForKey,实现对属性的存取和访问。

KVO(key-value-observing)键值观察,是一种使用观察者模式来观察属性的变化以便通知注册的观察者。通过注册observing对象addObserver:forKeyPath:options:context:和观察者类必须重写方法 observeValueForKeyPath:ofObject:change:context:。常应用MVC模型中,数据库(dataModal)发生变化时,引起view改变。

 

5.NSThread,NSOperation,GCD

NSThread,NSOperation,GCD是IOS中使用多线程的三种方式之一。他们各有优缺点。抽象层次是从低到高的,抽象度越高的使用越简单。

NSThread,缺点:需要自己维护线程的生命周期和线程的同步和互斥,但是这些都需要耗费系统的资源。优点:比其它两个更轻。

NSOperation,优点:不需要自己管理线程的生命周期和线程的同步和互斥等。只是需要关注自己的业务逻辑处理,需要和NSOperationQueue一起使用。

GCD,是Apple开发的一个多核编程解决方法,优点:比前面两者更高效更强大。

 

6.autorelease ,ARC 和非ARC

autorelease 自动释放,与之相关联的是一个自动释放池(NSAutoReleasePool).autorelease的变量会被放入自动释放池中。等到自动释放池释放时(drain)时,自动释放池中的自动释放变量会随之释放。ios系统应用程序在创建是有一个默认的NSAutoReleasePool,程序退出时会被销毁。但是对于每一个RunLoop,系统会隐含创建一个AutoReleasePool,所有的release pool会构成一个栈式结构,每一个RunLoop结束,当前栈顶的pool会被销毁。

ARC,自动应用计数。(iOS 6加入)IOS内存管理是基于变量的应用计数的。这样系统帮你管理变量的release,retain等操作。

非ARC,非自动应用计数。手动管理内存。自己负责系统变量的release,retain等操作。做到谁分配谁释放,及alloc和release像对应。函数返回对象时使用autorelease。

可以使用Xcode将非ARC转化为ARC,ARC和非ARC混编。可在在编译ARC时使用-fno-objc-arc,-fobjc-arc标签。实际需要看工程是支持还是不支持ARC模式。

 

7.xib,storyboard,手动书写代码

xib(interface buider),方便对界面进行编辑。可以在窗口上面直接添加各种视图,优点:直接看到界面的效果,操作简单。缺点:不方便对视图进行动态控制,不灵活。

手动编写代码,继承(主要是UIView,UIViewController),优点:可以对视图进行定制,灵活控制方便。缺点:不能马上看到效果,复杂。

storyboard(故事板在ios6加入)。优点:可以看到界面效果,能同时进行多个界面的交互,高效快速。缺点:不能进行进行界面的定制,却笑灵活性。

xib和storyboard主要用于界面中的元素位置固定和清楚里面有哪些元素。但是如果需要动态变化界面还是手动编写代码比较好。一般还是各种方式混合使用。

 

8.loadView,viewDidLoad,ViewDidUnload,viewWillAppear,viewDidAppear,viewwilldDisappear,viewDidDisappear

当view的nib文件为nil时,手动创建界面时调用loadView,当view的nib文件存在时,会在viewDidLoad中实现。但是当你的程序运行期间内存不足时,视图控制器收到didReceiveMemoryWarning时,系统会检查当前的视图控制器的view是否还在使用,如果不在,这个view会被release,再次调用loadView来创建一个新的View。viewDidLoad ,不论是从xib中加载视图,还是从loadview生成视图,都会被调用。但是如果改view在栈中下一次显示是不会被调用。ViewWillAppear,ViewDidAppear会在view每次即将可见和完全显示时都会调用。我们会在ViewWillAppear里面进行一些view显示的准备工作,ViewDidDi sappear 和ViewWillDisAppear时会在view每次消失时都会调用。当系统收到didReceiveMemoryWarning通知时显示内存不足时,会调用ViewDidUnload来清理View中的数据和release后置为nil。

 

9,copy 和retain区别

retain,相当于指针拷贝。变量的引用计数加一。另外一个指针也指向改地址。

copy,相当于内容拷贝。变量的引用计数加一。但是自己本身计数不变。开辟另外一个地址空间放入相同变量的值进去。

 

10,手动写setter和getter方法

 

– (void) setOldValue: (NSString*) newValue {

if (newValue !=oldValue) {

[oldValue release];

oldValue = [newValue retain];

}

}

11,NSRunLoop 和NSOperationQueue

NSRunLoop 是所有要监视的输入源和定时源以及要通知的注册观察者的集合.用来处理诸如鼠标,键盘事件等的输入源。每一个线程拥有自己的RunLoop有系统自动创建。你不应该自己去创建,只能获取。一般不会用NSRunLoop,因为它不是线程安全的。一般都用CFRunLoop,这个是线程安全的,是一种消息处理模式,我们一般不用进行处理。

NSOperationQueue时一个管理NSOperation的队列。我们会把NSOperation放入queue中进行管理。

 

12,IOS常用的设计模式

单例模式,DeafutCenter,Deafultqueue等

MVC模式,View,model,ViewController。

观察者模式,通知,KVO

工厂模式,

代理模式,delegate

 

13.内存管理和优化

原则:

1.1    谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
例如,你在一个函数中alloc生成了一个对象,且这个对象只在这个函数中被使用,那么你必须在这个函数中调用release或autorelease。如果你在一个class的某个方法中alloc一个成员对象,且没有调用autorelease,那么你需要在这个类的dealloc方法中调用release;如果调用了autorelease,那么在dealloc方法中什么都不需要做。

1.2  除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。

1.3  谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。有时候你的代码中明明没有retain,可是系统会在默认实现中加入retain。

 

优化:

在收到内存didReceiveMemoryWarning的警告时,释放掉一些不再需要的资源,注意编码规范,如一些变量不使用需要及时的释放。避免是占用太多的内存空间,有时需要用空间去换取时间,尽量使用一些高效的算法和数据结构节约内存空间。*后使用一些内存检测工具和代码的静态分析查找内存泄漏和分配(instrument,leaks,allocations)。

 

14,tableview的优化

优化:

1.1 正确的复用cell。

1.2 减少在返回每个cell里面的处理逻辑和处理时间。尽量将数据进行缓存和复用。

1.3,尽量减少处理加载和计算的时间,不阻塞UI线程。

1.4,尽量使用绘制每个cell。

1.5,设置每个cell的opaque属性。

1.6,尽量返回每行固定的height。

1.7,在每个cell减少图形效果。

1.8,分段加载数据。

 

15,opengl,quatarz 2d

上面2种方式是进行图形绘制会使用到的技术。

quatarz 2d 是Apple提供的基于Core graphic的绘制基本图形工具库。操作简单方便,能够满足大部分需要。只是适用于2D图形的绘制。

opengl,是一个跨平台的图形开发库。适用于2D和3D图形的绘制。功能强大但是复杂。

 

16, animation

IOS提供丰富的Core Animation动画满足用户的需要,主要实现方式如下3种:

1.1  commitAnimations方式使用UIView动画

UIView Animations 动画:
[UIView beginAnimations:@”animationID” context:nil];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationRepeatAutoreverses:NO];
//以下四种效果
/*
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];//oglFlip, fromLeft
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];//oglFlip, fromRight
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
*/
//你自己的操作
[UIView commitAnimations];

 

1.2、CATransition

 

CATransition *animation = [CATransitionanimation];

animation.duration = 0.5f;

animation.timingFunction =UIViewAnimationCurveEaseInOut;

animation.fillMode = kCAFillModeForwards;

animation.type = kCATransitionMoveIn;

animation.subtype = kCATransitionFromTop;

[self.window.layeraddAnimation:animationforKey:@”animation”];

//自己的操作
1.3、UIView animateWithDuration

方法: +(void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; //多一个动画结束后可以执行的操作.

[UIView animateWithDuration:1.25 animations:^{
CGAffineTransform newTransform = CGAffineTransformMakeScale(1.2, 1.2);
[firstImageView setTransform:newTransform];
[secondImageView setTransform:newTransform];}
completion:^(BOOL finished){
[UIView animateWithDuration:1.2 animations:^{
//自己的操作} completion:^(BOOL finished){ 自己的操作}];
}];

 

17,定制化view

需要自己自己继承自cocoa touch提供的丰富的类。如(UIView,UiScrollView,UITableView等等)。需要重载实现drawRect,touch事件,init,initFrame等方法。

 

18.core Data,sqlite,file,NSUserDefaults

上面四种是IOS中数据存取的方式。

Core Data,sqlite涉及到数据库。sqlite需要通过sqlite语句操作数据库,而core data是Apple提供的一个基于sqlite更抽象成对象的一种对数据库操作方式。

file,主要是把数据存储在磁盘中。通过写和读文件操作。

NSUserDefaults,主要是存储应用程序中的一些轻量级数据如应用程序的设置和属性和用户信息等。

 

19.机型和尺寸的适配

Iphone 的主要尺寸是3.5和4英寸。分辨率为:320*480,480*960(retina)。

IPad 主要尺寸是7.9和9.7英寸。分辨率为:1024*768,2048*1536(retina)。

 

20.添加手势的方式(gesture和touches事件)

1.自己重载实现touchMoved,touchBegin,touchEnd,touchCanceled事件。

2.通过UIGestureRecongnizer添加AddGestureRecognier事件。该方式方便添加一些诸如点击,双击,拖动等基本的手势事件。

 

21.应用程序的生命周期和状态(参照:http://blog.csdn.net/totogo2010/article/details/8048652)

 

Not running  未运行  程序没启动

Inactive          未激活        程序在前台运行,不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态

Active             激活           程序在前台运行而且接收到了事件。这也是前台的一个正常的模式

Backgroud     后台           程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态

Suspended    挂起           程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。

下图是程序状态变化图:
%title插图%num

各个程序运行状态时代理的回调:

– (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
告诉代理进程启动但还没进入状态保存
– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
告诉代理启动基本完成程序准备开始运行
– (void)applicationWillResignActive:(UIApplication *)application
当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了
– (void)applicationDidBecomeActive:(UIApplication *)application
当应用程序入活动状态执行,这个刚好跟上面那个方法相反
– (void)applicationDidEnterBackground:(UIApplication *)application
当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可
– (void)applicationWillEnterForeground:(UIApplication *)application
当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
– (void)applicationWillTerminate:(UIApplication *)application
当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。
– (void)applicationDidFinishLaunching:(UIApplication*)application
当程序载入后执行

 

加载应用程序进入前台

 

加载应用程序进入后台

 

22.block编程

Block 是一种具有匿名功能的内嵌函数块。Block 一般是用来表示、简化一小段的程式码,它特别适合用来建立一些同步执行的程式片段、封装一些小型的工作或是用来做为某一个工作完成时的回传呼叫(callback) 。格式如下:^(传入参数列) {行为主体};

 

23.常用的开源框架

网络框架:ASIHttpRequest,AFNetworking,coocaHttpServer等。

进度条:SVprogressHUD,MBprogressHUD,

工具类:SSToolKit等。

分享类:ShareKit等

日志框架:log4j,cocoa lumberJack 等。

等等。

 

24.通知消息和代理的区别

通知:分为本地和远程通知。接受通知的接受者需要进行注册改通知。这样通知被NSNotificationCenter发送出来后会被注册的接受者所接受。远程通知需要借助苹果的服务器去实现通知的中转。

代理:把某个对象要做的事情委托给别的对象去做。

两者区别:

delegate针对one-to-one关系,用于sender接受到reciever的某个功能反馈值。

notification针对one-to-one/many/none,reciver,用于通知多个object某个事件,sender只是负责把notification发送出去。

25.数据解析(json和XML)

json数据的解析通常借助一些开源的框架如:SBJson,TouchJson,jsonKit,Apple 提供的原生的JSon解析 NSJSON Serialization等。去json数据转化为IOS中常用的字典等。

XML数据的解析。xml分为SAX和DOM两种解析方式。

 

DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。

SAX解析XML,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,当在读取解析过程中遇到需要处理的对象,会发出通知对其进行处理。

一般在iOS平台下,比较常用的XML解析类库有如下几种:

NSXMLParser,,这是一个SAX方式解析XML的类库,默认包含在iOS SDK中,使用也比较简单。

libxml2,是一套默认包含在iOS SDK中的开源类库,它是基于C语言的API,所以使用起来可能不如NSXML方便。这套类库同时支持DOM和SAX解析,libxml2的SAX解析方式还是非常酷的,因为它可以边读取边解析,尤其是在从网上下载一个很大的XML文件,就可以一边下载一边对已经下载好的内容进行解析,*大的提高解析效率。

TBXML,这是一套轻量级的DOM方式的XML解析类库,有很好的性能和低内存占用,不过它不对XML格式进行校验,不支持XPath,并且只支持解析,不支持对XML进行修改。

TouchXML,这也是一套DOM方式的XML解析类库,支持XPath,不支持XML的修改。

KissXML,这是一套基于TouchXML的XML解析类库,和TouchXML相比,支持了XML的修改。

TinyXML,这是一套小巧的基于C语言的DOM方式进行XML解析的类库,支持对XML的读取和修改,不直接支持XPath,需要借助另一个相关的类库TinyXPath才可以支持XPath。

GDataXML,这是一套Google开发的DOM方式XML解析类库,支持读取和修改XML文档,支持XPath方式查询。

 

26.webservice

Web service是一个平台独立的,松耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。技术支持包含如下:

1.1 xml 和xsd

1.2 Soap

1.3wsdl

1.4 uddi

1.5调用RPC和消息传递

 

27.开发App的步骤,开发者账号,发布app到appstore

 

证书分两种:开发者证书、发布者证书。前者开发时使用,后者发布使用

(1) 模拟器调试无需代码签名;真机调试需开发者证书代码签名;发布时需发布证书签名

(2) 代码签名需要:证书+私钥,

(3) 真机调试时要求在设备上安装描述文件(provision profile),该文件包含信息:调试者证书,

授权调试设备清单,应用ID。一个应用对应一个描述文件。

28.类继承,类的扩展(extension),类别(category)

 

category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。
并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中。
(2)创建对私有方法的前向引用。
(3)向对象添加非正式协议。
继承可以增加,修改或者删除方法,并且可以增加属性。

category和extensions的不同在于后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的Category。

29.CAlayer介绍

一个UIView包含CALayer树,CALayer是一个数据模型。包含了一些用来显示的对象,在UIView的子类中都可以找到层这个组件,层是位于固定的画布上的一个子片,可以被覆盖。层是彼此堆叠在一起的*终产生一个界面。除此之层可以包含多个层,通过层可以操作位于此层上面的其他内容,例如旋转,动画,翻页等。

 

30.ios 怎么实现多继承

IOS通过实现protocol委托代理,实现多个接口来实现多继承。

 

31.app性能测试方式

通过Xcode提供的工具如Instrument,测试CPU,Mermory性能。也可以适用一些开源的自动化测试工具:如Frank,KIF等。

 

32.NSArray可以放基本数据类型不(int,float,nil)怎么放进一个结构体

NSArray 只能存放objective-c对象数据模型,这些基本数据类型需要先转化为NSNumber对象再存放进数组中。

 

33.objective-c和c,c++混合编写

在 Objective-C++中,可以用C++代码调用方法也可以从Objective-C调用方法。在这两种语言里对象都是指针,可以在任何地方使用。例 如,C++类可以使用Objective-C对象的指针作为数据成员,Objective-C类也可以有C++对象指针做实例变量。Xcode需要源文件以”.mm”为扩展名,这样才能启动编译器的Objective-C++扩展。

 

34.常见的语言编码(utf-8,unicode,gb2312,gbk)

常见的语言编码有:

 

GB2312:简体中文编码,一个汉字占用2字节,在大陆是主要编码方式。

BIG5:繁体中文编码。主要在台湾地区采用。

GBK:支持简体及繁体中文,但对他国非拉丁字母语言还是有问题。

UTF-8:Unicode编码的一种。Unicode用一些基本的保留字符制定了三套编码方式,它们分别UTF-8,UTF-16和UTF-32。在UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的*大好处,是UTF-8保留了ASCII字符的编码做为它的一部分。UTF-8俗称“万国码”,可以同屏显示多语种,一个汉字占用3字节。为了做到国际化,网页应尽可能采用UTF-8编码。

当然,处理中文时http头也要改成UTF-8编码的—–加上<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>。

 

语言                             字符集                                正式名称

英语、西欧语                ASCII,ISO-8859-1        MBCS多字节

简体中文                      GB2312                          MBCS多字节

繁体中文                      BIG5                               MBCS多字节

简繁中文                      GBK                                MBCS多字节

中文、日文及朝鲜语       GB18030                        MBCS多字节

各国语言                      UNICODE,UCS              DBCS宽字节

 

35.常见的加解密方式(rsa,aes,md5)

常见的加解密方式有:

RSA:基于公钥和私钥的非对程加密算法。适用范围广。

AES:是一种对程加密的流行方式。加密涉及矩阵运算。

MD5:将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,

 

36.objective-c语言的优缺点

objc优点:

 

1) Cateogies
2) Posing
3) 动态识别
4) 指标计算
5)弹性讯息传递
6) 不是一个过度复杂的 C 衍生语言
7) Objective-C 与 C++ 可混合编程
缺点:
1) 不支援命名空間
2)  不支持运算符重载

3) 不支持多重继承

4) 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。

37,ios应用的调试技巧

1.如遇到crash,分析崩溃日志(symbolicatedrash工具的适用)保留崩溃版本的.dSYM文件

2.在 XCode 中进入断点管理窗口;然后点击右下方的 +,增加新的 Exception Breakpoint。

3.如遇到EXC_BAD_ACCESS,打开Scheme选项选择EditScheme。然后按图勾上Enable Zombie Objects和Malloc Stack那两项。

4.有效的日志管理。NSLog和加入一些开源的日志管理框架。

5.程序断点debug模式。

 

38,应用程序性能的调优(转http://www.open-open.com/lib/view/open1365861753734.html)

 

1. 用ARC去管理内存(Use ARC to Manage Memory)

2.适当的地方使用reuseIdentifier(Use a reuseIdentifier Where Appropriate)

3.尽可能设置视图为不透明(Set View as Opaque When Possible)

4.避免臃肿的XIBs文件(Avoid Fat XiBs)

5.不要阻塞主进程(Don’t Block the Main Thread)

6.调整图像视图中的图像尺寸(Size Images to Image Views)

7.选择正确集合(Choose the Correct Collection)

8.启用Gzip压缩(Enable GZIP Compression)

9. 重用和延迟加载视图(Reuse and Lazy Load Views)

10.缓存,缓存,缓存(Cache,Cache,Cache)

11.考虑绘图(Consider Drawing)

12.处理内存警告(Handle Memory Warnings)

13.重用大开销对象(Reuse Expensive Objects)

14.使用精灵表(Use Sprite Sheets )

15.避免重复处理数据(Avoid Re-Processing Data)

16.选择正确的数据格式(Choose the Right Data Format)

17.适当的设置背景图片(Set  Background Images Appropriately)

18.减少你的网络占用(Reduce Your Web Footprint)

19.设置阴影路径(Set the Shadow Path )

20.你的表格视图Optimize Your Table Views)

21.选择正确的数据存储方式(Choose Correct Data Storage Option)

22.加速启动时间(Speed up Launch Time )

23.使用自动释放池(Use AutoRelease Pool)

24.缓存图像(Cache Images-Or not )

25.尽可能避免日期格式化器(Avoid Date Formatters Where Possible)

 

39.UIScrollView 的contentSize、contentOffSet和contentInset属性的区别

contentSize表示UIScrollView滚动区域的大小。UIScrollView的frame属性在设置好了以后不会随内容的变化而变化。

contentOffSet表示是UIScrollView当前显示区域顶点相对于frame顶点的偏移量,一般用来设置UIScrollView显示的位置。

contentInset表示是scrollview的contentView的顶点相对于scrollview的位置,假设你的contentInset = (0 ,100),那么你的contentView就是从scrollview的(0 ,100)开始显示。一般都是(0,0)表示从scrollView的开始显示。

 

40.IOS6 AutoLayout

AutoLayout是IOS6之后引进的自动布局功能,有点类型有android的相对布局属性。通过勾选AutoLayout设置各种Constraint约束来实现在不同设备和不同方向上的自动布局。autosizing mask也就是 “springs and struts” 模式。autosizing mask决定了一个view会发生什么当它的superview 改变大小的时候。而autolayout 不仅可以设置superview改变时view所做的变化,还支持当相邻view变化时自己所做的变化。