OC学习_1_一些常识

=====文档变更状态====
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函数所蕴含的设计思想
这种设计使得这两个函数具有更好的扩展性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值