id、构造方法、Category 分类、类的本质、description方法、SEL
1.id: 万能指针id :id对象不能用点语法、id对象本身已经有 * 了 因此变量名不能有 * 。
可以吧id理解为 NSObject * 类型数据!
int main()
{
@autoreleasepool {
Person *p = [Person new];
NSObject *o = [Person new];
// 万能指针id
id d = [Person new];
[d setAge:10];
[d setObj:@"123456"];
NSLog(@"%d",[d age]);
}
return 0;
}
2.构造方法:用于调用构造方法的同时初始化部分数据
//Person.m :
#import "Person.h"
@implementation Person
// 重写init方法
- (id)init
{
if(self = [super init])
{
_age = 10;
}
return self;
}
@end
3.自定义构造方法:同时初始化更多数据
//Person.m
- (id)initWithName:(NSString *)name andAge:(int)age
{
if(self = [super init])
{
_name = name;
_age = age;
}
return self;
}
//Student.m
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{
if(self = [super initWithName:name andAge:age])
{
_no = no;
}
return self;
}
4.Category-分类:在不改变原Person类的基础上给Person类扩展一些方法,主要用于给系统类扩展方法。
5.分类的应用:给系统类NSString类扩展一个方法
//NSString+Number.m
#import "NSString+Number.h"
@implementation NSString (Number)
// 分类的作用:可以扩展原类的功能。
+ (int)numberCountOfString:(NSString *)str
{
return str.numberCount;
}
- (int)numberCount
{
int count = 0;
for (int i=0;i<self.length; i++) {
unichar c = [self characterAtIndex:i];
if (c >= '0' && c <= '9') {
count++;
}
}
return count;
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "NSString+Number.h"
int main()
{
@autoreleasepool {
int count = [@"s8dfdfs8df78sdf6s7" numberCount];
NSLog(@"%d",count);
}
return 0;
}
6.类的本质:
1.当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法。只会调用一次。
2.当第一次使用某个类时,就会调用当前类的+initialize方法
3.先加载父类,再加载子类(先调用父类的+load方法,再调用子类的+load方法)
先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的+initialize方法,最后调用的initialize方法的内容会覆盖前面所有initialize方法!)
7.description方法:
NSLog(@"%@",c);语句执行前会:
1.会调用类的+description方法
2.拿到+description方法的返回值(NSString *)显示到屏幕上
// 默认情况下,利用NSLog和%@输出对象时,结果是:<类名:内存地址>
// 1.会调用对象p的-description方法
// 2.拿到-description方法的返回值(NSString *)显示到屏幕上
// 3.-description方法默认返回的是“类名+内存地址”
// 输出行号
NSLog(@"%d",__LINE__);
// NSLog输出C语言字符串的时候,不能有中文
// NSLog(@"%s", __FILE__);
// 输出源文件的名称
printf("%s\n"__FILE__);
test9();
Person *p = [[Person alloc] init];
// 指针变量的地址
NSLog(@"%p",&p);
// 对象的地址
NSLog(@"%p",p);
// <类名:对象地址>
NSLog(@"%@",p);
8.SEL:
SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法
其实消息就是SEL
// 直接调用test2方法
Person *p = [[Person alloc] init];
[p test2];
// 1.间接调用test2方法
NSString *name = @"test2";
SEL s = NSSelectorFromString(name);//将OC字符串转为SEL对象
[p performSelector:s];//通过SEL对象间接调用方法test2
// 2.间接调用test2方法
[p performSelector:@selector(test2)];
[p test3:@"123"];
SEL ss = @selector(test3:);//将方法名test3转为SEL对象
[p performSelector:ss withObject:@"456"];//通过SEL对象间接调用方法test3
[p test2];
// 1.把test2包装成SEL类型的数据
// 2.根据SEL数据找到对应的方法地址
// 3.根据方法地址调用对应的方法