OC基础-day02

#pragma mark - Day02_01_对象的创建与使用

 

1)如何通过类创建一个对象

 

        1. 类是抽象的,无法直接使用

 

        2. 对象是类的一个具体实现,可以直接使用

 

        3. 语法

 

        类名 *对象名 = [对象名   new]

 

 

 

2)如何使用对象

 

        1. 类中有什么,对象中就有什么,类中有的属性,对象中都可以访问

 

        2. 类中的成员变量,默认外界不能访问,我们需要加上修饰符@public

 

        语法:

        对象名 -> 属性名

还可以这么使用:(*对象名).属性名

 

"扩展

 

属性:    通常是类暴露出来,外界可以访问或者修改(不一定真实存在)

成员变量: 类声明大括号里面的变量(对象类型和基本数据类型)

实例变量: 类声明大括号里面的变量(对象类型)

 

"练习

1.定义类

2.通过类来创建对象

3.使用对象

 

 

#pragma mark - Day02_02_犯错列表

 

    1). 声明和实现 类名要一致.

    2). @interface下面有1个大括弧,这个大括弧中才是写属性的.

    3). 属性名一定要以下划线开头.

    4). 属性是指针的时候,*要么和类型写在一起,要么和属性名写在一起,要么写中间,

    5). 对象名其实是个指针变量,所以,对象的命名要遵守变量的命名规范.

    6). 访问对象的属性的时候,虽然可以使用*去访问,但是你最好不要这么做,因为所有人都不这么做.都是使用->来访问的.

    7). 通过对象名来访问对象的属性的时候,

    对象名->属性名;

    属性名是带了下划线的.

    8). 默认情况下,对象的属性是不允许被外界访问的,应该加1@public

    9). 为对象的属性赋值,其实就是为对象的属性变量赋值,类型要和属性的类型一致.

    10). 在类的外部不能直接操作属性,必须要创建对象,操作对象的属性.

    11). 无论是为属性赋值,还是取属性的值, 都是操作的对象的属性,都要通过对象名来操作.

 

#pragma mark - Day02_03_无参数的方法的声明实现调用

 

1)方法定义

 

        用来描述类共同的行为

 

        类似于函数,只是跟语法不同

 

2)语法:

 

        无参方法:

 

        声明位置:放在类声明中{}的外面

 

        - (返回值类型)方法名称;

 

        - (void)run;

 

        实现位置:放在类的实现中

 

        - (void)run {

            

            。。。。

            

        }

 

        调用

 

        使用类的对象调用。

 

        语法[对象名  方法名]

 

 

 

 

#pragma mark - Day02_04_1个参数的方法的声明实现调用

 

1)声明

 

    位置 同样是在.h{}外面

 

    语法 - (返回值类型)方法名:(参数类型)形参

 

2)实现

 

    位置,同样是在.m

 

    语法,加上{}实现就行,并且直接可以使用形参

 

3)调用

 

    [对象名  方法名:参数]

 

    把对用的参数穿进去就可以了

 

 

 

 

#pragma mark - Day02_05_带多个参数的方法的声明实现调用

1)声明

 

    位置 同样是在.h{}外面

 

    语法 - (返回值类型)方法名:(参数类型)形参1    :(参数类型)形参2    ......

 

2)实现

 

    位置,同样是在.m

 

    语法,加上{}实现就行,并且直接可以使用形参

 

 

 

 

3)调用

 

    [对象名  方法名:参数1   : 参数2]

 

 

 

 

#pragma mark - Day02_06_方法的命名规范

1)方法的名称

 

方法带参数,:也是方法的名字

 

- (void)run;

- (void)runWithSpeed:(double)speed;

- (void)runWithSpeed:(double)speed1 :(double)speed2;

- (void)runWithSpeed1:(double)speed1 speed2:(double)speed2;

 

2)命名规范

 

1.只有一个参数:  XXXXWith:参数   XXXXWithXXXX:参数

 

 

2.多个参数:XXXwith:参数  and :参数

 

 

3.不要使用拼音

 

#pragma mark - Day02_07_1个类的多个对象之间毫无关系(重点)

 

 

1 1个类,可以创建无数个对象.

        对象可以创建很多个.所以你在访问属性的时候,必须要指定访问的是那1个对象的属性或者方法.

 

2 1个对象都有自己的属性.

        每创建1个对象,这个对象中都有自己的属性和方法.

        1个类的多个对象之间毫无关系.

        唯一的关系是:他们是根据同1个类模板创建出来的.

        对象中具有相同的属性和方法.

        但是对象的属性的值,各自是各自的 不相互影响.

 

 

 

