美文网首页开发小技巧
Objective-C分析之一

Objective-C分析之一

作者: MrSong | 来源:发表于2017-10-12 09:48 被阅读10次

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>

/***********    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时,对象会被内存回收。

接下来继续往下看

相关文章

网友评论

    本文标题:Objective-C分析之一

    本文链接:https://www.haomeiwen.com/subject/ofdnyxtx.html