美文网首页
NullSafe代码理解

NullSafe代码理解

作者: 李某lkb | 来源:发表于2018-03-03 10:40 被阅读113次

    相信大家多NullSafe并不陌生,但是为什么就一个文件,还不用导入就能解决NULL导致的崩溃呢.

    首先.不用导入是用到了runtime黑魔法.写的NULL的分类.自动生效.
    具体的就看我给大家的代码解析吧.
    就164行,不多.

    
    //
    //  NullSafe.m
    //
    //  Version 1.2.2
    //
    //  Created by Nick Lockwood on 19/12/2012.
    //  Copyright 2012 Charcoal Design
    //
    //  Distributed under the permissive zlib License
    //  Get the latest version from here:
    //
    //  https://github.com/nicklockwood/NullSafe
    //
    //  This software is provided 'as-is', without any express or implied
    //  warranty.  In no event will the authors be held liable for any damages
    //  arising from the use of this software.
    //
    //  Permission is granted to anyone to use this software for any purpose,
    //  including commercial applications, and to alter it and redistribute it
    //  freely, subject to the following restrictions:
    //
    //  1. The origin of this software must not be misrepresented; you must not
    //  claim that you wrote the original software. If you use this software
    //  in a product, an acknowledgment in the product documentation would be
    //  appreciated but is not required.
    //
    //  2. Altered source versions must be plainly marked as such, and must not be
    //  misrepresented as being the original software.
    //
    //  3. This notice may not be removed or altered from any source distribution.
    //
    
    #import <objc/runtime.h>
    #import <Foundation/Foundation.h>
    
    
    #ifndef NULLSAFE_ENABLED
    
    #define NULLSAFE_ENABLED 1
    
    #endif
    
    
    #ifdef DEBUG
    
    #define NULLSAFE_ENABLED 0
    
    #endif
    //屏蔽编译器警告
    #pragma GCC diagnostic ignored "-Wgnu-conditional-omitted-operand"
    
    //分类
    @implementation NSNull (NullSafe)
    
    //当我们给一个NSNull对象发送消息的话,可能会崩溃(null是有内存的),而发送给nil的话,是不会崩溃的
    //
    //创建一个方法缓存,这个缓存会缓存项目中类的所有类名。
    //遍历缓存,寻找是否已经有可以执行此方法的类。
    //
    //如果有的话,返回这个NSMethodSignature。
    //
    //如果没有的话,返回nil,接下来会走forwardInvocation:方法。
    //
    //[invocation invokeWithTarget:nil];将消息转发给nil。
    
    
    /*
     
     在OC中,系统如果对某个实例发送消息之后,它(及其父类)无法处理(比如,没有这个方法等),系统就会发送methodSignatureForSelector消息,如果这个方法返回非空,那么就去执行返回的方法,如果为nil,则发送forwardInvocation消息。
     
     */
    //如果NULLSAFE_ENABLED 为真,执行下面的代码块.
    #if NULLSAFE_ENABLED
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
    {
        @synchronized([self class])//锁住,防止并发.
        {
            //look up method signature
            NSMethodSignature *signature = [super methodSignatureForSelector:selector];//调用父类方法.
            if (!signature)//如果为空
            {
                //not supported by NSNull, search other classes
                static NSMutableSet *classList = nil;
                static NSMutableDictionary *signatureCache = nil;
                if (signatureCache == nil)
                {
                    classList = [[NSMutableSet alloc] init];
                    signatureCache = [[NSMutableDictionary alloc] init];
                    
                    //get class list
                    int numClasses = objc_getClassList(NULL, 0);//获取所有注册类的数量
                    Class *classes = (Class *)malloc(sizeof(Class) * (unsigned long)numClasses);//根据类的数目调整类的空间
                    numClasses = objc_getClassList(classes, numClasses);//已分配好内存空间的数组 classes 中存放元素
                    
                    //add to list for checking
                    NSMutableSet *excluded = [NSMutableSet set];//选用集合是怕重复.
                    for (int i = 0; i < numClasses; i++)//遍历
                    {
                        //determine if class has a superclass
                        Class someClass = classes[i];//类
                        Class superclass = class_getSuperclass(someClass);//父类
                        while (superclass)//父类不为空的话
                        {
                            if (superclass == [NSObject class])//到了根类
                            {
                                [classList addObject:someClass];
                                break;
                            }
                            [excluded addObject:NSStringFromClass(superclass)];//添加不是根类的类.
                            superclass = class_getSuperclass(superclass);//父类递归
                        }
                    }
    
                    //remove all classes that have subclasses
                    for (Class someClass in excluded)
                    {
                        [classList removeObject:someClass];//移除掉所有有子类的类.
    //这里解释一下,因为子类会继承父类,所以只要子类就好了,避免冗余.
                    }
    
                    //free class list
                    free(classes);//手动释放类空间
                }
                
                //check implementation cache first
                NSString *selectorString = NSStringFromSelector(selector);
                signature = signatureCache[selectorString];
                if (!signature)
                {
                    //find implementation
                    for (Class someClass in classList)
                    {
                        if ([someClass instancesRespondToSelector:selector])//该类的实例是否响应这个方法
                        {
                            signature = [someClass instanceMethodSignatureForSelector:selector];
                            
                        
                            
                            break;
                        }
                    }
                    //再缓存以备下次使用.
                    //cache for next time
                    signatureCache[selectorString] = signature ?: [NSNull null];
                }
                else if ([signature isKindOfClass:[NSNull class]])//属于NULL就改为nil.
                {
                    signature = nil;
                }
            }
            return signature;
        }
    }
    //把目标对象置于nil.
    - (void)forwardInvocation:(NSInvocation *)invocation
    {
        invocation.target = nil;
        [invocation invoke];
    }
    
    #endif
    
    @end
    
    
    

    相关文章

      网友评论

          本文标题:NullSafe代码理解

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