OC基础

2 篇文章 0 订阅
1 篇文章 0 订阅

12.14

1.提纲:

a.面向对象与面向过程

b.类和对象

c.设计类

d.OC简介

e.类和对象的使用

2.面向对象与面向过程

面向对象、面向过程是思考问题的两种不同的方式:

a.面向过程 注重 业务功能

b.面向对象 注重 封装和层次

3.面向对象的三个基本特征:封装、继承、多态

4.类和对象:

类    相当于结构体

对象  相当于结构体中的类型

类是对无数个对象的属性和行为的描述。

开发一个程序,首先得有对象,想要创建对象,那么必须得有类。

5.面向对象开发过程:

a.分析应用需要哪些类

b.设计类

c.创建对象并使用对象

6.一般名词都是类,具有相同(或者类似)属性和行为的对象都可以抽象出一个类。

7.设计类

a.确定类的类名

b.确定类具有的属性

c.确定类的行为(具有的功能)

8.OC中设计类名的规范:类名的第一个字母必须大写、不要有下划线(驼峰标识)。

9.OC的特点:

兼容性:是一种面向对象的C语言,可以有C和C++语句,可以调用C的函数,也可以通过C++对象访问的方法。

类:定义类是基本能力,OC的类声明和实现,包括接口部分和实现部分。定义类要求前缀大写,首字母大写。

方法:定义方法也是它的基本能力,OC中的方法是通过[]运算符进行调用,有时也称作“消息发送”。

属性:是OC2.0提出的概念,代替对成员变量访问的“读取方法(getter)”和“设置方法(setter)”的手段。

协议:OC中来的协议类似于Java中接口或C++的纯虚类,只有接口部分定义没有实现部分。

分类:OC中的分类类似于继承机制,通过分类能够扩展父类的功能。

10. OC的缺点:

a.OC的最初版本并不支持垃圾回收。

b.OC不包括民命名空间机制。

c.OC不支持运算符重载。

d.OC不支持多继承。

故,OC不是一个完全面向对象语言。

11. OC的扩展名:

a.在Mac OS X下使用Xcode进行开发。

b. Xcode通过.m扩展名表示文件使用的时OC代码(可以嵌入C语言)。

c.如果需要嵌入C++的代码,则扩展名应为.mm。

12.OC中使用#import代替#include来包含头文件

#import能够自动防止头文件被重复包含,#include则需要添加那三句条件编译。Foundation.h是Foundation框架的头文件,Foundation框架提供了OC开发中一些列基本的类及函数.

13.NSLOG()是OC中的输出语句,和printf功能类似,NSLOG会自动添加\n。NSLOG()使用日志格式的输出,会有一个较长的前缀。@“”是OC中的字符串表示形式,在OC中,@表示对象,而且很多OC中的关键字都是以@开头。NSLOG()如果想要打印OC对象的值,使用%@。

14.其他的基本说明:

a.布尔类型:布尔类型用于描述“真”、“假”,类型为BOOL,其值可为YES NO。

b.OC对象指针类型:

void * 任意类型的指针。

id OC的对象指针。

instancetype 和id类似,用于构造方法的返回值类型。

c.OC中的“空”:

NULL 对应普通指针变量的地址。

nil  表示OC对象指针的空地址。

Nil  表示OC类对象指针的空地址。

15.接口与实现的分离

OC定义一个类,分为两部分:接口、实现。

接口(公开):声明类中的成员变量、属性、方法。

实现(隐藏):实现类中的方法。

接口与实现分离的好处:

想要使用这个类时只需知道接口部分即可。

同时将实现部分隐藏起来,有利于代码的封装。

[]表示调用方法

头文件中放:类的接口部分。control+command+上/下,在一个类的源文件和头文件之间快速切换。

源文件中放:类的实现部分。成员变量,实现中的成员变量对外隐藏。

接口部分:相当于说明书。

    @public           之后的成员变量,是公有的,任何地方都可以访问

    @protected        之后的成员变量,是受保护的,只能在类及其子类中访问,是默认值

    @private          之后的成员变量,是私有的,只能在类的内部访问

@package          之后的成员变量,在当前框架中能访问

实现部分:不对外公开的成员变量,只能用在当前类的实现的方法中,权限没有意义。

-表示对象方法,通过对象调用的方法叫做对象方法。

通过类名调用的方法叫做类方法。

+表示这是一个类方法。

注意:

先声明接口在编写实现。

成员变量(属性)的声明不能带有初值。

不能为成员变量(属性)随意添加限定(static const)。

