1.oc里把属性称为实例变量
2.类的方法到了实例里面就被称为实例的消息或者实例的方法了
3.OC里面的函数声明示例:
- (void)eat;
这个减号表示对象的方法或者行为,加号则表示是类的方法
4.下面这种写法是用来生成set和get方法的
@property (nonatomic,assign) int age;
@property (nonatomic,assign) char * name;
5.类名定义示例:
@interface Person :NSObject
6..h
文件是类的声明部分,.m
文件是类的实现部分
7.创建对象示例(以person类为例):
Person * person=[[Person alloc] init];
8.OC里面的方法只有两种,一是类方法(前置加号),二是对象方法(前置减号)
9.方法的调用示例(这里假设Person类有一个类方法run,一个对象方法eat)
1.类
[Person run ];
2.对象
[person eat];
//(没有括号)
10.带参函数声明示例:
-(void) setSex:(NSString*)valueSex;
-(void) setNumber:(int)numberValue;
-(void)run():(int) a:(int) b;
11.带参函数调用示例:
[p setSex:@''女'']
12.类外访问公有属性:person->name
13.OC里面的字符串必须以@打头,如:person->name=@"锤子"
14.权限符也是要以@打头
15.OC里面默认访问权限是protected,所以在OC里面的访问权限只有三个:public ,protected,private
16.OC里面修改属性的值时,如果属性是类似NSString这样的对象,那么首先需要判断传入的对象是否为空,然后把原属性的值释放掉:name=nil
。而且也不能进行下面这样的操作:指针A=指针B,这会导致两个指针指向相同的内存,程序会崩溃。还是以修改Person类的name属性来举一下例子:
name=[NSString stringWithString:nameValue];
//这里nameValue是传入的参数
//示例
-(void) setName:(char *)nameValue{
if(nameValue){
if(name!=nameValue){
free(name);
name=NULL;//空间释放和指针置空是两码事
int length=StrLength(nameValue)+1;//+1是因为StrLength计算长度的时候没有把\0给计算进去
name=(char*)malloc(length);
strcpy(name,nameValue)
}
}
}
17.获取name并打印:
NSLog(@"name is %@",[person getname]);
18..h
文件示例:注意@implementation和@end
#import
//定义一个Dog.h类,并且在Dog.h中定义两个方法
@interface Dog :NSObject
-(void) setAge:(int)age;
-(void) run;
@end
19..m
文件示例:注意@implementation和@end
#import
#import "Dog.h"
@implementation
-(void) run{
NSLog(@"I\'m running");
}
-(void) setAge:(int) age{
NSlog(@"My age is %d",age);
}
@end
20.id可以代表任何类型的对象。如:
Person p=[[Person alloc] init];
id tmp=p
然后这样子,tmp就能当作一个Person类了来用了
21.OC里面可以用变量名来代替它的get方法
22.不能用对象当属性,只能用对象指针,比如NSString * name
23.以NSString*为参数的函数声明,实现及调用:
//Dog.h
-(void) setName:(NSString*) nameValue;
//Dog.m
-(void) setName:(NSString*) nameValue{
if(name!=nameValue){
name=nil;
name=nameValue;
NSLog(@"my name is %@",nameValue);
}
}
//main.m,调用:
[dog setName:@"huahua"];
24.OC输出指定格式的字符串:
NSString * str="hhhh";
NSLog(@"this is %@",str);
25.利用@property
关键字,通过系统编译器生成set和get方法:
@property(nonatomic,assign) unsigned short int age;
这里的nonatomic关键字是线程保护的意思(因为可能会有别的线程调用这个set方法,从而发生混乱,所以要进行线程保护),assign关键字是直接赋值的意思,专门针对基本数据类型(其实基本数据类型只能用assign关键字)。set方法名是set加上首字母大写的变量名,get方法同理。这样就不用在.m文件里自己实现了。想要覆盖系统方法的话就自己按以上命名方式声明+实现相应方法即可。
26.@property还有两个关键字:strong和weak,strong是两者相互依赖,你走了我也走了weak是不相互依赖,你走了我照样活。
27.在类外直接访问类的属性用的是->
,而点表达式实际上相当于调用类的set和get方法,具体调用哪个视情况而定:
p.age=45;//调用set
NSLog(@"p age=",p.age);//调用get
如果点表达式做左值,那么是调用set,如果做右值,那么是调用get
28.如果在property的括号里加上readonly关键字,那么表示只生成get方法
29.函数名相同,参数类型不同,不能构成重载,除非给参数加了标签,比如以下第一个函数中a后面的name
-(void) run:(int) a name:(char*) name;
-(void) run:(int) a:(int) b;
30.OC里面函数重载的规则:
1)函数名相同,参数个数不同
2)函数名相同,参数个数相同,但是标签不同
31.static静态代码只会被执行一次,可以用来保证我们的变量或者对象是唯一的
32.@synthesize
用于.m
文件中,用于自动实现getter和setter方法,但是OC会利用@property
自动帮我们实现setter和getter方法,所以这个@synthesize
其实是没必要的。同样没必要的是我们还可以利用@property
自动生成以下划线打头的属性,但是其实用self.变量名
也能访问属性,而且这时候变量名就不用带下划线了
33.self相当于java中的this,但是不能等同,因为self可以修改属性的值,this是不可以的
34.ViewController的根类是UIViewController,但其实后者的根类也还是NSObject类
35.在一个类里面要用到其它类时,最好的方法是在.h文件中使用前置声明,即@class 类名
,然后在.m文件里再用包含:#import "类名.h"
36.dealloc
在OC里面是用来释放内存空间的。当一个对象释放,或者对象的引用计数器的值为0时,会自动调用dealloc方法,回收内存
37.strlen()方法的返回值是long int
38.super:可用于调用父类的方法,如果父类没有,就会向父类的父类继续调用,直到根类
39.void *其实就是int型变量,因为它保存的是地址
40.如果用id类型声明了一个类,然后不管怎么调用,随便用哪个方法,编译阶段都不会报错,因为编译器并不会去检查这个类内部有什么方法或者属性
41.判断t是否是p的子类:
BOOL result=[t isKindOfClass:[p class]];
if(YES==result){
NSLog(@"t 是 p的子类")
}
42.(BOOL)isMemberOfClass:(Class)aClass;
判断是否为该类的对象,比如判断p是否是类Person的对象:result=[p isMemberOfClass:[Person class]];
43.OC里面的异常处理语句和Java里面的类似,只不过在try,catch,finally前面各加一个@
。下面是一个异常处理的示例:
@try{
[t learn];
}
@catch(NSException * exception){
NSLog(@"NSException name is %@",[exception name]);
NSLog(@"NSException reason is %@",[exception reason]);
}
44.OC中协议(protocol)的基本概念:协议的声明类似于Java中一个类的接口,但是和接口的不同之处在于:协议没有父类也不能定义实例变量。协议是一种特殊的程序设计结构,用于声明专门被别的类实现的方法。协议在以下场合中非常有用:(但是别管那么多,考试得时候就选objective-C语言中协议是一组没有实现的方法列表)
1)需要由别的类实现的方法
2)声明未知;类的接口
3)两个类之间的通信
协议的基本特点:
1)协议专门声明被别的任何类实现的方法
2)协议本身不是类,它是定义了一个其它类可以实现的接口
3)类别也可以采用协议
45.alloc负责创建对象,这个过程包括分配足够内存来保存对象,写入isa指针,初始化引用计数,以及重置所有实例变量这四个过程。也就是说alloc方法会返回一个未被初始化的对象,但是变量被置了默认值的对象实例。
46.init负责初始化对象,这意味着此时此对象处于可用状态,即实例对象的实例变量可以被赋予合理有效值。
47.一个方法的实际名称是所有签名关键词的串联,包括冒号字符
48.NSMutableString是可变字符串,NSString则是不可变字符串
50.如果想要在创建对象时就对对象的属性进行初始化,那么我们就需要写一个初始化对象的函数。这些初始化函数的函数名必须以init打头。
//声明示例:
-(id)initWithName:(NSString*) nameValue
age:(int) ageValue
number:(NSString*) numberValue;
//实现示例:
-(id)initWithName:(NSString*) nameValue
age:(int) ageValue
number:(NSString*) numberValue
{
//1.判断参数有效性
if(!nameValue||!numberValue||ageValue<20||ageValue>120){
return nil;
}
//2.初始化父类
self=[super init];
if(!self){
return nil;
}
//3.实例变量初始化
self.name=[[NSString alloc]initWithString:nameValue];
if(!self.name){
self=nil;
return nil;
}
self.number=[[NSString alloc]initWithString:numberValue];
if(!self.number){
self=nil;
return nil;
}
self.age=ageValue;
return self;
}
//调用示例
Teacher * zhangsan=[[Teacher alloc]initWithName:@"haha" age:35 number:@"10012"];
51.变量的作用域:变量(栈空间)的生命周期
52.char *c=(char*)malloc(sizeof(char));
这个语句是在堆上分配了一个字节,需要手动释放
53.查看指针的值:printf(“c is %c\n”,c);
查看该指针指向的地址:printf(“c value is %p\n”,c);
不同的地方在于%后面的字眼
54.在计算机科学中,内存泄漏指由于疏忽或者错误造成程序未能释放已经不再使用的内存。内存泄漏不是内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存前就失去了对该段内存的控制,从而造成内存的浪费。比如下面这段代码:
{char *c=(char*)malloc(sizeof(char));}
在这个大括号结束以后,指针c被释放,那么我们就无法访问到它原本指向的1个字节的空间,也就无法使用了
55.typedef语句:typedef 需要起别名的数据类型 别名
#define语句:#define 别名 数据/语句/..
56.基本数据类型转对象:(示例)
int a=5;
NSNumber * numberA=[[NSNumber alloc]initWithInt:a];
NSLog(@"numberA=%@",numberA);//注意这时候就不能用%d了
//获取对象的值
int c=[number intValue]+120;
57.隐式类型转换:
进行算术运算时,不同类型的数据必须转换成同一类型的数据才能运算,算术转换原则为:
1)整型提升,对于所有比int小的类型,首先会提升为int类型。
2)进行运算时,以表达式中最长类型为主,将其它类型数据均转换成该类型,比如double,float,long这些的
3)隐式转换的顺序是:(概括起来就是字符型->整型->浮点型)
char,short->int->unsigned int->long->unsigned long->float->double->long double
58.通过继承和分类来给已有类添加方法:
比如,现在我们有一个Person类,它有一个run方法。我们可以写一个分类,来给这个Person类添加相关方法,也可以重写Person类的已有方法:
//.h文件
@interface Person (SayEnglish)
-(void ) speakENglish;
-(void) run;
@end
//.m文件
#import "Person+SayEnglish.h"
@implementation Person (SayEnglish)
-(void)speakEnglish{
}
-(void )run{
}
@end
//main.m文件:
#import "Person+SayEnglish.h"
#import "Person+SayEnglish.m"
//然后在这里面就可以通过Person实例调用speakEnglish和重写后的run方法了
59.协议类的声明示例:
//修电脑
#import
//在协议的声明里面可以加@required或者@optional关键字,前者表示必须在遵循协议的类里面去实现它,后者表示可以去做也可以不去做
@protocol repairComputerDelegate
-(void ) repairComputer;
@end
然后在别的类(Student类)里面声明实现该方法:
//.h文件
#import
#import "repairComputerDelegate.h"
@interface Student:NSObject
//此处只能用assign,不能用strong
@property (nonatomic,assign) id delegate;
@end
接着在.m文件里实现该方法
(也就是基于协议向另一个类发出消息)
然后在Teacher类里面说明遵循协议(作为接收信息的一方):
然后再Teacher.m里面实现(设置init方法的目的是与发出消息的一方建起联系)
60.一个简单的条件编译例子:
先判断有没有这个宏定义,如果没有,那就来定义一个,如果这个宏定义已经存在了,那就不再定义,直接跳到#endif处。条件编译可以保证只有一个宏定义。另一个条件编译的关键字是#ifdef,它的意思是如果这个标识存在,那我们做一些事。条件编译的用处就是按需要生成不同版本的程序。
61.include和import都是将.h文件定义的属性等拷贝到.m文件中来,它们的区别如下:
include:
在一个.m文件中写两个一样的include 类名.h时会报错,提示对同一个类有两次重复的实现
import:
在一个.m文件中写两个一样的include 类名.h时不会报错,因为它做了优化,比include多了一次判断,在拷贝之前判断前面有没有同样的类名头文件被载入了,如果有就直接跳过
63.定义一个block示例(block和指针类似):
void (^testBlock)();
64.block封装了一段代码,可以在任何时候执行;block可以作为函数参数或者函数的返回值,而本身又可以带输入参数或返回值;block在多线程,异步任务,集合遍历,集合排序,动画专场用得比较多
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10]; //创建一个可变的数组长度为10