=====文档变更状态====
2015-12-14:发布
=================
day01_2015-12-10
一、要求
要求:此处就不在贴出来了
二、阶段内容
1.OC语法:ObjectiveC
2.框架库:
// first.m
#import<Foundation/Foundation.h>
int main(){
NSLog(@"this is my first Obj-C.");
return 0;
}
注意:
1>关于import
#import可以防止重复包含,#include需要自己添加防止重复包含的代码[#ifndef XXX #define XXX #endif],#import需要自己写
2>关于Foundation框架.
[需要下载foundation文档,自己研究]
3>关于快捷键
A. 运行:
B. 注释、取消注释
C. 整行删除:行末尾command+delete
三、基本语法
1.NextStep:NS
Log:日志
2.vi编辑器
A。终端模式下:vi 文件名
B.按“i”进入编辑模式
C.保存:按”esc”键再按“:”键进入命令模式,输入“w”(保存)、“q”(退出)或“x”(保存并退出)、“q!”(不保存强制退出)
3.编译:cc(或clang) -framework Foundation 文件名
4.import和include的区别:
import不会重复嵌入相同的文件,include需要通过预处理命令判断是否重复
5.命名规范:
A.见名知意:age name
B.骆驼命名:第一个单词全小写,以后每个单词首字母大写,用在函数、方法、变量、属性的定义上:firstName lastName
C.Pascal命名:每个单词首字母大写,用在类(类型)、协议、分类、扩展:FirstName LastName
OC中:综合使用骆驼和Pascal命名规范,如
Int age;
Int firstName;
NSString *str=@””;
NSMutableString;
D. 前缀:一般以公司名的缩写作为前缀(如:NS,UI,CG)
—————–休息一会儿———–
数据类型:
1>注意NSInteger,NSUInteger 是用typedef定义的别名会根据平台自己适应
2>对于BOOL类型
Bool flag =100;
if(flag == YES)// 注意这里输出NO与我的原意不同。把flag ==YES -> [ if(flag !=NO) 或者 直接写if(flag) ] 即可
{
printf:YES;
}
else
{
printf:NO;
}
typedef singned char BOOL (char 有没有符号可以在项目中设置,在项目中搜索char即可)
OC中在扩展C时几乎没有增加基本类型,只是用typedef重新定义和新定义类
3>id,SEL是数据类型,后面再学
四、NSString
1.简单定义:NSString* str=@“…”;
2.输出:使用NSLog函数,以及%@占位符
3.NSLog的%s不支持中文字符,必须转换为NSString后使用%@占位符,语法如下:
NSString* str=[NSString stringWithUTF8String:chs];<是下面方法的高效版,弊端在于编码不能指定>
或者
NSString* str=[NSString stringWithCString:chs encoding:NSUTF8StringEncoding];
4.printf不能使用%@,使用%s不能输出OC字符串,需转换为C字符串,语法:
char* s2=[str cStringUsingEncoding:NSUTF8StringEncoding];
// main.m
#import <Foundation/Foundation.h>
int main1(int argc, const char * argv[]) {
BOOL flag=0;
// 不建议使用:if (flag==YES)
// 可以使用:
// if (flag!=NO)
// 或
if(!!flag){
NSLog(@"YES");
}
else{
NSLog(@"NO");
}
NSString* str=@"hello world";
char *s1="你好 c语言";
// printf的占位符%s不能用于输出OC字符串
// printf("str:%s\n",str);
NSLog(@"str:%@",str);
printf("s1:%s\n",s1);
// OC的NSLog函数可以使用%s输出C语言字符串,前提是字符串中只有ASCII码字符
// 将C语言字符串转换为OC的字符串,否则中文字符无法输出
NSString* str1=[NSString stringWithUTF8String:s1];
NSLog(@"str1:%@",str1);
// 将C语言字符串按照指定编码转换为OC字符串
NSString* str2=[NSString stringWithCString:s1 encoding:NSUTF8StringEncoding];
NSLog(@"str2:%@",str2);
//OC字符串同样可以转换为C的字符串
printf("str2:%s\n",
[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
return 0;
}
注意:
1>NSLog并不完全兼容C字符串
关于NSLog只能用%s输出c中ASSIC字符串而含有非ASSIC字符的C字符串不能输出但可以用printf输出,可以把这种c字符串转化为OC字符串最后以%@输出即可或者用printf函数输出,否则无法输出
NSString *str= @"xiaobai小白";
char *str1 = "xiaobai小白";
char *str2 = "xiaobai";
printf("%s,%s\n",str1,str2);
NSLog(@"--(%@)--(%s)--(%s)--\n",str,str1,str2);// str1中含有非ASSIC字符不能输出,NSLog并不完全兼容C字符串,str2没有非ASSIC字符,全部输出了
输出结果为:
xiaobai小白,xiaobai
2015-12-10 14:31:10.857 1210课堂[1270:1248408] --(xiaobai小白)--()--(xiaobai)--
Program ended with exit code: 0
2>C字符串和OC字符串之间的转化
一个是以NSString开头、一个是以对象名开头
五、块Block
1.提高程序运行速度,类似于函数的代码块机制
2.可以在函数(或方法)内定义并调用
3.语法:^返回值类型{代码块};
4.定义块变量和定义块:返回值类型 (^块变量名)(参数列表)
=^返回值类型{代码块};
A.等号左边的返回值类型,在没有返回值时使用void
B.形参类型列表:只需要形参类型,无需形参名;int、void可以省略
C.等号右边的返回值类型可以省略void、int类型的说明
与定义函数指针相比定义块变量只是把*换成^,注意在定义块变量时返回值类型void不能省,在定义块时返回值void可以省;等号左边的参数列表可以只写类型不写形参,右边的参数列表要写形参
5.可省略部分,如果返回值类型是int或void可以省略;定义块变量时,=左边的参数列表可以全部省略(但圆括号不能少)
6.调用:块变量名(实参);
7.块外变量:默认情况下,可以读取,不可以修改;如果需要修改,增加修饰符__block,增加后块的编译会有变化,效率会降低,应尽量避免
8.块的类型定义(typedef):类似于函数指针类型定义
语法:typedef 返回值类型 (^块类型)();
使用块类型定义块变量:
块类型名称 块变量名=块定义语法;
// block1.m
// 定义块变量和块
#import <Foundation/Foundation.h>
int main2(){
// 定义无参数无返回值的块变量和块
void (^bk1)()=^(){
NSLog(@"this is a block");
};// 此处的块在调用时才会运行编译链接时不会执行NSLog
bk1();
NSLog(@"----------");
// 无参数有返回值的块变量
int (^bk2)()=^(){
NSLog(@"this is a block with return type.");
return 10;
};
int a=bk2();
NSLog(@"a=%d",a);
NSLog(@"----------");
// 有参数有返回值的块变量
int (^bk3)()=^(int a,int b){
NSLog(@"this is a block with return type and parameter.");
return a+b;
};
int sum=bk3(10,35);
NSLog(@"sum=%d",sum);
return 0;
}
注意:
1>定义块变量和定义块的方式
2>等号左边的参数列表可以只写类型不写形参,右边的参数列表要写形参
3>为了防止出错不要省列返回值类型<即除了上面一条能可以省其它都不要省>
// block2.m
// 块与内、外部变量
#import <Foundation/Foundation.h>
int a=100;
void f1(){
NSLog(@"function f1:a=%d.",a);
}
int main3(){
f1();//100
a=200;
f1();//200
__block int b=10;
// __block有2个意思:1.让块中的变量可以向此
变量写值
2. 块外的修改能影响块内(上面一点只在
第一次影响)
这个代码块整体和函数的作用相同
void (^bk)()=^(){
// b=100;// 由于加了__block所以可以写值,
NSLog(@"block:b=%d.",b);
};
bk();//10
b=20;
bk();//20
return 0;
}
注意:
1>自己先研究一下执行流程
2>没有__block修饰b,在块中只能读取b的值且只读取一次,当加了
__block修饰就不仅能读还能写且读写多次
//--------------第二块相关代码----------
#import <Foundation/Foundation.h>
int b=10;
void ptb(){
NSLog(@"b=%d",b);
}
int main_4(){
// ptb();//10
// b=20;
// ptb();//20
__block int a=10;
int c=10;
void (^bk)()=^(){
a++;
NSLog(@"this is the first block.a=%d,c=%d",a,c);
};
NSLog(@"============");
bk();//a=11 c=10
c=20;
bk();//a=12 c=10
return 0;
}
注意:
1>自己先研究一下执行流程
2>没有__block修饰b,在块中只能读取b的值且只读取一次,当加了
__block修饰就不仅能读还能写且读写多次
3>关于第二点的唐僧解释
对于函数中定义的局部变量,默认在块中只能读取,不能修改,并且读取到
的值是定义块变量是的值,即使以后修改过局部变量,对块也没有影响;
如果需要修改局部变量或者希望块外的修改有影响,需要给局部变量增加
修饰符:__block
// block3.m
#import <Foundation/Foundation.h>
typedef int (*FuncPointer)(int,int);
typedef int (^BlockType)(int,int);
int maxTwoInt(int a,int b){
return a>b?a:b;
}
int minTwoInt(int a,int b){
return a>b?b:a;
}
void calc(int x,int y,FuncPointer fp){ //函数指针作为参数
NSLog(@"fp:%d",fp(x,y));
}
void calcWithBlock(int x,int y,BlockType bt){ // 代码块作为函数参数
NSLog(@"bt:%d",bt(x,y));
}
int main(){
NSLog(@"函数指针用法");
int a=100;
int b=20;
calc(a, b, maxTwoInt);// 在给maxTwoInt中函数指针传参时必须在main函数外定义
calc(a, b, minTwoInt); // 在给minTwoInt中函数指针传参时必须在main函数外定义
NSLog(@"块类型定义用法");
BlockType maxBK=^int(int a,int b){ // 在main函数中定义代码块
return a>b?a:b;
};
// BlockType minBK=^int(int a,int b){
// return a>b?b:a;
// };
calcWithBlock(a,b,maxBK); // 直接传main函数中定义的代码块
calcWithBlock(a,b,^(int a,int b){ // 在给代码块变量传参时直接定义
return a>b?b:a;
});
return 0;
}
注意:
代码块与函数指针的区别与联系
区别
1> 函数指针作为参数时要在main函数外先定义,然后再传参数如上面的calc函数,不能在一个函数中定义另一个函数如不能在main函数中
定义 maxTwoInt 和minTwoInt函数;代码块可以在传参数时直接定义如第二个calcWithBlock函数,也可以在其他之前的地方定义如第一个calcWithBlock函数且可以在一个函数中定义代码块如在main函数中定义了maxBK代码块
联系
1> 从功能上看它们都能实现相同的功能但用block块会有更高的效率
注意体会上面calc和calcWithBlock函数所蕴含的设计思想
这种设计使得这两个函数具有更好的扩展性