OC的对象,必须使用指针存储地址,不能创建局部对象和全局对象。[]运算符的含义是向对象发送一个消息,对象受到消息后会调用对应的方法。new这个消息的含义是创建一个对象(分配空间、成员变量初值为0)。

OC中类其实也是一种对象,所以new这个消息发送给类这种对象的,对应方法我们称之为类方法,和对象方法是不同的。

对象方法:要和函数区分:函数可直接调用,方法需要通过[]发送消息,方法内可以直接使用类(对象)中的成员变量。

一个参数的方法:

接口声明:- (void) makeCallToTel:(NSString*) tel;

方法调用:[p makeCallToTel:@"10086"];

带多个参数的方法:

接口声明:- (void) messageToTel:(NSString*) tel withMessage:(NSString*) message;

//messageToTel: withMessage:

方法调用:    [p messageToTel:@"10086" withMessage:@"10000是什么?"];

16.方法中的self关键字:

方法中可以使用self关键字,是一个指针,指向当前对象。self指针的指向不能变化。

用途:

a.成员变量(属性)与参数名的区分。

b.获得当前对象的地址(如作为返回值)。

c.OC中在定义类的成员变量时习惯以_开头。

17.description方法(重写方法):

用于返回该类型的对象的描述。

a.任何一个类都可以实现这个方法(无需声明)。

b.该方法返回一个OC对象类型NSString。

c.在NSLOG()函数打印时,指定%@,将自动调用该方法并打印返回的字符串。

12.15

1.返回一个按照指定格式拼接的字符串:

NSString *p = [NSString stringWithFormat:@"%@ %@  %f %f %@"orderId,goodsName,closingPrice,freight,consigneeAddress];

2.以下划线开头定义成员变量。

3.NSInteger 是 long

  CGFloat  是  double

4.复合关系:类的复合关系是类的关系中最常见的一种。复合是has a 的关系。OC中要求,所有的对象都以指针的形式引用。可能存在的问题:头文件包含的循环引用。解决问题:在头文件(接口部分)中,声明成员变量的复合关系时,尽量使用@class声明复合的类型,在源文件(实现部分)中,应当包含复合关系的头文件。

5.[new] == [[alloc] + init]

12.16

1.OC中枚举类型的命名规范:前缀是关联的类名,后面是具体的枚举类型名。枚举值的命名规范:前缀是所属的枚举类型名,后面是值的含义。

2.在类的外部想要访问成员变量,则提供方法接口。

getter方法:

作用:返回对象内部的成员变量。

命名规范:方法名与去掉下划线的成员变量名一致。

有返回值,类型与去掉下划线的成员变量名一致,不需要接收任何参数。

setter方法:

作用:提供一个方法给外界设置成员变量值,可以在方法里面对参数进行过滤。

命名规范:以set开头,后面跟成员变量名(首字母大写)。返回值一定是void,接收一个参数且与成员变量类型相同。形参名不要和成员变量一样,如果一个成员变量时只读的挥着不提供直接修改的方法,则不提供setter方法即可。

3.@property声明的被称为“属性”, 属性管理着一个成员变量以及它的getter/setter方法@property关键字声明成员变量,声明与实现getter方法和setter方法。重写setter实现方法,代替默认生成的setter方法。

4.只有成员变量和getter方法和setter方法叫做模型类。

5.@property的点语法:点语法不是取成员,是调用gettersetter方法。点语法的目的:降低对程序员的要求。

6.@property参数有四类,每一类有一个默认值,且只能有一个值,

a.是否提供setter方法

readonly:只生成get方法。

readwrite:生成set方法及get方法(默认)。

b.多线程原子操作

nonatomicsetter方法时不要加上多线程锁的代码(一般都加上)。

atomic: setter方法时加上多线程锁的代码(默认)。

c.指定setter/getter方法(更改setter/getter名字)

getter = 。。。/setter = 。。。

d.内存管理相关的

