1. 在成员变量的声明时候,不要加上@public,不然成员变量的值就变得可以在类方法之外也能随便改变。正确的方法是通过set方法(写入)和get方法(读取)来操作成员变量。
set,get格式:
int _sex
- (void)setSex : (int)sex;
- (int)sex;
2.成员变量命名规范:一定要以下划线_ 开头.有利于与局部变量区分来
3.经典错误: unrecognized selector sent to instance 给对象发送了一个无法识别的消息 。 【p run】 要是run没有定义实现 就会出现。
这是OC的弱语法。在编译链接的时候 不会报错误 只会提出警告。但是在程序运行时就会出现。这是因为OC的动态实现,运行时才发消息,检测方法是否有实现。
4.类方法不能访问实例变量(成员变量),对象才可以。 类在内存中是一块空间,只存有方法列表。 对象在内存是另一块空间,存有实例变量和指向类内存空间实例方法列表的isa指针。
4.类方法执行效率比对象方法高,不依赖于对象。当类方法内部不需要使用成员变量的话,就尽量使用类方法。
5.谁调用了当前方法,self就代表谁。
利用self->成员变量名 访问当前对象内部的成员变量
self出现在对象方法中,self就代表当前对象。
self出现在类方法中,self就代表类。
利用self调用类方法[self 方法名] self代表类
2.继承注意事项:
1.父类必须声明在子类前面。
2.不允许子类和父类拥有相同名称的成员变量。
3.调用某个方法时,优先寻找子类是否有满足调用需求的方法,找不到再去父类找,一层层往上找。 成员变量也一样,就近原则。
4.对象调用方法时,会通过自己指向类的isa指针,去类中寻找方法如果找不到就去父类里面找,,子类中有superclass指针指向其父类。
5.A类拥有B类的属性方法的时候,可以继承,但是前提要逻辑对。比如A类为成绩,B类为学生。这是B类就不能去继承A类,因为逻辑不正确。
这时就考虑使用组合。
组合:
在学生类的成员变量里面,实例化一个成绩对象。
@interaface Student : NSObject
{
Scode *scode;
}
继承的组合使用场合简单判断:
XX是XXX 继承 学生是人
XX拥有XXX 组合 学生拥有成绩
super:调用父类的方法。至于是调用类方法还是对象方法 看它所在的环境
1.直接调用父类中的某个方法
2.super处在对象方法中,那么就会调用父类的对象方法。
super处在类方法中,那么就会调用父类的类方法。
使用场合:子类重写父类的方法时想保留父类的一些行为。
多态: 多种形态。
a.没有继承就没有多态
b.代码体现:父类类型的指针指向子类对象
c.好处:如果函数/方法参数中使用的父类类型,可以传入父类,子类的对象
用一个父类指针变量就可以指向多个子类对象
多态的好处:
当一个方法 在猫上面跟狗上面都是一样的,就直接定义一个动物类指针 然后传入猫狗参数来调用
局限性:父类类型的变量不能直接调用子类特有的方法。 必须强制把子类对象转换为父类类型才可以了
NSString:
@interface Person : NSObject{
//char *_name;
NSString *_name;
}
@end
int main()
{
/*
// 最简单的创建字符串的方式
NSString *str = @"itcast";
char *name = "itcast";
NSLog(@"我在%@上课", str);
//NSLog(@"%s", name);
*/
int age = 15;
int no = 5;
NSString *name = @"哈哈jack";
// length方法算的是字数
int size = [name length];
NSLog(@"%d", size);
// 创建OC字符串的另一种方式
NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name];
NSLog(@"---- %ld", [newStr length]);
return 0;
}
类的分文件使用:
定义一个类分两个文件: .h声明文件 .m实现文件
.h:成员变量,方法的声明
.m: 方法的实现
如果想使用某个类,只需要#import类的 .h 文件即可以。
注释标记 加 - 就会多一条横线 用来分组
#pragma mark
C语言中,非零就是“1” 零就是“0” ,与C语言不同,OC中,1就是“1” 也可以是YES 0就是“0”也可以是NO
点语法:本质是把语句转换成 set 和 get 方法
Person *p = [Person new];
p.age = 10;
需要注意的是:这里的点语法不是去访问类的成员变量,而是编译器会自动帮我们把p.age = 10这行代码转换成[p setAge: 10]
同样的:
int a = p.age; 转换为 [p age];
点语法使用注意:
注意不要在set和get方法定义里面使用self.age; 不然会进入死循环。
在声明和定义里面还是要自己写set和get方法。
@private 只能在当前类的对象方法中直接访问 (@implementation默认是private)
@protected 能在当前类和 子类 的对象方法中直接访问 (@interface 默认是protected)
继承是父类的成员变量方法 子类都继承了,但是关键是能不能访问。
id类型: 是一个能指向 任何 oc对象的指针。 id d = [Person new]注意不要加上*
构造方法:这个变量属于谁,你就在谁那里初始化。
分类的作用:在不改变原来类内容的基础上,为原来类增加一些方法。
description方法:
默认情况下,利用NSLog和@%输出对象信息时,结果是:《类名 : 内存地址》
1.会调用对象p的-description方法
2.拿到-description方法的返回值(NSString *)显示到屏幕上
3.-description方法默认返回的是“类名+内存地址”
引用计数器占 四个 字节
当使用alloc new copy创建新对象的时候,新对象的引用计数器默认就是1 当计数器值为0的时候 对象占用的内存才会被回收
retain 引用计数+1 用到的时候就要加1
release 引用计数-1
retainCount 查询引用计数
当对象引用计数器值为0 时 对象会被销毁,其所占用的内存会被系统回收。当对象被销毁时,系统会自动向对象发送一条dealloc消息,我们一般会重写dealloc方法来释放一些资源。
对于dealloc,最后都要加上 [super dealloc]
xcode7 取消arc:
打开你的工程,点击目录的工程文件,最顶端蓝色的,然后双击project下你的工程,还是蓝色那项,然后build Settings,然后往下拉,在Apple LLVM 5.0 - Language - Objective C 里有一个选项,Objective-C Automatic Reference Counting 选择NO,就可以了。
project ->
build Settings ->
Apple LLVM 5.0 - Language - Objective C ->
Objective-C Automatic Reference Counting 选择no
僵尸对象:所占用内存已经被收回的对象,僵尸对象不能再被使用。
野指针:指向僵尸对象(不可用内存)的指针,给它发消息会报错,exc_bad_acess
空指针:没有指向任何东西的执政
当你想用某个对象的时候 你就需要调用该对象的retain方法,使其计数器加1 ,当你不想用的时候你就要release,使其计数器减1,当对象的计数器为0的时候,就会调用dealloc方法,这时如果 对象里面拥有别的对象,就要在这里释放掉 ,在dealloc方法里面,最后要加上[super dealloc],然后记得要把对象指针设为nil p = nil。
原则:
1.谁retain,谁release。
你想使用(占用)某个对象,就应该让对象的计数器+1(调用一次对象的retain方法)
你不想再使用(占用),就应该让对象的计数器-1(调用对象的release方法)
2.谁alloc, 谁release。
内存管理代码规范:
1.只要调用了alloc,必须有release
2.set方法的代码规范
1》基本类型数据类型:直接复制
- (void)setAge:(int)age
{
_age = age;
}
2》oc对象类型
- (void)setCar:(Car *)car
{
//1.先判断是不是新传入的对象
if( car != _car)
{
//2.对旧对象做一次release
[ _car release];
//3.对新对象做一次retain
_car = [car retain];
}
}
3.delloc方法的代码规范
1》一定要[super dealloc] 而且放到最后面
2》对self(当前)所拥有的其他对象做一次release
- (void)dealloc
{
[ _car release];
[ super dealloc];
}
当get方法的返回值为bool类型,就要写成下面的格式( 把方法名修改成is+变量名 首字母大写)
@property (getter = isRich) bool rich
1.set方法内存管理相关的参数
* retain : release旧值,retain新值(适用于OC对象类型)
* assign : 直接赋值(默认,适用于非OC对象类型)
* copy : release旧值,copy新值
2.是否要生成set方法
* readwrite : 同时生成setter和getter的声明、实现(默认)
* readonly : 只会生成getter的声明、实现
3.多线程管理
* nonatomic : 性能高 (一般就用这个)
* atomic : 性能低(默认)
4.setter和getter方法的名称
* setter : 决定了set方法的名称,一定要有个冒号 :
* getter : 决定了get方法的名称(一般用在BOOL类型)
*/
开发中引用一个类的规范
1.在" person.h "文件中 使用@class card 来包含card类
2.然后在 main.m文件中才用#import来包含头文件card.h
两端循环引用解决方案 person card互相引用 则 在@property 参数中
1. 一端使用retain
2.一端使用assign
autorelease 其实就是相当于在最后的时候 对池的对象都做一次 release
内存管理总结:
一、计数器的基本操作
1> retain : +1
2> release :-1
3> retainCount : 获得计数器
二、set方法的内存管理
1> set方法的实现
- (void)setCar:(Car *)car
{
if ( _car != car )
{
[_car release];
_car = [car retain];
}
}
2> dealloc方法的实现(不要直接调用dealloc)
- (void)dealloc
{
[_car release];
[super dealloc];
}
三、@property参数
1> OC对象类型
@property (nonatomic, retain) 类名 *属性名;
@property (nonatomic, retain) Car *car;
@property (nonatomic, retain) id car;
// 被retain过的属性,必须在dealloc方法中release属性
- (void)dealloc
{
[_car release];
[super dealloc];
}
2> 非OC对象类型(int\float\enum\struct)
@property (nonatomic, assign) 类型名称 属性名;
@property (nonatomic, assign) int age;
四、autorelease
1.系统自带的方法中,如果不包含alloc、new、copy,那么这些方法返回的对象都是已经autorelease过的
[NSString stringWithFormat:....];
[NSDate date];
2.开发中经常写一些类方法快速创建一个autorelease的对象
* 创建对象的时候不要直接使用类名,用self
-------------
ARC
ARC的判断准则:只要没有强指针指向对象,就会释放对象
1.ARC特点
1> 不允许调用release、retain、retainCount
2> 允许重写dealloc,但是不允许调用[super dealloc]
3> @property的参数
* strong :成员变量是强指针(适用于OC对象类型)
* weak :成员变量是弱指针(适用于OC对象类型)
* assign : 适用于非OC对象类型
4> 以前的retain改为用strong
指针分2种:
1> 强指针:默认情况下,所有的指针都是强指针 __strong
2> 弱指针:__weak
把没有arc的旧项目转换为新的有arc的项目方法:
点击xcode菜单 edit-》convert-》to object-c ARC
ARC循环引用,一端使用week,一端使用strong。
比如 人拥有一只狗。这时候 人的狗是dog 狗的主人是person
就会循环引用 导致释放不了 这是就需要 person和dog
在pproperty的时候 一方为strong 一方为week。
非ARC就一端用retain 一端用assign
-------------------------------
BLOCK
block要掌握的东西
1> 如何定义block变量
int (^sumBlock)(int, int);
void (^myBlock)();
2> 如何利用block封装代码
^(int a, int b) {
return a - b;
};
^() {
NSLog(@"----------");
};
^ {
NSLog(@"----------");
};
3> block访问外面变量
* block内部可以访问外面的变量
* 默认情况下,block内部不能修改外面的局部变量
* 给局部变量加上__block关键字,这个局部变量就可以在block内部修改
4> 利用typedef定义block类型
typedef int (^MyBlock)(int, int);
// 以后就可以利用MyBlock这种类型来定义block变量
MyBlock block;
MyBlock b1, b2;
b1 = ^(int a, int b) {
return a - b;
};
MyBlock b3 = ^(int a, int b) {
return a - b;
};
--------------
Foundation
/*
集合
1.NSArray\NSMutableArray
* 有序
* 快速创建(不可变):@[obj1, obj2, obj3]
* 快速访问元素:数组名[i]
2.NSSet\NSMutableSet
* 无序
3.NSDictionary\NSMutableDictionary
* 无序
* 快速创建(不可变):@{key1 : value1, key2 : value2}
* 快速访问元素:字典名[key]
*/
#import <Foundation/Foundation.h>
int main()
{
NSArray *persons = @[
@{@"name" : @"jack", @"qq" : @"432423423", @"books": @[@"5分钟突破iOS编程", @"5分钟突破android编程"]},
@{@"name" : @"rose", @"qq" : @"767567"},
@{@"name" : @"jim", @"qq" : @"423423"},
@{@"name" : @"jake", @"qq" : @"123123213"}
];
//
// NSDictionary *jim = persons[2];
//
NSString *bookName = persons[0][@"books"][1];
NSLog(@"%@", bookName);
440106199509220046 19950922