2018年5月25日 ios面试2 组件化 crash

crash

https://github.com/Michaelyb520/michaelyb520.github.io/blob/38105b73bfaec5fb8bcabecaed94851bb6674c27/_posts/2017-05-05-avoidCrash.md

 

baidu

cocoapods 组件化

forwardinvocation jianshu

 

1.

+ (instancetype)gl_dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key) {
            continue;
        }
        if (!obj) {
            obj = [NSNull null];
        }
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    return [self gl_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j];
}

 

小结一下,造成NSInvalidArgumentException异常大概有以下原因:

  • NSDictionary插入nil的对象。NSMutableDictionary也是同样的道理。
  • NSJSONSerialization序列化的时候,传入data为nil。
  • an unrecognized selector 无法识别的方法

NSInvalidArgumentException的崩溃记录有149条(总崩溃记录304条),占49.01%,称霸Crash界,杀手排名第一。

 2.

SIGSEGV 异常

SIGSEGV是当SEGV发生的时候,让代码终止的标识。当去访问没有被开辟的内存或者已经被释放的内存时,就会发生这样的异常。另外,在低内存的时候,也可能会产生这样的异常。

 

Can't add self as subview crash 
SIGSEGV的崩溃记录有57条(总共304条崩溃记录),占18.75%。在Crash界排名第二。
 
3.
越界的崩溃记录有46条(总共崩溃记录是304条),占15.13%,在crash界杀手排名第三。
 
方案二:利用runtime的Swizzle Method特性,可以实现从框架层面杜绝这类的崩溃问题,这样做的好处有两点:

4.

SIGPIPE 异常

先解释一下什么是SIGPIPE异常,通俗一点的描述是这样的:对一个端已经关闭的socket调用两次write,第二次write将会产生SIGPIPE信号,该信号默认结束进程。

那如何解决该问题呢?对SIGPIPE信号可以进行捕获,也可将其忽略,对于iOS系统来说,只需要把下面这段代码放在.pch文件中即可。

// 仅在 IOS 系统上支持 SO_NOSIGPIPE
#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
    // We do not want SIGPIPE if writing to socket.
    const int value = 1;
    setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(int));
#endif

5.

SIGABRT 异常

这是一个让程序终止的标识,会在断言、app内部、操作系统用终止方法抛出。通常发生在异步执行系统方法的时候。如CoreData、NSUserDefaults等,还有一些其他的系统多线程操作。

注意:这并不一定意味着是系统代码存在bug,代码仅仅是成了无效状态,或者异常状态。

 

https://www.jianshu.com/p/c7efbc283480

6.野指针
 
NSZombieEnabled
 
http://devma.cn/blog/2016/11/10/ios-beng-kui-crash-jie-xi/
 
7.forwardInvocation
 
 

在一个函数找不到时,Objective-C提供了三种方式去补救:

1、调用resolveInstanceMethod给个机会让类添加这个实现这个函数

2、调用forwardingTargetForSelector让别的对象去执行这个函数

3、调用methodSignatureForSelector(函数符号制造器)和forwardInvocation(函数执行器)灵活的将目标函数以其他形式执行。

如果都不中,调用doesNotRecognizeSelector抛出异常。

 

https://www.cnblogs.com/biosli/p/NSObject_inherit_2.html

https://github.com/Mrshang110/GLFoundationGuardian
 
https://github.com/huazi1228/AvoidCommonCrashDemo
 
8.优化
 
https://github.com/lianhuaren/iOS-Performance-Optimization
 
9.模块化
//ComponentProtocol.h
@protocol BookDetailComponentProtocol <NSObject>
- (UIViewController *)bookDetailController:(NSString *)bookId;
- (UIImage *)coverImageWithBookId:(NSString *)bookId;
@end
@protocol ReviewComponentProtocol <NSObject>
- (UIViewController *)ReviewController:(NSString *)bookId;
@end

//BookDetailComponent  组件
#import "ProtocolMediator.h"
#import "ComponentProtocol.h"
#import "WRBookDetailViewController.h"
+ (void)initComponent
{
   [[ProtocolMediator sharedInstance] registerProtocol:@protocol(BookDetailComponentProtocol) forClass:[self class];
}
- (UIViewController *)bookDetailController:(NSString *)bookId {
    WRBookDetailViewController *detailVC = [[WRBookDetailViewController alloc] initWithBookId:param[@"bookId"]];
    return detailVC;
}
- (UIImage *)coverImageWithBookId:(NSString *)bookId {
    ….
}

//WRReadingViewController.m  调用者
//ReadingViewController.m
#import "ProtocolMediator.h"
#import "ComponentProtocol.h"
+ (void)gotoDetail:(NSString *)bookId {
    Class cls = [[ProtocolMediator sharedInstance] classForProtocol:BookDetailComponentProtocol];
    id bookDetailComponent = [[cls alloc] init];
    UIViewController *vc = [bookDetailComponent bookDetailController:bookId];
    [[UIApplication sharedApplication].keyWindow.rootViewController.navigationController.navigationController pushViewController:vc animated:YES];
}

 

 
http://wereadteam.github.io/2016/03/19/iOS-Component/
posted @ 2018-05-25 12:31  lianhuaren  阅读(188)  评论(0)    收藏  举报