Objective-C分析之一
2017-10-12 本文已影响10人
MrSong
Objective-C分析,再深入了解一下,发现还是有很多不懂得地方,有些方法属性从来都没有用过。官方文档确实很详细。
基础
-
Objective-C模块API定义了Objective-C语言的基础。 这些API包括:类型,如NSObject类和NSObject协议,提供大多数Objective-C类的根功能构成Objective-C运行时的函数和数据结构,为Objective-C语言的动态属性提供支持。
-
类 Classes
- NSObject
- Object
- Protocol
-
协议 Protocols
- NSObject
-
相关数据
- Objective-C Runtime
- Objective-C Structures
- Objective-C Enumerations
- Objective-C Constants
- Objective-C Functions
- Objective-C Data Types
NSObject
- 大多数Objective-C类层次结构的根类,子类继承了运行时系统的基本接口以及拥有Objective-C对象的基本能力。
初始化类
-
initialize
- 这个方法在一个类中会调用一次,父类先调用,子类后调用。(Initializes the class before it receives its first message.)
-
load
- 每当将类或类添加到Objective-C运行时时调用;实现此方法在加载时执行类特定的行为。
- 而且是一个类所有方法中第一个调用的方法。只要这个类包含在项目中就会调用这个方法。
- 父类先调用load,子类再调用。父类先调用,分类再调用。
- 注意:桥接到Objective-C的Swift类的加载方法的自定义实现不会自动调用。
create,copy,dealloc对象
- alloc
- Returns a new instance of the receiving class. 返回一个新的类对象
- 分配数据结构以及内存空间
- alloc 方法不可单独用,要配合init方法完成初始化流程。
TheClass *newObject = [[TheClass alloc] init];
- allocWithZone:
- 和alloc 方法功能一样,是因为历史原因而存在。alloc方法会唤醒allocWithZone方法。
- 参数zone可以忽略,因为Objective-C不再使用内存块(memory zones)。
- init
- init 只是在NSObject中进行了声明,并没有实现。
- 由子类实现,在内存被分配之后立即初始化一个新的对象。如果创建失败就返回nil。
- init 不应该单独出现,应该和alloc和allocWithZone一起出现。
- 在子类中重写init时应该调用父类的init 方法。
- (instancetype)init {
self = [super init];
if (self) {
// Initialize self
}
return self;
}
-
copy
- copyWithZone: 的便捷方法
- 拷贝构造函数,至于深拷贝还是浅拷贝由自己实现
- 遵守NSCopying协议的对象通过copyWithZone:方法返回的对象。
- NSObject对象本身不遵守NSCopying协议,必须由子类遵守NSCopying协议并实现copyWithZone:方法才能使用copy方法,否则会有异常。
-
copyWithZone:
-
+ (id)copyWithZone:(struct _NSZone *)zone
参数zone忽略。 - 拷贝构造函数,至于深拷贝还是浅拷贝由自己实现。
- 只要遵守NSCopying协议就可以实现这两个 copy方法实现对象拷贝操作。
-
-
mutableCopy
- mutableCopyWithZone: 的便捷方法
- 遵守NSMutableCopying协议的对象通过mutableCopyWithZone:方法返回的对象。
- 要使用这个方法必须由子类遵守NSMutableCopying协议并实现mutableCopyWithZone:方法才能使用mutableCopy方法,否则会有异常。
-
mutableCopyWithZone:
-
+ (id)mutableCopyWithZone:(struct _NSZone *)zone;
参数zone忽略。 - 只要遵守NSMutableCopying协议就可以实现这两个mutableCopy方法实现对象拷贝操作。
-
-
dealloc
- 类似C++析构函数,释放内存空间
- 可以重新这个方法释放自己定义的对象等。不需要调用
[super dealloc]
,而且不能直接调用这个方法,它会自动由运行时调用。 - 不用ARC是要自己控制对象的引用计数,在dealloc中进行release
-
new
- 便捷方法,相当于调用
[[Class alloc] init]
- 便捷方法,相当于调用
方法
-
+ class
- 返回类自身
-
+ (Class)superclass;
- 返回父类对象
-
+ (BOOL)isSubclassOfClass:(Class)aClass;
- 是否是某个类的子类
-
+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
- 判断类是否支持相应某个方法,和
- respondsToSelector:
方法一样
- 判断类是否支持相应某个方法,和
-
+ (BOOL)conformsToProtocol:(Protocol *)protocol;
- 判断对象是否遵守指定协议,协议可以继承,那么父类的协议中的方法有没有在子类中实现要自己检查。
-
- (IMP)methodForSelector:(SEL)aSelector;
- 返回方法地址,参数不能为空,必要时使用
respondsToSelector:
方法进行判断。 - 如果调用着是一个类,那么参数必须是类方法,是对象,参数必须是对象方法。
- 返回方法地址,参数不能为空,必要时使用
if ([self respondsToSelector:@selector(test)]) {
IMP imp = [self methodForSelector:@selector(test)];
NSLog(@"对象方法imp:%x",imp);
}
if ([AppDelegate respondsToSelector:@selector(test1)]) {
IMP imp = [AppDelegate methodForSelector:@selector(test1)];
NSLog(@"类方法imp:%x",imp);
}
- (void)test {
NSLog(@"test");
}
+ (void)test1 {
NSLog(@"test1");
}
-
+ (IMP)instanceMethodForSelector:(SEL)aSelector;
- 返回对象方法的地址
if ([AppDelegate instancesRespondToSelector:@selector(test)]) {
IMP imp = [AppDelegate instanceMethodForSelector:@selector(test)];
NSLog(@"对象方法imp:%x",imp);
}
-
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;
- 返回对象方法的方法签名
NSMethodSignature *methodSignature = [AppDelegate instanceMethodSignatureForSelector:@selector(test)];
NSLog(@"参数%zd个,参数总长度:%zd,返回类型:%s,返回长度:%zd",methodSignature.numberOfArguments,methodSignature.frameLength,methodSignature.methodReturnType,methodSignature.methodReturnLength);
// 参数2个,参数总长度:224,返回类型:v,返回长度:0
methodSignature = [AppDelegate instanceMethodSignatureForSelector:@selector(testWith:number:)];
NSLog(@"参数%zd个,参数总长度:%zd,返回类型:%s,返回长度:%zd",methodSignature.numberOfArguments,methodSignature.frameLength,methodSignature.methodReturnType,methodSignature.methodReturnLength);
// 参数4个,参数总长度:224,返回类型:@,返回长度:8
if([methodSignature isOneway]) {
NSLog(@"异步");
}
- (void)test {
NSLog(@"test");
}
- (NSString *)testWith:(NSString *)one number:(NSInteger )num {
NSLog(@"testWith:%@ number:%zd",one,num);
return @"";
}
/* NSMethodSignature.h
Copyright (c) 1994-2016, Apple Inc. All rights reserved.
*/
#import <Foundation/NSObject.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available")
@interface NSMethodSignature : NSObject {
@private
void *_private;
void *_reserved[6];
}
/// 创建对象
+ (nullable NSMethodSignature *)signatureWithObjCTypes:(const char *)types;
/// 参数个数,至少两个,一个self,一个_cmd
@property (readonly) NSUInteger numberOfArguments;
/// 获取参数类型,self -> id ,_cmd -> IMP
- (const char *)getArgumentTypeAtIndex:(NSUInteger)idx NS_RETURNS_INNER_POINTER;
/// 参数总长度,在内存堆栈上的大小,和硬件架构有关
@property (readonly) NSUInteger frameLength;
// 调用着是否是异步的
- (BOOL)isOneway;
/// 返回值类型
@property (readonly) const char *methodReturnType NS_RETURNS_INNER_POINTER;
/// 返回值长度,内存堆栈上的长度
@property (readonly) NSUInteger methodReturnLength;
@end
NS_ASSUME_NONNULL_END
-
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
- 和上面方法类似,还可以生成类方法的方法签名。
- 另外在消息转发中,如果遵守了协议,但是没有直接实现协议方法,可以重写这个方法来返回正确的方法签名
methodSignature = [self methodSignatureForSelector:@selector(testWith:number:)];
NSLog(@"对象方法参数%zd个,参数总长度:%zd,返回类型:%s,返回长度:%zd",methodSignature.numberOfArguments,methodSignature.frameLength,methodSignature.methodReturnType,methodSignature.methodReturnLength);
// 参数2个,参数总长度:224,返回类型:v,返回长度:0
if([methodSignature isOneway]) {
NSLog(@"异步");
}
methodSignature = [AppDelegate methodSignatureForSelector:@selector(test1)];
NSLog(@"类方法参数%zd个,参数总长度:%zd,返回类型:%s,返回长度:%zd",methodSignature.numberOfArguments,methodSignature.frameLength,methodSignature.methodReturnType,methodSignature.methodReturnLength);
// 参数2个,参数总长度:224,返回类型:v,返回长度:0
if([methodSignature isOneway]) {
NSLog(@"异步");
}
- (NSString *)testWith:(NSString *)one number:(NSInteger )num {
NSLog(@"testWith:%@ number:%zd",one,num);
return @"";
}
+ (void)test1 {
NSLog(@"test1");
}
-
+ (NSString *)description;
- 打印对象信息,默认只打印类名,可以重写这个方法打印更加详细的信息。
NSLog(@"self:%@",[self description]); // <AppDelegate: 0x174032480>
-
@property(readonly, retain) id autoContentAccessingProxy;
- 返回遵守NSDiscardableContent协议的对象,
- 具体用法参看 http://southpeak.github.io/2015/02/11/cocoa-foundation-nscache/
/*********** Discardable Content ***********/
@protocol NSDiscardableContent
@required
- (BOOL)beginContentAccess; // count + 1
- (void)endContentAccess; // count - 1
- (void)discardContentIfPossible; // 丢弃内存数据
- (BOOL)isContentDiscarded; // 是否丢弃内存数据
@end
@interface NSObject (NSDiscardableContentProxy)
// 返回遵守NSDiscardableContent协议的代理
@property (readonly, retain) id autoContentAccessingProxy NS_AVAILABLE(10_6, 4_0);
@end
- NSDiscardableContent是一个协议,实现这个协议的目的是为了让我们的对象在不被使用时,可以将其丢弃,以让程序占用更少的内存。
- 使用类似引用计数的方式,对象的count动态+1,-1,当count为0时,对象会被内存回收。
接下来继续往下看