Aretainstrong(引用计数+1

ARC使用strong,非ARC使用retain

Bassignweak:直接赋值(引用计数不变)

ARC使用assign

ARCOC对象使用weak,非OC对象使用assgin

Ccopy:用于深拷贝(新的),引用计数为1

一般用于NSStringNSArray等。

12.17

1.继承关系:is a

继承:A继承自B,A包含B的所有属性和方法,且A还可以包含一些额外的属性和方法。A被称作子类或派生类,B被称作父类或基类。有利于代码复用。只能继承一个(单继承),也不支持多种继承方式,可以用“协议”来代替实现。

其他说明:

a.OC中不准许子类与父类拥有相同名字的属性。

b.子类调用方法时,是先在当前类中找,找不到再到父类中找。

c.子类可以重写父类的方法,即覆盖了父类的方法,不用声明,只写实现即可。重写要求:方法名、参数、返回值与父类方法一致。有时需先执行父类方法,在执行新的方法,使用supper关键字,super关键字指向该对象的父类部分。

d.父类中的@protected属性在子类方法中可以访问,但private的不能。

NSObject是OC中所有类的父类。

2.多态:使用父类指针存储子类对象的地址。OC中自动实现多态。

3. 多态指针:

a.id是一个任意对象指针类型,NSObject*

注意与void*区分

b.instancetype与id差不多,只用于方法返回值,比id多一个类型检测的功能。

多态指针

4.对象初始化

1.类对象的new方法可以创建一个属性均为0的对象,new方法实际是两个方法的连续调用:

a.分配存储空间alloc类对象方法。

b.初始化init对象方法。

alloc和init方法都是NSObject的方法,故所有的OC类型都可以使用这种方式创建对象。

可以重写init方法,使对象初始化。

重写init方法过程:

a.调用super的init。

b.判断self,然后父类部分初始化。

自定义init方法:规范:返回值类型为instancetype  方法名以initWith开头。需要在接口中声明。

12.18

1.类在源文件中进行接口扩展,与头文件中一样,只是接口扩展不对外公开。

2.定义的类也是一种对象,是Class类的对象。

方法的调用过程:通过基类部分的isa属性,找到成员函数列表,再将消息传递的参数拿过来和函数列表中的参数对比。在自己的函数列表中找不到就到父类的函数列表中去找,直到找到为止。

3.对象方法:通过对象调用的方法,以 - 开头。

类对象方法:通过类对象调用的方法,以 + 开头。

对象方法和类对象方法可以重名。

在类方法中,self表示类对象,,指向对象本身,sper表示父类对象,self指向类对象本身super指向父类对象,类对象的self用来调用其他类方法,类方法在子类中也可以被重写。

4.class方法:变量 == 类

类对象和对象都可以用class返回class类型的类对象。

5.类对象加载:load方法,在程序运行开始时,回家再一次项目中的所有类,类加载完毕就会调用类的load方法,在程序第一次使用这个类时,会调用类的initialize方法,这两个方法是可以重写的,都是类对象方法。

注意:第一次使用该类时,会先调用该类的父类的inintialize方法,当有子类是,类和子类的load方法都会被调用;第一次使用该类时,只会调用子类的initialize方法。

6.实例化一个对象时,类方法也可以封装进行简化。

7.Foundation框架(类库、函数库等等)

a.数值类型,封装成对象。用NSNumber进行封装。就可以在很多只准许使用对象的借口中进行使用。

b.字符串对象NSString

1创建:init方法和类方法

//空串

    NSString * s1 = [[NSString alloc] init];

    NSString * s11= [NSString string];

    //C语言字符串创建OC字符串

    NSString * s2 = [[NSString alloc] initWithUTF8String:"hello world"];

    NSString * s22 = [NSString stringWithUTF8String:"hello world"];

    NSString * s4 = [NSString stringWithCString:"hello" encoding:NSUTF8StringEncoding];

    const char *p = s2.UTF8String;//OC字符串转C字符串

    //按照指定的格式生成字符串

    NSString * s3 = [[NSString alloc] initWithFormat:@"h"];

NSString * s33= [NSString stringWithFormat:@"h"];

2基本操作:

NSLog(@"%ld", s5.length);//返回字符串的长度(按照unicode编码) 

unichar c = [s5 characterAtIndex:1];//返回指定下标的字符

s1 isEqualToString:s2//判断字符串是否相等

3表示数值:

NSString * s3 = @"10";

NSLog(@"%ld", s3.integerValue); //字符串转数值

double a = 123.4;

NSString * s4 = [NSString stringWithFormat:@"%lf", a];//数值转整型数

4文件操作相关:

NSString * path = @"/Users/teacher/Desktop/课堂资源/作业.txt";

NSError * err;

NSString * s5 = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];

if ( err != nil ) 

{

        NSLog(@"%@", err.localizedDescription);

}

[s5 writeToFile:@"/Users/teacher/Desktop/a.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL]; //文件拷贝

5URL操作相关:

NSURL * url = [NSURL URLWithString:@"http://www.baidu.com"];

NSError * err;

NSString * s6 = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&err];

    if ( err != nil ) {

        NSLog(@"%@", err.localizedDescription);

    }

NSLog(@"%@", s6);

6获得子串:

//    NSString * s2 = [s1 substringToIndex:2];

//    NSString * s2 = [s1 substringFromIndex:2];

    NSString * s2 = [s1 substringWithRange:NSMakeRange(22)];

