---------- CornerFly真诚期待与您交流! ----------
一、点语法
1、基本使用
Person *p = [Person new];
p.age = 10; // [p setAge:10];
2、注意点
1>点语法的本质是get和set方法的调用
2>点语法是编译器特性
3>在set或get方法中调用点语法,会引发死循环
- (void)setAge:(int)age
{
NSLog(@"setAge");
// 会引发死循环
self.age = age; //相当于[self setAge:age];
}
二、成员变量的作用域
* @private:只能在当前类的对象方法中直接访问(@implementation中默认是@private)
*@protected:可以在当前类以及子类的对象方法中直接访问(@interface中默认就是@protected)
*@public:在任何地方都能直接访问对象的成员变量
*@package:只要处在同一个“体系内”(框架)中,就能直接访问对象的成员变量(用的少,一般用系统自带的)
* @interface和@implementation中不能声明同名的成员变量。
三、@property
基本使用:
@interface Person : NSObject
{
// @property: 可以自动生成某个成员变量的setter和getter声明
@property int age;
}
四、@synthesize
基本使用:
@implementation Person
// @synthesize自动生成age的set和get方法的实现,并且会访问_age这个成员变量
@synthesize age = _age;
// 默认会访问height这个成员变量,没有height就会自动生成@private类型的age变量
@synthesize height;
@end
五、id
1、万能指针,是一种类型,能指向/操作任何OC对象
2、定义新对象的时候不需要加*。id p = [Person new];
3、只使用于OC对象
六、构造方法
1、完整地创建一个可用的对象
*分配存储空间 +alloc
*初始化 –init
Person *p = [[Person alloc] init];
2、构造方法是用来初始化对象的方法,是个对象方法,用减号-开头。
3、重写-init方法
1>目的:为了让对象创建出来,成员变量就会有一些固定的值。
2>新生成的对象的成员变量默认情况下都是0,如果想改变一个新对象的默认值,就需要重写init方法。
- (id)init
{
// 1、一定要调用回super的init方法:初始化父类中声明的一些成员和方法。
// 如果对象初始化成功,才有必要进行接下来的初始化
if(self = [super init])
{ // 初始化成功
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
七、分类(category)
1、声明和实现
// 分类的声明
@interface 类名 (分类名称)
// 方法声明
@end
// 分类的实现
@implementation 类名 (分类名称)
// 方法实现
@end
2、作用:不改变原来类内容的基础上,可以给某类扩充一些方法。
3、使用注意
1>分类只能增加方法,不能增加成员变量
2>分类方法实现中可以访问原来类中声明的成员变量
3>分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法失效
4>方法调用的优先级:分类(最后参与编译的分类有效)--->原来类---->父类
4、好处
1> 一个庞大的类可以分模块开发
2>一个庞大的类可以由多个人来编写,更有利于团队合作
八、类的本质
1、类也是个对象
类是Class类型的对象,简称“类对象”。类名就代表着类对象,每个类只有一个类对象
Class c = [p class]; // 创建了一个类对象
[c test]; // 类对象调用类方法
2、类的加载和初始化
1> 当程序启动时,就会自动加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法。只会调用一次
2> 当第一次使用某个类时,就会调用当前类的+initialize方法。
3>先加载父类,再加载子类(先调用父类的+load方法,再调用子类的+load方法)
*先将所有的类加载完毕后,再加载分类
*不管程序运行过程中有没有用到这个类,都会调用+load加载
*先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的+initialize方法)
九、description方法
1、默认情况下,利用NSLog和%@输出对象时,结果是[类名 内存地址]
2、使用NSLog和%@输出某个对象时,会调用对象-description方法,并拿到返回值进行输出。使用NSLog和%@输出某个类对象时,会调用类对象+description方
法,并拿到返回值进行输出。
3、重写description方法
- (NSString *)description
{
// 下面代码会引发死循环
// NSLog(@"%@", self);
return [NSString stringWithFormat:@"age=%d, name=%@", _age, _name];
}
4、代码示例
void test2()
{
Class c = [Person class];
// 1.会调用类的+description方法
// 2.拿到+description方法的返回值(NSString *) 显示到屏幕上
// 3.默认情况下会返回类名:Person
NSLog(@"%@", c);
}
void test1()
{
Person *p = [[Person alloc] init];
p.age = 20;
p.name = @"Jack";
// 1.会调用对象p的-description方法
// 2.拿到-description方法的返回值(NSString *)显示到屏幕上
// 3.-description方法默认返回的是“类名+内存地址”
NSLog(@"%@", p);
Person *p2 = [[Person alloc] init];
// 默认情况下,利用NSLog和%@输出对象时,结果是:<类名:内存地址>
NSLog(@"%@", p2); 打印的是:Person 0x100109e60
NSString *name = @"Rose";
NSLog(@"我的名字是%@", name); 打印:我的名字是Rose
}
5、NSLog补充
NSLog(@”%d”,__LINE__);// 输出当前代码所在的行号
NSLog(@”%s”,__FILE__); // 输出源文件的名称
_cmd :代表着当前方法的SEL
十、SEL
SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法。其实消息就是SEL。
1、SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
2、使用
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (void)test;
- (void)test2;
- (void)test3:(NSString *)abc;
@end
#import <Foundation/Foundation.h>
#import "Person.h"
@implementation Person
+ (void)test
{
NSLog(@"test-----");
}
- (void)test2
{
NSLog(@"test2-----");
}
- (void)test3:(NSString *)abc
{
NSLog(@"test3-----%@", abc);
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main ()
{
Person *p = [[Person alloc] init];
// 间接调用test2 方法
//[p performSelector:@selector(test2)];
//[p test2];
//[p test:@"123"];
[p performSelector:@selector(test3:) withObject:@"123"];
// 1.把test2包装成SEL类型的数据
// 2.根据SEL数据找到对应的方法地址
// 3.根据方法地址调用对应的方法
return 0;
}