#pragma mark - Day02_08_在方法的实现中直接访问属性(较难)

 

1 在方法的实现中,可以直接访问本类的属性.

如果在方法中直接访问了属性的.

 

方法是通过对象来调用.方法是通过那1个对象来调用的.那么这个方法中访问的属性就是那1个对象的.

 

 

 

#pragma mark - Day02_09_案例演示

 

1)创建一个对象 Person

 

特征: 姓名 年龄 体重 智商

 

行为: 爬山 学习 吃饭 打游戏

 

 

 

声明

 

@interface HMPerson : NSObject

{

@public

    NSString *_name;

    int _age;

    double _weight;

    int _iq;

}

- (void)paShanWithLocation:(NSString *)location;

- (void)study;

- (void)eatWithFood:(NSString *)foodName;

- (void)playGame;

 

@end

 

 

实现

@implementation MKPerson

 

- (void)paShanWithLocation:(NSString *)location

{

    //1,1次山.爬山的人的体重就减掉0.5Kg

    NSLog(@"我登上了%@!",location);

    //2..

    _weight -= 0.5;

    //3. 显示

    NSLog(@"我的体重是%.2lf",_weight);

    

    

}

- (void)study

{

    //每学习1,智商+1;

    NSLog(@"头悬梁,锥刺股");

    //智商++;

    _iq++;

    //显示.

    NSLog(@"学习完了以后我的智商是:%d",_iq);

    

}

- (void)eatWithFood:(NSString *)foodName

{

    //1.先吃.

    NSLog(@"主人.你给我的%@真好吃!",foodName);

    //2.长体重.

    _weight++;

    //3.显示.

    NSLog(@"吃完以后,我的体重是:%.2lf",_weight);

}

- (void)playGame

{

    NSLog(@"魔兽毁一生,Doat穷三代!");

    //智商--

    _iq--;

    NSLog(@"我的智商是:%d",_iq);

}

 

#pragma mark - Day02_10_类加载(难点、重点)

1 内存中的五大区域.

        : 存储局部变量.

        : 允许程序员手动在堆区申请指定的连续的字节数的空间来使用.

        BSS: 存储未初始化的全局变量、静态变量.

        数据段(常量区):  存储已经初始化的全局变量、静态变量、常量数据.

        代码段:存储程序的代码.

 

2)类加载.

        1. 当我们创建对象的时候,肯定需要访问这个类.因为只有访问了类才知道类中有那些成员.

        2. 如果只是声明类指针的时候,也会访问这个类.以确定这个类型是否存在.

        '当类第一次被访问的时候,会将类存储到代码段之中. 这个过程叫做类加载.

        将类的代码存储在代码之中.

            将类的代码以字符串的形式存储在代码段中.

 

        '只有类第1次被访问的时候,才会有类加载.

            一旦类被加载到代码区.直到程序结束的时候才会被回收.

 

 

 

 

#pragma mark - Day02_11_对象在内存中的存储

 

1. 类的本质是:我们自定义的数据类型.

        MKPerson *p1 = [MKPerson new];

2. MKPerson *p1;  int *p;

        这句话,仅仅是声明了1个指针变量而已.这个指针变量的类型是HMPerson*.

        p11个局部的变量.所以p1指针变量是存储在栈区的.

        p11个指针变量,所以这个变量中只能存储地址.

        本质上来讲.p11个指针变量 不是1个对象.

3.[MKPerson new];

        这句话,才是在真正的创建对象.

        new做的事情.

        a. 在堆内存中申请一块合适大小的空间.

        b. 在申请的这块空间中根据类的模板创建对象.

        类中有哪些属性.就把类的属性依次的挨个的一个不落的声明在这个对象中.

        对象中除了有类中定义的属性之外,还有1个属性叫做isa 这是1个指针.

        这个isa指针指向代码段中的类.

        c. 初始化对象的属性.为对象的属性赋默认值

        -> 如果属性的类型是基本数据类型.就赋值为0

        -> 如果属性的类型是C指针类型.就赋值为NULL

        -> 如果属性的类型是OC指针类型.就赋值为nil

        d. 返回这个对象在堆空间中的地址.

        将这个地址赋值给p1指针.

        p1指针指向了堆空间中的HMPerson对象.

 

 

#pragma mark - Day02_12_对象在内存中的存储的细节

 

