————————————————————————————————————————————
Hello World
//引入头文件
//c中的引入头文件的方式
//#include <stdio.h>
//#include <Foundation/Foundation.h>
#import <Foundation/Foundation.h> //引入头文件(单单引入这一个头文件,无后顾之忧,里面包含了太多的头文件,一有全有)
//1、面试题:为什么要使用import,import和include的区别
//include 和 import 都是引入头文件
//import引入的头文件,可以防止重复包含,什么是重复包含呢,简而言之,重复包涵就是多次包含相同的头文件,编译时间会大大增加,而对程序的最终结果危害不大。这也是import先进的地方,以后都用import吧
//include它是使用预处理指令防止重复包含,如果没有写预处理指令,则无法防止重复包含问题
//2、import 和 @class的区别
//3、Foundation/Foundation.h 是什么东西
// 1)头文件
// 2)头文件的位置
// 3)文件包含了其他的大量的头文件
// /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
// 作用:把Foundation.h引入了,等于把OC的库文件都引过来了
int main(int argc, const char * argv[]) {//小括号里面的东西可以省略,无参
@autoreleasepool {//这里是一个自动释放池,现在先不涉及,以后内存管理的时候需要用到
//strlen(<#const char *#>) 虽然没引入包含计算字符串长度方法的头文件,但是这只是表面现象,我们引入了<Foundation/foundation.h>之后就全有了!所以说其实我们已经引入了包含计算字符串长度方法的头文件了。
// insert code here...
//NSLog是一个函数,里面必须有@,@表示后面跟一个字符串,等价于printf函数,而且NSLog该大写的地方一定要大写
//作用:向控制台输出字符串
NSLog(@"Hello, world!");
}
return 0;
}
————————————————————————————————————————————
NSLog函数的使用
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
//NSLog和printf使用的差异
//1、NSLog 会自动换行 而printf不会自动换行
//2、NSLog 会自动输出时间等项目信息,printf不会输出调试信息
//3、NSLog 函数的参数是一个NSString 对象
// printf输出的是一个字符串常量指针
NSLog(@"Hello, World!”); //记住,一定要加@符号,因为@符号是要加在所有的字符串前面的。这表明了这个字符串是一个oc字符串,而不是c字符串
printf("Hello, World!\n");
//2、NSLog格式化输出的问题
#import <Foundation/foundation.h>
int main()
{
char a='X';
int b=19;
float c=1.23;
double d=3.566;
printf("a=%c,b=%d,c=%.2f,d=%.2f\n",a,b,c,d);
NSLog(@"a=%c,b=%d,c=%.2f,d=%.2f",a,b,c,d);//NSLog可以和printf一样输出,不同之处要再字符串格式的前面加一个@符号。也可以说明OC向下包容C
char *ch="412sss王中尧4rfd";
printf("%s\n",ch);
NSLog(@"\n----->%s",ch);//该行无法正常输出。不能这么写的,在oc中有oc的格式(注意,这里是字符串,刚刚验证了一下,如果字符串中包含汉字字符,则整个字符串都无法正常输出,但是如果是只含一般的字母和数字,是可以正常输出的,这里注意一下。虽然这么说,但是总而言之,oc还是有自己固定的格式,所以还是用oc自己的方式去定义字符串和用oc的格式去输出字符串吧。)
NSString *e=@“34gwerger43g王中尧”;//oc中声明并初始化一个字符串是和c不一样的,是NSString *abc=@“asdfasfa”; 一定要声明成字符串指针变量的形式哦!
NSLog(@"%@",e);//%@即oc字符串的格式,oc中打印oc字符串的格式也是不同的
//当然也不能用printf去打印e,因为NSString是oc独有的,C是不支持的。
//如: printf("%@",e); 这条语句只能打印出一个@号,但是字符串e是打印不出来的
//所以说,oc很傲娇,我们只能用oc的格式去打印oc的字符串等
return 0;
}
————————————————————————————————————————————
@符 和 注释符 的使用
@符
1)@“ ”
这样在@后面跟一个字符串,表示将C字符串转化为OC的字符串,这也是OC字符串特有的表示形式
2)@标识符 OC中大部分关键字都是以@开头的,比如@inferface,@end,@class
注释符
1)单行注释 //
2)多行注释 /* */
3)文档注释 /**
*
*
*/
文档注释可以在代码中提示这一部分的信息,挺好的。
———————————————————————————————————————————
访问OC源文件、C源文件中的函数
这一部分我们建立了一个oc program(包含main.m文件),和一个c文件(包括源文件和头文件)。接下来展示三个文件中的具体代码并讲解:
1)main.h文件
#import<Foundation/foundation.h>
#include "CC.h"
int main()
{
void test();
test(); //成功调用,显然,再oc中是可以访问c函数的
ctest2(); //我们建立了一个c文件,然后再头文件(.h)中声明了一个函数,在源文件(.c)中实现声明了的方法。所以我们可以这样理解,要把方法声明写在头文件(.h)中,把方法定义写在源文件(.c)中.(刚刚测试了一下,将方法声明和定义都写在源文件(.c)中也是可行的。为什么可行呢,想一下,刚开始只学c的时候不就是新建项目就出现一个main.c么,开头还引入了stdio.h的头文件)。
//解释一下c语言的源文件(.c)和c语言的头文件(.h):我们平常写的代码都是在源文件里,但是我们学习c的时候通常在这个源文件中将函数的声明和定义都包含了。在我们的源文件(.c)中由于需要对外提供接口,因此在源文件(.c)必须有一些函数或者是变量提供给外部其他文件进行调用。而头文件(.h),我们可以将他看成是一份接口描述文件,可以形象的理解成一份说明书,说明的内容就是我们的模块对外提供的接口函数或者是接口变量,同时也包含了一些宏定义和结构体信息,离开这些信息,很可能就无法正常使用接口函数和接口变量。总的来说,应该让外界知道的必须信息就应该出现在头文件(.h)里,不该让外界知道的信息就不应该出现在头文件(.h)里。这也就是模块化编程的概念。
return 0;
}
void test()
{
printf("1231\n");
}
2)CC.c
#include “CC.h"
//使用<>这种方式,编译器查找的时候,会在编译器的安装目录的标准库中开始查找,””这种方式,会在当前的工程所在的文件夹开始寻找,也就是你的源程序所在的文件夹。所以说编译器中有的一般用< >,而自己写的头文件,一般用 “ ” 。
void ctest2()
{
printf("This is a ctest2!!!");
}
3)CC.h
#include <stdio.h>
void ctest2();
———————————————————————————————————————————
C与OC的差异(1)
OC 和 C对比学习
1) 文件的差异:
C中有 .c(源文件) .o(目标文件) .out(可执行文件) .h(头文件)
OC中有 .m(OC的源文件) .h(头文件) .mm(OC++的源文件) 前两个重点记忆
这里再次强调一下,头文件中包含方法、属性的声明,源文件中包含类的实现文件,参与编译的文件,用来实现类中声明的方法。
2)数据类型差异
C中包括:基本类型(整型、字符型、实型)、构造类型(数组、结构体、共用体、枚举类型)、指针类型、空类型(void)、定义类型(typedef)
OC中包括:基本数据类型(数值型(数值型、浮点型)、字符型、布尔型、空类型)、Block类型(有参数和返回值的代码块)、指针数据类型(类:class、id类型:在运行时才知道其中值类型是什么,编译的时候都不知道。也被形象的成为万能指针)、特殊类型(SEL、nil(对象为空))
3)关键字差异
新增的关键字大部分有@标记,少数新增关键字需要特殊记忆一下,在此不列出了
4)流程控制语句
OC中并没有增加新的流程控制
OC中提供一种增强型的for循环(唯一多了一个增强的for循环)
NSArray *arr=@[@"one",@"two",@"three"];
for(NSString *str in arr){
NSLog(@"%@",str);
}
5)OC中函数的定义和声明的差异
C语言中的函数
int max(int x,int y);
int max(int x,int y){
return x>y?x:y;
}
OC中把 函数 称之为 方法 (这里必须注意!要称之为方法。下面怎么做的暂时不解释)
+(void) test;
-(void) test;
-(int)max:(int)x andY:(int) y;
*/
下面的程序为大家展示了OC的增强for循环
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray *arr=@[@"one",@"two",@"three"];
//OC中的增强型for循环
for(NSString *str in arr){
NSLog(@"%@",str);
}
}
return 0;
}
———————————————————————————————————————————
C与OC的差异(2)
/*
1、新增的数据类型介绍
Boolean用来存放逻辑值
逻辑值: 真1 假0
OC中也可以使用 true 表示真 false表示假
用来存放true和false的结果的变量一般我们声明为 Boolean
2、异常捕捉的方法
*/
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
//1、Boolean类型的使用
Boolean flag = true;
//false 假 0
flag = false;
//true 真 1
printf("flag = %d\n",flag);
//用Boolean类型的变量经常用于条件判断
if(flag){
printf("xxxxxxx\n");
}
//2、存放逻辑值的另外一种方法
//BOOL 它的取值 YES 和 NO
//YES 真 1
//NO 假 0
BOOL flag2 = YES;//这里一定要注意BOOL是大写(下面是在网上精简的资料,但是还是不是太明确这个概念,还得慢慢琢磨)
/* bool只有一个字节。bool取值false和true,是0和1的区别; false可以代表0,但true有很多种,并非只有1,是剩余所有非0的值。 也就是说你定义一个bool型的变量,他的值非零,那么输出这个bool型的变量,结果就是1,反之同理。
BOOL视环境而定,一般是4个字节,BOOL是微软定义的typedef int BOOL(在windef.h中)。与bool不同,它是一个三值逻
辑,TRUE/FALSE/ERROR,返回值为大于0的整数时为TRUE,返回值为0时候,为FALSE,返回值为-1时为ERROR。
*/
printf("YES = %d\n",YES);
printf("flag2 = %d\n",flag2); // 1
flag2 = NO; //0
//flag2 == YES
if (flag2) {
printf("0000000000\n");
}
// 1/0
int a = 1;
int b = 1;
b = NO;
//注意:try catch 并不能检测所有的错误
//先了解!
@try {
//此处放的事有可能出错的代码
int result = a/b;
}
@catch (NSException *exception) {
//此处放出错以后 我们处理的代码
}
@finally {
//不管出没出错,这里的代码一定会执行
printf("fengjie!\n");
}
}
return 0;
}
———————————————————————————————————————————
面向对象编程的概念
面向过程:做一件事需要哪些步骤。关注的是解决问题的步骤。
面向对象:做一件事我需要哪些对象帮我去做,建立许多模型,来帮助我们完成。关注的是解决这个问题需要哪些具备相应功能对象。(当然面向对象是基于面向过程的,每一个对象的模块里面还是存在许多操作步骤的)
例子:
洗衣服这件事我们从面向对象和面向过程两个角度去分析:
面向过程:1、打开洗衣机 2、放进去衣服和洗衣粉 3、按下开关开始洗 4、洗完了之后拿出来晾起来
面向对象:1、找个女朋友 2、让女朋友去洗
———————————————————————————————————————————
类和对象
类是具有 相似内部状态(属性) 和 运动规律(行为) 的实体的集合(一种统称,或者是一种抽象)
类的内部状态是指类的集合中所有对象 共同的 状态,类的运动规律是指类的集合中对象 共同的 运动规律 。
比如说,有一个学生类:
年龄 班级 姓名 性别 —————— 类的属性
写作业 回答问题 考试 —————— 类的行为(方法)
张三 李四 —————— 类的对象
类的对象也就是将类实例化了。
我们可以联系到以前学过的结构体,很相似,但是不是一回事。比如类的属性就可以看成结构体的成员变量,但是结构体是不定义方法的。
———————————————————————————————————————————
类的声明和实现
/*
1> 方法的声明和实现,都必须以 + 或者 - 开头
+ 表示 类方法(静态方法)
- 表示 对象方法(动态方法)
2> 在.h中声明的所有方法作用域都是public类型,不能更改
*/
#import <Foundation/Foundation.h>
//类的声明
@interface Car:NSObject //@inerface 类名:父类名 这个地方后面的父类名为NSObject,这个暂时先这么固定写法
{
//类的属性在这里定义
int lunzi;
NSString *color;//用oc的方法定义字符串
int speed;
}
//类的行为(方法)在这里声明,暂时不写。
@end
//类的实现
@implementation Car
{
//code(行为(方法)的具体实现)
}
@end
int main()
{
@autoreleasepool {
}
return 0;
}
———————————————————————————————————————————
创建一个对象并访问成员变量(属性)
成员变量的常用 作用域 有3种:
1> @public 全局都可以访问
2> @protected 只能在类内部和子类中访问
3> @private 只能在类内部访问
代码:
#import <Foundation/Foundation.h>
@interface Car : NSObject
{
@public;//这个地方让属性变成全局的,这样就都能访问了,否则
NSString *name;
int lunzi;
int speed;
NSString *color;
}
//方法声明在这里(@interface和@end之间,且在大括号之外。如果没有属性,也就没有大括号,属性是可以没有的)
@end
@implementation Car
{
//行为(方法)的具体描述
}
@end
int main()
{
@autoreleasepool
{
Car *car=[Car new];//这里在编写代码的时候,为了规范,我们可以先写[Car new],再写前面的部分,也看起来很专业。
//★★★另外注意:所有OC对象都是用指针变量来接收的,如果你不了解指针,你记住下面这点就行了:利用类名定义一个变量时,类名后面一定要带个*号。★★★
//OC中对象创建
//[Car new];
//做了3件事情
// 1)向计算机申请内存空间
// 2) 给类中的每一个成员初始化值
// 3)返回新申请的空间的首地址
//理解方式一:
//定义了一个Car类型的指针变量
//指针变量指向新申请的内存空间
//理解方式二:(这是我们以后常用的理解方式)
//用Car类实例化了一个实例对象car
car->name=@"shifeng";//为我们实例化的对象属性赋值时,记得用 -> ,用 . 来访问会出错
car->lunzi=3;
car->speed=120;
car->color=@"blue";
NSLog(@"name:%@,lunzi:%d,speed:%d,color:%@",car->name,car->lunzi,car->speed,car->color);
//当然输出的时候也要用->来调用!!!
}
return 0;
}
———————————————————————————————————————————
无参方法的声明、实现和调用
#import <Foundation/Foundation.h>
@interface Car:NSObject
{
@public;
NSString *name;
int speed;
NSString *color;
}
-(void)run;//这是声明了两个无参无返回值的函数
-(void)stop;
@end
@implementation Car //这里记住下面是不用大括号将两个方法的实现括起来的,只有属性的定义需要括起来(@interface的下面属性部分),关键字@end其实起了一个大括号的作用了
-(void)run //动态方法,也就是成员方法
{
NSLog(@"123");
}
-(void)stop
{
NSLog(@"456");
}
@end
int main()
{
@autoreleasepool {
Car *car=[Car new];
car->name=@"shifeng";
car->speed=@"120";
car->color=@"blue";
NSLog(@"name:%@\nspeed:%d\ncolor:%@",car->name,car->speed,car->color);
//调用方法。调用格式为: [对象名 类方法名];
[car run];
[car stop];
}
return 0;
}
———————————————————————————————————————————
有参方法的声明、实现和调用
下面是一个计算器的类,用来简要说明这一部分的知识:
#import <Foundation/Foundation.h>
@interface Caculator : NSObject
{
@public //不一定要加冒号
int _num1; //类中的属性,记得要用下划线加属性名的格式,标准格式
int _num2;
}
// -(返回值类型)方法名1:(参数类型) 参数名; //有一个参数的方法
// -(返回值类型)方法名1:(参数类型1) 参数名1 and:(参数类型2) 参数名2; //有2个参数的方法
// -(int)sum:(int) x and:(int) y; //方法的声明
// 有参方法的使用注意:
// 方法的类型 - 对象方法(动态方法)
// 方法的返回值类型: int 类型
// 方法的参数是: x y
// 参数的类型: 第一个 int 第二个 int
// 方法名: sum: and: (冒号是方法名的一部分)
-(int)sum;//声明了一个无参函数sum
-(int)sum:(int) x andaaa:(int) y;//有两个参数的函数 sum: and:(这里的函数名是 sum: and: 所以说不和上面的无参函数重名)
@end
@implementation Caculator
-(int)sum //无参,有返回值的方法
{
return _num1+_num2;
}
-(int)sum:(int) x and:(int) y and:(int) z //有参,有返回值的方法,每多一个参数,就多加一个 and:
{
return x+y+z;
}
@end
int main()
{
@autoreleasepool
{
Caculator *a=[Caculator new];//还是注意创建类的实力对象的时候,一定要是指针类型。有一个小技巧,在后面写[Caculator new] 的时候,可以先写里面的,然后再写后面半个中括号‘]’ ,这样前半个中括号也自动生成,很方便。
//对象访问实例变量
a->_num1=12;
a->_num2=13;
//调用无参方法
int s1=[a sum];
//调用有参方法
int s2=[a sum:13 and:14 and:15];
NSLog(@"%d,%d",s1,s2);
}
return 0;
}
下面是一个iPhone的类,加深这部分知识的理解:
/*
类名:苹果手机(iPhone)
属性:颜色(_color ), 大小(_size), _cpu
行为:查看本机信息(aboutMyPhone),打电话(call), 发短信(sendMessage)
实现该类,并:
1)查看本机信息
2)打电话给10086
3)给10086发短信问联通的客服电话是多少
*/
#import<Foundation/Foundation.h>
typedef enum {kColorWhite,kColorBlack,kColorTHJ} iColor; //定义一个枚举类型,用于声明一组命名了的常数,所以要用%d输出。这样解释就明白了把~
//typedef enum { 枚举成员 } 枚举名称;
@interface iPhone : NSObject
{
@public
iColor _color; //将颜色这个属性声明为枚举类型,比设置成字符串类型更规范,可读性更高。
float _size;
NSString *_cpu; //字符串类型的属性,要定义成字符串类型的指针变量
}
//方法的声明
-(void)about_My_iPhone; //无参无返回值的方法,用来查看本机信息
-(void)calltelephone:(NSString *) telNum; //有一个参数telNum(字符串类型)无返回值的方法,用来打电话
-(void)setMessage:(NSString *) telNum and:(NSString *) content; //有两个参数telNum、content(内容的意思),用来给某某发短信
@end
@implementation iPhone
-(void)about_My_iPhone //无参无返回值的方法,用来查看本机信息
{
NSLog(@"Color:%d,Size:%.2f,Cpu:%@",_color,_size,_cpu); //输出字符串属性值的时候,并不用加*号,直接用属性的名字即可( _cpu )。输出枚举类型的时候用的是%d,这里要切记!
}
-(void)calltelephone:(NSString *) telNum //有一个参数telNum(字符串类型)无返回值的方法,用来打电话
{
NSLog(@"call %@ by iPhone",telNum);
}
-(void)setMessage:(NSString *) telNum and:(NSString *) content //有两个参数telNum、content(内容的意思),用来给某某发短信
{
NSLog(@"set %@ to %@",content,telNum);
}
@end
int main()
{
@autoreleasepool {
iPhone *abc=[iPhone new]; //一定一定要注意,实例化类的对象的时候一定要实例化成指针变量的类型!!!切记!!!
abc->_color=kColorWhite;
abc->_cpu=@"ahagargrax";
abc->_size=9.9;
[abc about_My_iPhone];
[abc calltelephone:@"10086"]; //字符串实参记得加@“”,这一点不要忘记!!!
[abc setMessage:@"10086" and:@"i love you"];
}
return 0;
}
———————————————————————————————————————————
声明:
作者按照黑马 如意大师 的教学视频学习,内容主要来自如意大师的视频讲解,另外在学习过程中查找了大量的辅助资料,综合完善了这部分的笔记内容。内容的概括一部分来自于如意大师的教学笔记,一部分来自于我自己的编排理解。无论是哪一部分,都是作者亲自手敲验证(包括代码和注释),没有一点是完全copy的。仅供作者本人翻看复习,当然喜欢的读者可以来看一下,绝对会对你的学习有帮助的。
版权声明:本文为博主原创文章,未经博主允许不得转载。