NSLog(@"s2:%@", s2);

 

NSRange r = [s1 rangeOfString:@"ef"];

NSLog(@"loc:%ld len:%ld", r.location, r.length);

 

NSString * s3 = @"a.txt";

if ( [s3 hasSuffix:@"txt"] ) 

{

        NSLog(@"YES");

}

   判断后缀。

NSString * s3 = @"a.txt";

if ( [s3 hasPrefix:@"a.t"] ) 

{

        NSLog(@"YES");

}

判断前缀。

    NSString * s4 = @"ABCDEFH";

NSString * s5 = s4.lowercaseString;

大写转小写。

    NSString * s4 = @"A123BCDEFHijklmn";

NSString * s5 = s4.uppercaseString;

小写转大写。

7构造新串:

    NSString * s6 = @"hello";

NSString * s7 = [s6 stringByAppendingString:@" world"];

追加后新建一个字符串。

8字符串用于表示路径:

9可变字符串对象:NSMutableString用于描述可变字符串,是NSString的子类:    

int a =123;

    NSMutableString * s1 = [NSMutableString stringWithFormat:@"a=%d", a];创建可变字符串。

a追加:

[s1 appendString:@"hello"];改变了原字符串。

b删除:

    [s1 deleteCharactersInRange:NSMakeRange(22)];

c插入/替换:

插入:[s1 insertString:@"  " atIndex:5];//a=123  a=123

替换:[s1 setString:@"hello"];

12.22

1. Foundation框架:

c. NSArray:只能存储OC对象,其他基本数据类型以及结构体都存储不了。

1创建:

 NSArray* arr1 = [NSArray array];//空数组

 NSArray * arr2 = [NSArray arrayWithObject:@(a)]; //单个对象元素数组

NSArray*arr3=[NSArrayarrayWithObjects:@"hello"@YES@(a), p1, @"world", [NSNull null], nil];

//多个对象元素数组

NSArray*arr=@[@"hello",@10,@YES]//常量方式

2数组写入文件中:

BOOL b=[arr4writeToFile:@"/Users/teacher/Desktop/a.txt" atomically:YES]; //将数组内容写入文件NSArray*arr4=[NSArrayarrayWithContentsOfFile:@"/Users/teacher/Desktop/a.txt"];//按照数组形式读取文件中的数据

3基本操作

NSLog(@"%ld", arr4.count); //数组长度

if ( [arr4 containsObject:@YES] ) //数组中是否包含

NSLog(@"firstObject:%@", arr4.firstObject); //数组中第一个元素

NSLog(@"lastObject:%@",arr4.lastObject); //数组中最后一个元素

NSLog(@"%@",arr4 [2]); //数组中第n个元素

NSLog(@"%ld", [arr4 indexOfObject:@YES]); //数组中元素的下标

NSLog(@"%ld", [arr4 indexOfObject:@NO]);//数组中元素的下标,若没有会出现一个随机数

4数组遍历

a//for循环的in语法不适合在循环过程中,改变了数组的情况

for ( id obj in arr4 ) 

{

       NSLog(@"%@", obj);

}

b//for循环的c语言用法

for int i=0; i<arr.count; i++) 

{

        NSLog(@"%@", arr[i]);

 }

5可变数组对象NSMutableArrayNSArray用于描述可变数组对象,是NSArray的子类

a添加:

NSMutableArray * arr1 = [NSMutableArray array];

[arr1 addObject:@"neusoft"];

[arr1 addObject:@YES];

[arr1 insertObject:@10 atIndex:1];

b删除:

[arr1 removeAllObjects];//删除所有

[arr1 removeLastObject];//删除最后一个

[arr1 removeObjectAtIndex:1];//删除指定下标的

12.24

1. Foundation框架:

d.字典对象NSDictionary

NSDictionary用于描述字典对象,数组的下标是整型数,字典的下标是字符串类型的key。字典是一种 key-value 形式的数组。大部分情况下,都使用字符串的对象作为key。字典中的key唯一。    NSDictionary 不可变字典对象

NSMutableDictionary 可变字典对象

和数组对象一样,字典中只能存储OC对象

1创建:

NSDictionary * dict1 = [NSDictionary dictionary];//空字典

NSDictionary * dict2 = [NSDictionary dictionaryWithObject:@30 forKey:@"age"];

//传递一个value的字典

NSDictionary * dict3 = [NSDictionary dictionaryWithObjectsAndKeys:@30@"age"@"neusoft"@"name"nil]; // 传递多个value的字典,以key-value形式传递

