Objective-C 学习笔记(Day 1)

————————————————————————————————————————————

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的。仅供作者本人翻看复习,当然喜欢的读者可以来看一下,绝对会对你的学习有帮助的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/wzy294250051/p/4787901.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值