1) 注意

        a. 对象中只有类的属性+isa的指针. 没有方法.isa指针指向了代码段中的类.

        b. 如何访问对象的属性.

        通过指针就可以找到指针指向的对象.找到对象了,就可以找到对象的属性.

        p1->_name = @"jack";

        c. 如何调用对象的方法?[p1 sayHi];

        通过p1指针找到对象,发现是在调用方法.那么再根据对象的isa指针找到代码段中的类,再找到类中的对应的方法来执行.

        d. 为什么方法不保存在对象中.

        因为不管对象有多少个.方法的代码都是一样的.没有必要保存多份,只保存1份就可以了

        e. 相同类的对象的isa指针的值一定都是一样的.

 

 

2) 对象的属性的初始值.

    我们创建1个对象 如果没有为这个对象的属性赋值.那么这个对象的属性是有值的.

    属性的类型是基本数据类型0

    OC指针:      nil

    C指针:       NULL

 

 

 

 

 

#pragma mark - Day02_13_nil

 

1) C语言中学习的NULL.

        a). NULL1个值. C语言中指针变量的值.

        b). 如果1个指针的值为NULL,就代表这个指针不指向内存中的任何空间.

        c). NULL本质上是1个宏.

        define NULL ((void*)0)

        所以 NULL 0 等价.

 

2) nil

        a). nil也是1个值. 它也是1个指针变量的值.

        b). nil的本质也是1个宏.

        #define __DARWIN_NULL ((void *)0)

        所以,nilNULL完全是等价的.

        c). 所以,如果你想要让1个指针不指向任何空间.

        可以为这个指针变量赋值为NULL nil 0

 

3) 使用建议

        a). 如果希望C指针不指向任何空间.我们一般为其赋值为NULL

        b). 如果希望OC指针不指向任何空间,我们一般赋值nil

 

4) 注意问题

        如果1个类指针的值为nil

        HMPerson *p1 = nil;

        代表p1指针不指向任何对象.

        1. 所以这个时候 你通过p1去访问p1指向的对象的属性的时候,肯定的会报错.

        2. 这个时候, 通过这个指针去调用方法的时候,

        不会报错.也不会崩溃.只是没有任何反应的.

 

"扩展

 

void * C语言的万能指针

 

 

#pragma mark - Day02_14_多个指针指向同1个对象

 

 

"提问

int a = 10;

int *p1 = &a;

int *p2 = p1;

 

*p2 = 9;

 

a   的值是多少?

*p1 的值是多少?

 

 

 

1) 类型相同的OC类指针变量之间是可以相互赋值的

 

        HMPerson *p1 = [HMPerson new];

        HMperson *p2 = p1;

        这个时候.p1p2指针指向了同1个对象.

        无论通过p1指针去访问对象.还是通过p2指针去访问对象,

        访问的都是同1个对象.

 

 

 

2) 凡是你看到了new 就代表重新创建了1个对象.

 

 

        [类名 new]; 就代表新创建了1个对象. 结果就是新创建的这个对象的地址.

        [类名 new]; 其实啊,这是在调用1个方法.new是方法名称.

        new方法的功能:创建对象.

        new方法的返回值: 创建的对象的地址.

 

    MKPerson *p1 = [MKPerson new];

    p1->_name = @"李凯";

    p1->_age = 17;

 

    MKPerson *p2 = p1;

    p2->_name = @"花花";

    p2 = [MKPerson new];

 

    NSLog(@"p1->_name = %@",p1->_name);

 

    打印的值是花花

 

 

 

 

#pragma mark - Day02_15_分组导航标记

 

1) 存在的问题

1个文件中的代码太多的时候,要找某1段代码.很难找.

 

2) 一种快速的方式查找文件中的代码.

Xcode 提供了导航条可以快速查找.

 

3) 分组导航标记.

1. #pragma mark 标记名.

2. #pragma mark -  就会产生1条分割线.

3. #pragma mark - 标记名就会产生1条分割线.并取1个标记名.

 

"扩展

自定义代码块

 

#pragma mark -  Day02_16_方法与函数

 

1) 之前在C语言中学习的叫做函数.

void test();

 

OC类中定义的叫做方法.

- (void)sayHi;

 

2) 相同点:

1). 都封装1段代码,都表示1个相对独立的功能.

2). 函数/方法 如果不被调用,那么其中的代码是不会被执行.

 

3) 不同点.

 

1. 语法不同.

 

2. 定义的位置不一样.

    a. 函数除了函数的内部和@interface的大括弧中不能定义.其他的地方都是可以定义的.

    b. 而方法的声明只能在@interface的大括弧的外面,实现只能在@implementation.

    就算你把函数写在类中,这个函数也不是属于这个类的.

 

3. 归属感不同.

    a. 函数就像是1个没有家的孩子,1个函数是孤立的.

    b. 方法是属于类的.类就是方法的家.

 