NSDictionary * dict4 = [NSDictionary dictionaryWithObjects:@[@30@"neusoft"] forKeys:@[@"age"@"name"]];// 传递多个value的字典,以key和value分别的形式传递

NSDictionary * dict5 = @{@"age":@30@"name":@"neusoft"};// 传递多个value的字典,以基本形式传递

2文件操作:

[dict5 writeToFile:@"/Users/teacher/Desktop/a.txt" atomically:YES]; //将字典中的内容写入文件中。

NSDictionary * dict1 = [NSDictionary dictionaryWithContentsOfFile:@"/Users/teacher/Desktop/a.txt"];//将文件中的字典内容读出。

3长度与遍历:

NSLog(@"%ld", dict1.count); //字典的长度

for ( NSString * key in dict1 ) 

{

        NSLog(@"%@ = %@", key, dict1[key]);

 }//字典的遍历

4字典与数组结合:

    NSArray * a1 = @[

                    @{@"name":@"aaa"@"age":@10},

                    @{@"name":@"bbb"@"age":@20},

                    @{@"name":@"ccc"@"age":@30}

]; //数组嵌套字典

    NSDictionary * d1 = @{

                          @"name":@"aaa",

                          @"age":@10,

                          @"score":@[@80@78@12@67]

                          };//字典嵌套数组

网络中JSON->OC对象  数组与字典嵌套的格式

e.字典对象与模型对象的转换

从本地或者网络获取的数据,往往都是字典类型的。

这些字典数据往往字段固定,且以数组的形式存储。

使用字典可能带来的不利:

1key不方便记忆且编译器不进行正确性的验证。

2不能进行一些对象操作。

解决方法是:将固定字段的字典,封装成自定义对象,这种对象我们称之为“模型”。

字典转模型的步骤

1创建模型类,属性名对应字典中的key字符串中的名字,而属性类型应为字典中对应value的类型。

2添加init及类方法创建模型类。

3在持有模型对象的类中添加属性,往往是数组。

4将字典转成模型对象,属性存储。

f.关于懒加载:

是一种延迟加载方式,在需要的时候才加载。

具体做法:重写属性的getter方法。

模型转字典:使用模型对象的方法。

12.25

1. Foundation框架:

g.KVC   Key Value Coding 键值编码,提供一种机制来间接访问属性。要注意与字典的操作区分 key-Object。

意义:

1提供了对象属性的另一种有效的访问方式。

2为KVO(观察者设计模式)提供了实现基础。

1//setter方法与KVC

p.name = @"neusoft";

[p setValue:@"neusoft" forKey:@"name"];

2//getter方法与KVC

NSLog(@"%@", p.name);

NSLog(@"%@", [p valueForKey:@"name"]);

3//KVC中使用setValuesForKeysWithDictionary:方法对对象的所有属性赋值

[p setValuesForKeysWithDictionary:@{@"name":@"neusoft"@"age":@10}];//字典转模型

NSDictionary * d1 = [p dictionaryWithValuesForKeys:@[@"name"@"age"]];//模型转字典

h.集合类NSSet NSMutableSet

与NSArray的区别:

1集合不能通过下标取成员

2集合类中的对象不能重复

i.NSData 数据对象(缓冲区对象) NSMutableData

NSData一般而言,从网络上获取的数据都是NSData对象。

j.NSFileManager

用于管理文件系统

常见操作:常见、删除一个文件或目录   获得目录中的文件。

类方法defaultManager用于获取对象,不要使用alloc+init new。----单例设计模式。

k. 时间操作对象

1 NSData  用于描述日期时间,提供一些基本的时间获取和比较。

2 NSDateFormatter  用于字符串格式化NSDate。

3 NSCalendar对象  用于将NSData 对象应用在日历上。

4 NSDateComponents对象  用于对象的方式描述NSData对象。

l. 几何数据结构体  可以封装到NSValue对象中,NSValue是NSNumber的父类

1 NSRange  表示范围

2 CGSize 表示二维尺寸

3 CGPoint  表示位置

4 CGRect  表示矩形的尺寸以及位置

12.28

1.不可变数组实现(单向链表)

#import "AMArray.h"

#include <stdlib.h>

@implementation AMArray

{

    void ** _objArray;

}

+ (instancetype) arrayWithObject:(id) obj

