iOS复习笔记15:NSObject

为了描述方便,把如下代码贴出来:

@interface Student:NSObject
-(void)go;
-(void)showName:(NSString *)name;
-(void)introduce:(NSString *)name :(NSString*)address;
@end

Student* stu = [[Student alloc]init];

一 创建和初始化方法

alloc

allocWithZone

new

copy -- 只有不可变到不可变是浅拷贝(相当于retain),其他都是深拷贝,产生不可变的副本(NSString, NSSet等)

mutableCopy -- 深拷贝,产生可变的副本(NSMutablString, NSMutablSet等)

init

重点看copy和mutableCopy

copy:只有不可变到不可变是浅拷贝(相当于retain),其他都是深拷贝,产生不可变的副本(NSString, NSSet等)

mutableCopy:深拷贝,产生可变的副本(NSMutablString, NSMutablSet等)

并不是所有的对象都支持copy,mutableCopy;

遵守NSCopying/NSMutableCopying协议的类可以发送copy/mutableCopy消息。

这两个协议里面分别声明了下面两个方法:

- (id)copyWithZone:(NSZone *)zone;
- (id)mutableCopyWithZone:(NSZone *)zone;

示例:

<pre name="code" class="objc">@interface Student:NSObject <NSCopying>
@end

@interface Student
(id)copyWithZone:(NSZone *)zone
{
	// 创建的副本对象不需要释放,有调用者释放
	// [self class]防止继承之后,返回父类对象
	Student* copy = [[[self class] allocWithZone:zone] init];

	return copy;
}
@end

二 内存管理方法retain 增加对象的计数器retainCount 返回一个对象当前的计数器release 减少对象的计数器autorelease 自动减少对象的计数器,但是以推迟的方式来实现。dealloc 应用于类来释放对象实例变量并释放动态内存三 判断方法isKindOfClass:判断对象是否是某个类或子类的对象isMemberOfClass:判断对象是否是某个类的对象comfirmsToProtocal:判断对象是否实现了某个协议instancesRespondToSelector:判断对象是否实现了某个方法respondsToSelector:判断类是否实现了某个方法四
间接调用performSelector:performSelector:withObjct:performSelector:withObjct:withObjct:performSelector:withObjct:afterDelay:

// 相当于[stu go];
[stu performSelector:@selector(go)];
// 相当于[stu showName:@"Jun"];
[stu performSelector:@selector(showName:) withObjct:@"Jun"];
相当于[stu introduce:@"Jun":@"address"];
[stu performSelector:@selector(introduce::) withObjct:@"Jun" withObjct:@"address"];
// 延时2秒之后调用
[stu performSelector:@selector(showName:) withObjct:@"Jun" afterDelay:2];

五 描述

NSObject有一个description方法

+ (NSString *)description;

当我们调用NSLog(@"%@", instance);时,就会调用description方法。

自定义类时,可以重写这个方法。

六 反射

根据字符串反射成类和方法

1 Class反射

// 字符串类名到类
NSString* className = @"Student";
Class class = NSClassFromString(className);
Person* p = [[class alloc] init];
// 类到字符串类名
NSString* strClass = NSStringFromClass([Person class]);

2 方法反射

// 字符串方法名到方法
NSString* funName = @"go";
SEL selector = NSSelectorFromString(funName);
[stu performSelector:selector];
// 方法到字符串方法名
NSString* strFun = NSStringFromSelector(selector);

七 NSObject本质

@interface NSObject <NSObject> {
        Class isa;
}

可以看到NSObject对象只有一个成员变量Class isa;

Class又是什么呢?

typedef struct objc_class *Class;

它结构体objc_class指针的别名。

objc_class的定义如下:

struct objc_class {
    Class isa;
};

跟NSObject定义类似,此外还有id也是这样的。

typedef struct objc_object {

Class isa;

} *id;

所以id就是结构体objc_object指针。

从上面可以看出,NSObject,objc_class,objc_object都仅有一个objc_class * 类型,也就是Class类型的变量isa

以得出结论,类是用objc_class结构体表示的,对象是用objc_object结构体表示的,对象的isa用来标示这个对象是哪个类的实例。

看下面的源代码:

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

- (Class)class {
    return object_getClass(self);
}

Class object_getClass(id obj)
{
    return _object_getClass(obj);
}

static inline Class _object_getClass(id obj)
{
    if (obj) return obj->isa;
    else return Nil;
}

如果obj不空,返回的Class类型就是obj->isa,否则,返回的是Nil。

这就从源码上证实了isa就是代表一个对象的类型。

时间: 2024-11-02 23:36:22

iOS复习笔记15:NSObject的相关文章

iOS复习笔记1:HelloWorld项目