4. 调用形式不同.

    a. 函数直接调用.

    b. 方法必须要通过对象名来调用.

 

 

 

#pragma mark - Day02_17_都是你的错

 

创建类常见错误

 

1). @interface是类的声明. @implementation是类的实现 他们之间不能相互嵌套.

声明和实现是相对独立的 不能嵌套

 

2). 类的声明和实现必须都要有

 

3). 类必须要先声明然后再实现

 

4). @end不能省略

 

5). OC方法不能像函数那样直接调用 而是要创建对象 通过对象来调用

 

6). 成员变量不允许声明的同时初始化

 

7). 类的声明必须要放在使用类的前面.实现可以放在使用类的后面

 

8). 类语法上其实可以只有实现没有声明.

         例如:

            @implementation MKDog : NSObject

            {

            @public

                NSString *_name;

                int _age;

            }

            - (void)shout

            {

                NSLog(@"汪汪.....");

            }

            @end

虽然这样写是可以的,但是千万别这么写.很不规范.

 

9). 方法只有声明 没有实现

unrecognized selector sent to instance 0x100105a80

只要你看到了这个错误,就代表你调用的方法这个对象中没有 或者 没有实现.

 

实例--对象.

 

#pragma mark -  Day02_18_多文件开发

 

1 需求,为什么要多文件开发?

 

如果将所有的类都写在main.m文件中,

那么类就会越来越多.canshufangfadedhihuyizhidyiduinahanchuanguolaipandaunchuanzhihhiihihchanfangfaebu

缺点

-> 这个文件就会很庞大.

-> 不容易维护.

-> 不利于团队开发.

 

2 我们的一般做法.

 

1. 1个类独占1个模块.

1个模块至少分为两个文件

.h 文件.  h head 头文件. 在这个文件中我们写类的声明.

.m 文件   实现文件. 写上类的实现.

 

2. 什么时候要使用这个类,就只需要引入这个类模块的头文件就可以了.

 

 

3 从现在开始.类不要再写在main.m

而是应该独占1个模块.

.h  类的声明

.m  类的实现. .m中引入.h

 

 

4 NewFile --> cocoaClass --> 自动添加头文件和实现文件.并且还帮你把类的框架搭好.

 

5)  Xcode 可以自动生成前缀模板

 

 

 

 

#pragma mark - Day02_19_对象作为方法的参数()(重点)

 

1)对象与方法.

    对象作为方法的参数.

    对象作为方法的返回值.

 

2 对象可以作为方法的参数.

    因为类是我们自定义的数据类型.

    1. 如何将对象作为方法的参数.

    参数的类型写类的指针类型.

    - (void)liuGouWith:(MKDog *)dog

    2. 在调用这个方法的时候. 实参对象要和形参要求的一致.

    3. 对象传递是 地址 传递.

    传递完成以后,形参指针和实参指针其实指向的是同1个对象.

    在方法的内部.通过形参指针访问对象的时候 其实啊 访问的就是实现指向的那个对象.

 

#pragma mark - Day02_20_对象作为方法的参数()

 

对象作为方法的返回值实际应用

 

1)首先创建一个人的类

 

有两个属性,一个是名字(name),另一个是剩余寿命(leftLife)

 

还有一个死的方法

 

 

再创建一个上帝类,名字(name),年龄(age)

 

有一个杀人的方法 (参数是人类型对象,把人的剩余寿命变为0)

 

 

声明:

 

@interface MKPerson : NSObject

{

@public

    NSString *_name;

    int _leftLife;

}

 

- (void)die;

 

@end

 

实现:

 

@implementation MKPerson

 

- (void)die

{

    NSLog(@"救命啊.我叫%@.",_name);

    NSLog(@"大不了,二十年后又是1条好汉.");

}

@end

 

 

 

上帝声明

 

#import <Foundation/Foundation.h>

#import "MKPerson.h"

@interface MKGod : NSObject

{

@public

    NSString *_name;

    int _age;

}

- (void)killWithPerson:(MKPerson *)per;

@end

 

实现

 

@implementation MKGod

 

- (void)killWithPerson:(MKPerson *)per

{

    NSLog(@"孽畜:%@.我是%@,赶紧过来受死!",per->_name,_name);

    per->_leftLife = 0;

    [per die];

}

 

@end

 

 

 

在这里,通过上帝对象的killWithPerson:方法,我们把person对象传给上帝对象,上帝对象对person对象做处理。这个时候,我们就是把对象当做参数传递。

 

 

 

posted @ 2016-07-26 14:52  MK王月  阅读(163)  评论(0编辑  收藏  举报