{

    return [[self allocinitWithObject:obj];

}

- (instancetype) initWithObject:(id) obj

{

    if ( self = [super init] ) {

        _objArray = (void**)malloc(sizeof(void*)*1);

        *_objArray = (__bridge void *)(obj);

        _count = 1;

    }

    return self;

}

- (instancetype) initWithObjects:(id) firstObj, ...

{

if ( self = [super init] ) 

{

        if ( firstObj ) 

        {

            NSMutableArray * arr = [NSMutableArray arrayWithObject:firstObj];

            va_list params; //变参列表指针

            va_start(params, firstObj);//开始解析变参

while (1

{

                id a = va_arg(params, id);

                if ( a == nil )

               {

                    break;

                }

                [arr addObject:a];

            }

            va_end(params);//解析结束

            //arr中存储所有的变参

            _count = arr.count;

            _objArray = (void**)malloc(sizeof(void*)*_count);

for ( int i=0; i<_count; i++) 

{

     _objArray[i] = (__bridge void *)(arr[i]);

            }

        }

    }

    return self;

}

- (id)objectAtIndex:(NSUInteger)index

{

    if ( index >= _count) {

        return nil;

    }

    return (__bridge id)(_objArray[index]);

}

- (BOOL)containsObject:(id)anObject

{

    for ( int i=0 ;i<_count; i++) {

        if ( anObject == _objArray[i] ) {

            return YES;

        }

    }

    return NO;

}

2.可变数组实现(单向链表)

#import "AMMutableArray.h"

typedef struct arr_node {

    void* data;

    struct arr_node * next;

}sArrNode, *pArrNode;

//sArrNode  ==   struct arr_node

//pArrNode  ==   struct arr_node * == sArrNode *

@implementation AMMutableArray

{

    pArrNode _phead;

    pArrNode _ptail;    //指向最后一个结点

}

+ (instancetype)array

{

    return [[self allocinit];

}

- (instancetype)init

{

if ( self = [super init] ) 

{

        _count = 0;

        //头结点:不存储数据的结点

        _phead = (pArrNode)malloc(sizeof(sArrNode));

        _phead->next = NULL;

        _phead->data = NULL;

        //保证_ptail存储最后一个结点的地址

        _ptail = _phead;

    }

    return self;

}

- (void)addObject:(id)obj

{

    pArrNode pnew = (pArrNode)malloc(sizeof(sArrNode));

    pnew->data = (__bridge void *)(obj);

    pnew->next = NULL;

    _ptail->next = pnew;

    _ptail = pnew;

    _count++;

}

- (void)insertObject:(id)obj atIndex:(NSUInteger)index

{

if ( index > _count ) 

{

        return ;

    }

    pArrNode pnew = (pArrNode)malloc(sizeof(sArrNode));

    pnew->data = (__bridge void *)(obj);

    pnew->next = NULL;

    pArrNode ptrav = _phead;

for ( int i=0; i<index; i++) 

{

        ptrav = ptrav->next;

    }

    pnew->next = ptrav->next;

    ptrav->next = pnew;

if ( ptrav == _ptail ) 

{

        _ptail = pnew;

    }

    _count++;

}

- (NSString *)description

{

    NSMutableString *s = [NSMutableString stringWithFormat:@"(\n"];

    

    for (pArrNode ptrav = _phead->next;

         ptrav != NULL;

         ptrav = ptrav->next

{

        [s appendFormat:@"  %@,\n", (__bridge id)(ptrav->data)];

    }

    [s appendString:@")"];

    return s;

}

- (id) objectAtIndex:(NSUInteger) index

{

    pArrNode ptrav = _phead->next;

for ( int i=0; i<index; i++) 

{

        ptrav = ptrav->next;

    }

    return (__bridge id)(ptrav->data);

}

- (void)removeLastObject

{

    pArrNode ptrav;

for (ptrav = _phead; ; ptrav=ptrav->next)

 {

        if ( ptrav->next == _ptail ) 

       {

            break;

        }

    }

    ptrav->next = NULL;

    free(_ptail);

    _ptail = ptrav;

    _count--;

}

- (void)removeObjectAtIndex:(NSUInteger)index

{

if ( index >= _count )

   {

        return;

    }

    pArrNode ptrav = _phead;

for (int i=0; i<index; i++)

    {

        ptrav=  ptrav->next;

    }

    pArrNode pdel = ptrav->next;

    ptrav->next = pdel->next;

    free(pdel); 

if ( index == _count-1

{

        _ptail = ptrav;

    }

    _count--;

}

- (void)removeAllObjects

{

while ( _count != 0 ) 

{

        [self removeLastObject];

    }

}

12.29

1.单链表:数据域、指针域(下一个结点的地址)。

  头结点:是一个不存储数据的结点,起作用是方便管理链表,当头结点的指针域为NULL,意味着链表为NULL

  双链表:两个指针域(下一个结点的地址、上一个结点的地址)。

  双循环:两个指针域、首尾相连(头结点的上一个结点是尾结点,尾结点的下一个结点是头结点)。

链表优点:长度不固定,且增加、删除数据效率高。

数组优点:长度固定,访问数据效率高。

插入时:先连接被插入结点中的指针,先连接后继指针再连接前驱指针。

pinsert插入到pback的后面

    pinsert->prev = pback;

    pinsert->next = pback->next;

    pback->next->prev = pinsert;

    pback->next = pinsert;

pdel从链表中拿掉

    pdel->prev->next = pdel->next;

    pdel->next->prev = pdel->prev;

    pdel->prev = pdel;

    pdel->next = pdel;

链表的遍历

for(pArrNode ptrav = phead->next;ptrav !=  phead;ptrav = ptrav->next);  //查找

for(pArrNode ptrav = phead;ptrav->next !=  phead;ptrav = ptrav->next);  //插入删除

for(pArrNode ptrav = phead->ptrav;ptrav !=  phead;ptrav = ptrav->ptrav);  //倒叙遍历

12.30

1.存储方式:

 连续存储(数组)

 链式存储(链表)

 离散存储(哈希)

2.hash:

哈希函数:所得结果的个数,一定是有穷的。

哈希表(数组):长度 == 哈希函数所得到结果的个数。

哈希冲突:

3.判断单向链表是否环。

int HASH_FUNC()

{

p1 = phead;

p2 = phead;

while(1)

{

p1 = p1->next;

p2 = p2->next;

if(p2 == NULL)

{

return 0;

}

p2 = p2->next;

if(p2 == NULL)

{

return 0;

}

if(p1 == p2)

{

return 1;

}

}

}

4.有一个单向不循环链表,有一个指针指向一个结点,删除这个结点。

将后面的数据域整体向前移,删除最后一个结点。

5.删除非循环单向链表中倒数第K个结点,要求时间复杂度为0(n)

pArrNode p1 = phead,p2 p1 = phead;

int i = 0;

while(1)

{

i++;

p1 = p1->next;

if(i > k)

{

p2 = p2->next

}

if( p1 == NULL)

{

break;

}

}

5.请用最快的速度找到单向非循环链表中的中间结点。

两个指针一个走两步一个走一步,走两步到尾结点,走一步到中间结点。

6.海量数据问题

1Top K问题:

从海量数据中找出频率最高的K个元素(搜索引擎的统计、微博热点话题、歌曲的排行榜等等)

解决思路:hash  1000份   1万条

求出每一份中频率最高的K个,1000*K个

2找出或删除重复元素

解决思路:位图法

100亿个整型数

10G   1bit

 

0~4G-1

char arr[512];

3排序

解决思路:位图法

12.31

1.分类:对现有类的扩展,分类只扩展方法,不扩展属性(成员变量),不能改变类的代码。

要使用分类的方法,必须包含分类的头文件。

用途:

1将不同作用的代码分散到不同的文件中,是代码结构更清晰。且多人开发一个类代码时,方便共同开发。

2对现有的类进行扩充。

3也可用于覆盖类中原有的方法,和子类的重写功能类似。

使用@property,仅仅是声明getter方法,没写实现,可以使用点语法使用。

2.SEL:方法的调用实际是发送SEL消息。

SEL是对方法的一种包装,所以说发消息,就是发送SEL数据。

将方法包装成一个SEL类型的数据,去找对应的方法地址,找到方法地址就可以调用方法。

调用方法的过程:

1将test包装成SEL。

2根据SEL数据找到对应方法的地址。

3根据方法地址调用对应的方法。

这个操作是由缓存的,能提高查找效率。实际上SEL是一个结构体指针。

每个方法中都有一个_cmd代表当前方法。

3.block:是一种数据类型,在iOS开发中广泛使用且苹果公司极力推荐使用,其功能很像C语言中的函数指针。^是block得特有标志。block的实现代码包含在{}中。大多数情况下,以内联的形式被定义及使用。block的使用和函数指针的使用类似。block内部可以访问外部的变量。外部的局部变量,block内部不能修改,全局变量可以。如果局部变量使用_block声明,则可以在内部修改。实际上,定义block时会对局部变量进行拷贝(副本)block的重要意义:在处理异步任务时非常方便。

4.新语法:

1nullability特性:nullable和nonnull

2轻量级泛型

3kindof

1.04

1.协议:可以用来声明一大堆方法(不能声明成员变量),只要某个类遵循了这个协议,就相当于拥有了这个协议中的所有方法声明,只要父类遵循了某个协议,就相当于子类也遵循。NSObject协议是基协议,Objective-C要求所有的协议1必须遵循基协议,一个类可以遵循多个协议。协议中的两个关键字:@required其后的方法必须实现,@optional其后的方法可选是否实现。协议本身似于C++中的抽象类,遵循协议,实现了部分多继承的功能,为代理设计模式,提供了基础。

2.NSCopying协议:一个对象调用copy,实际上是调用了copyWithZone:,该类型应当遵循<NSCopying>并实现copyWithZone:方法,一个对象调用mutablecopy,实际上是调用了mutablecopyWithZone:,该类型应当遵循<NSMutableCopying>并实现mutablecopyWithZone:方法。

3.深复制和浅复制

a.深复制:内容的拷贝,源对象和副本对象指向不同的对象,源对象的引用计数不变,副本的引用计数为1。

b.浅复制:指针的拷贝,源对象和副本对象指向同一个对象,对象的引用计数+1,相当于做了一次retain。(内存管理)

4. NSCoding协议(归档存储):Foundation框架中的基本数据类型,如:NSString NSNumber NSArray NSDictionary ...,可以进行归档存储,如果是一个自定义类型的对象,该类型需要遵循NSCoding协议。在归档时,会调用encodeWithCoder:方法,在解档时,会调用initWithCoder:方法。如果一个类型的对象,需要进行归档存储,该类型遵循协议<NSCoding> 并实现两个方法。NSCoder是编码器对象。

1.5

1.内存管理:

a.管理范畴:OC对象。

b.管理方式:手动、半自动、自动

在需要时分配,用完之后释放,不要使用任何已释放的内存资源,否则会发生错误。

c.引用计数与内存管理准则:

1retain方法  retainCount+1

2release方法 retainCount-1

3retainCount为引用计数,当值为0时,自动释放

4准则:有始有终,有加有减

a 只要还有人在使用某个对象,那么这个对象就不会被回收,只要你想使用这个对象,那么就应该让这个对象的引用计数器+1,当你不想使用这个对象时,应该让对象的引用计数器-1.

b谁创建,谁release:

如果你通过alloc,new,copy来创建一个对象,那么你就必须调用release或autorelease方法,不是你创建的,就不用你去负责。

c谁retain,谁release。

d.使用引用计数:

1当创建一个对象时,该创建对象的引用计数为1。

2当某段代码要访问这个对象时就对该引用计数+1。(retain)

3当这段代码完成后要对这个引用计数-1。(release)

4当引用计数为0时,表示没有代码访问这个对象了,该对象就会被销毁。(销毁前自动向其发送一个dealloc消息)

e.MRC中的代码规范:

1只要调用alloc,就必须有release。

2属性的setter方法:

a基本数据类型直接赋值

bOC对象,先判断和属性旧值的是不是同一对象,如果是,则什么也不做;如果不是,将旧值release,并对新值retain。

属性如果是字符串对象(copy)---属性的深拷贝

3dealloc方法:

a对self所持有的属性release一次

b[super dealloc]放在最后

- (void)dealloc

{

    [_car release];

    [super dealloc];

}

 

4不要出现垃圾代码。(无法释放的代码)

f.三个参数:

assgin关键字 生成的setter方法,直接赋值。

- (void)setAge:(NSInteger)age

{

    _age = age;

}

retain关键字 生成的setter方法,进行引用计数操作。

- (void)setCar:(AMCar *)car

{

    if ( _car != car ) {

        [_car release];

        _car = car;

        [_car retain];

    }

}

copy关键字   一般用于字符串,生成setter方法,新建一个对象(深复制)。

- (void)setName:(NSString *)name

{

    if ( _name != name ) {

        [_name release];

        _name = [name copy];

    }

}

1.6

1.半自动释放池:

autorelease方法:此方法将对象放到自动释放池中,自动释放池被销毁,同时自动释放池中的所有对象release一次,该方法不改变引用计数。

@autoreleasepool{}声明了一个自动释池的管理范围,其后de{…}相当于自动释放池的生存期。

将autorelease方法封装到类方法中是一个比较好的做法。

2.ARC机制和判断准则:

a.ARC禁用的方法:retainCount  retain release autorelease

b.在重写dealloc时,不必添加[super dealloc]

c.ARC下对象销毁的判断准则:

1当没有强指针指向这个对象时,对象销毁

2OC中,指针默认就是强指针

3涉及的关键字: __strong  __weak

3.ARC下的内存管理参数:

assign  -->  非OC对象。

strong  -->  OC对象,管理的成员变量是强指针,相当于retain。

weak    -->  OC对象,管理的成员变量是弱指针。

copy    -->  NSString对象。


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值