2012年10月到2013年5月期间,一直都做iOS开发,后来开始做用cocos做游戏开发. 过去了那么久,复习一下以前学的东西. 一 新建工程 打开Xcode,选择File>Project>Single View Application,然后输入工程名HelloWolrd,选择保存路径. 创建完成之后保存,如图: 二 运行 单击上图左上角的三角形按钮,程序久可是运行了,以下界面一闪而过: 然后出现: 这就是用模拟器运行程序啦:如果闲模拟器太大,看不清楚,可以点击模拟器,然后Window>

iOS复习笔记3:类的基本定义

// Car.h // 类的声明 // 类名:Car // 属性:m_nSpeed // 行为:run #import <Foundation/Foundation.h> // NSObject @interface Car : NSObject { // 属性:成员变量(可以是基础类型,枚举,结构体和类对象指针) @public int m_nSpeed;// 默认初始化为0 } // 行为:方法(方法名,返回值,参数) - (void)stop; - (void)run:(int)spee

iOS复习笔记11:协议和代理

一 功能 可以在协议中声明方法(不能声明变量), 某个类只要遵守这个协议,就相当于拥有协议中所有的方法声明. 父类准守协议,子类也拥有协议中的方法. 协议也可以准守另一个协议. 基协议NSObject(同时也是基类),NSObject基类也准守基协议. 基协议中包含了常用的内存管理方法:release,retain方法等. 二 定义 1 协议定义 @protocal 协议名 <NSObject> // 声明方法 @end 2 遵守协议 2.1 类 @interface 类名 : 父类名 <

iOS学习笔记 15:separatorInset设置UITableView的分割线无效的问题

一.问题描述 UITableView分割线要显示到最左端 查看UITableView的属性,发现设置separatorInset的值可以自定义分割线的位置. @property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; // allows customization of the frame of cell separators 打印separatorInset,其默

iOS开发笔记15:地图坐标转换那些事、block引用循环、UICollectionviewLayout及瀑布流、图层混合

1.地图坐标转换那些事 (1)投影坐标系与地理坐标系 地理坐标系使用三维球面来定义地球上的位置,单位即经纬度.但经纬度无法精确测量距离戒面积,也难以在平面地图戒计算机屏幕上显示数据.通过投影的方式可以将其转换成平面的投影坐标系,不同的投影方式可能会带来不同的变形及误差,类似于把一个橘子的橘子皮剥开摊平到桌面. GPS以及iOS系统定位获得的坐标是地理坐标系WGS1984,Web地图一般用的坐标细是投影坐标系WGS 1984 Web Mercator,国内出于相关法律法规要求,对国内所有GPS设备

iOS复习笔记8:autorelease详解

一 概念 iOS在程序在运行的过程中,会创建很多个释放池,自动释放池以栈的形式存放的(先进后出). 对象调用autorelease时,会被放入栈顶的自动释放池中. 当自动释放池销毁时,会对池的所有对象发送一次release消息: 所以发送autorelease之后引用计数不会立即-1. autorelease返回对象本身. 二 实例 // Person.h @interface Person @property(nonatomic, assign) int age; @end // Person

iOS复习笔记12:分类

1 功能描述 1.1 向已经存在的类中添加方法,不能添加成员变量. 1.2 将类的实现放到不同的文件中 1.3 创建对私有方法的引用 2 格式 头文件(文件名:"类名+类别名.h") #import "类名.h" @interface 类名(类别名) //新方法的声明 @end 源文件(文件名:"类名+类别名.m") #import "类名+类别名.h" @interface 类名(类别名) //新的实现方法 @end 3 示

IOS学习笔记 ---- 15/08/31

1.pch文件中的代码是全局的,不管是#import头文件还是#define宏,都可以在项目中的所有文件中使用.(凡是涉及到OC语法的内容都要放入到#ifdef __OBJC__  #endif中).2.pch中最好使用下面的宏对NSLog函数进行替换,在发布的时候直接将后部的NSLog进行注释则代码中不会打印任何值. #define MyLog(...) NSLog(__VA_ARGS__) 3.IOS在未打包状态的时候会默认有一个DEBUG宏,在打包后则会自动删除,可以利用判断来优化上方代码

iOS复习笔记4:内存管理

一 基础原理 1 为什么需要内存管理 因为移动设备内存有限,每个app所占用的空间有限. 当app占用内存空间过多时,系统会发出内存警告,这是回收一些不在使用的内存. 例如:不再使用的类对象和实例. 2 管理对象 任何继承自NSObject类的对象 3 内存区域 堆:主动分配空间,需要管理 栈:局部变量,自动管理 例如: int a = 1; Person* p = [[Person alloc] init]; a,p都放在栈区 Person分配的空间在堆区 二 引用计数 1 定义 每个OC对象