LookinMethodTraceRecord.m 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //
  2. // LookinMethodTraceRecord.m
  3. // Lookin
  4. //
  5. // Created by Li Kai on 2019/5/27.
  6. // https://lookin.work
  7. //
  8. #import "LookinMethodTraceRecord.h"
  9. #import "NSArray+Lookin.h"
  10. @implementation LookinMethodTraceRecordStackItem
  11. @end
  12. @implementation LookinMethodTraceRecord
  13. - (void)encodeWithCoder:(NSCoder *)aCoder {
  14. [aCoder encodeObject:self.targetAddress forKey:@"targetAddress"];
  15. [aCoder encodeObject:self.selClassName forKey:@"selClassName"];
  16. [aCoder encodeObject:self.selName forKey:@"selName"];
  17. [aCoder encodeObject:self.args forKey:@"args"];
  18. [aCoder encodeObject:self.callStacks forKey:@"callStacks"];
  19. [aCoder encodeObject:self.date forKey:@"date"];
  20. }
  21. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  22. if (self = [super init]) {
  23. self.targetAddress = [aDecoder decodeObjectForKey:@"targetAddress"];
  24. self.selClassName = [aDecoder decodeObjectForKey:@"selClassName"];
  25. self.selName = [aDecoder decodeObjectForKey:@"selName"];
  26. self.args = [aDecoder decodeObjectForKey:@"args"];
  27. self.callStacks = [aDecoder decodeObjectForKey:@"callStacks"];
  28. self.date = [aDecoder decodeObjectForKey:@"date"];
  29. _combinedTitle = [self _makeCombinedTitle];
  30. }
  31. return self;
  32. }
  33. + (BOOL)supportsSecureCoding {
  34. return YES;
  35. }
  36. - (NSArray<LookinMethodTraceRecordStackItem *> *)briefFormattedCallStacks {
  37. return [self _formattedStacksFromRawStacks:self.callStacks brief:YES];
  38. }
  39. - (NSArray<LookinMethodTraceRecordStackItem *> *)completeFormattedCallStacks {
  40. return [self _formattedStacksFromRawStacks:self.callStacks brief:NO];
  41. }
  42. - (NSString *)_makeCombinedTitle {
  43. NSString *selString;
  44. if (self.args.count) {
  45. NSArray<NSString *> *selParts = [[self.selName componentsSeparatedByString:@":"] lookin_filter:^BOOL(NSString *obj) {
  46. return obj.length > 0;
  47. }];
  48. NSMutableString *mutableSelString = [NSMutableString string];
  49. [selParts enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  50. [mutableSelString appendString:obj];
  51. NSString *arg = [self.args lookin_safeObjectAtIndex:idx];
  52. if (arg) {
  53. [mutableSelString appendFormat:@":%@", arg];
  54. } else {
  55. [mutableSelString appendString:@":?"];
  56. }
  57. if (idx < selParts.count - 1) {
  58. [mutableSelString appendString:@" "];
  59. }
  60. }];
  61. selString = mutableSelString.copy;
  62. } else {
  63. selString = self.selName;
  64. }
  65. NSString *combinedTitle = [NSString stringWithFormat:@"[(%@ *)%@ %@]", self.selClassName, self.targetAddress, selString];
  66. return combinedTitle;
  67. }
  68. - (NSArray<LookinMethodTraceRecordStackItem *> *)_formattedStacksFromRawStacks:(NSArray<NSString *> *)strings brief:(BOOL)brief {
  69. NSMutableArray<LookinMethodTraceRecordStackItem *> *items = [NSMutableArray array];
  70. [items addObject:({
  71. LookinMethodTraceRecordStackItem *item = [LookinMethodTraceRecordStackItem new];
  72. item.idx = 0;
  73. item.detail = [NSString stringWithFormat:@"-[%@ %@]", self.selClassName, self.selName];
  74. item;
  75. })];
  76. [items addObjectsFromArray:[strings lookin_map:^id(NSUInteger idx, NSString *value) {
  77. if (idx <= 2) {
  78. // 过滤掉 Lookin 相关
  79. return nil;
  80. }
  81. LookinMethodTraceRecordStackItem *item = [self _formattedStackItemFromRawString:value];
  82. item.idx = idx - 2;
  83. return item;
  84. }]];
  85. if (!brief) {
  86. return items.copy;
  87. }
  88. NSMutableArray<LookinMethodTraceRecordStackItem *> *briefItems = [NSMutableArray array];
  89. [items enumerateObjectsUsingBlock:^(LookinMethodTraceRecordStackItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  90. if ([obj.category isEqualToString:@"???"]) {
  91. return;
  92. }
  93. if (!obj.isSystemItem) {
  94. [briefItems addObject:obj];
  95. return;
  96. }
  97. if (!briefItems.lastObject.isSystemItem) {
  98. [briefItems addObject:obj];
  99. return;
  100. }
  101. LookinMethodTraceRecordStackItem *nextItem = [items lookin_safeObjectAtIndex:idx + 1];
  102. if (!nextItem || !nextItem.isSystemItem) {
  103. [briefItems addObject:obj];
  104. LookinMethodTraceRecordStackItem *prevItem = [items lookin_safeObjectAtIndex:idx - 1];
  105. LookinMethodTraceRecordStackItem *prevPrevItem = [items lookin_safeObjectAtIndex:idx - 2];
  106. if (prevItem && prevPrevItem && prevItem.isSystemItem && prevPrevItem.isSystemItem) {
  107. obj.isSystemSeriesEnding = YES;
  108. }
  109. }
  110. }];
  111. return briefItems.copy;
  112. }
  113. - (LookinMethodTraceRecordStackItem *)_formattedStackItemFromRawString:(NSString *)string {
  114. LookinMethodTraceRecordStackItem *item = [LookinMethodTraceRecordStackItem new];
  115. item.category = ({
  116. NSArray<NSString *> *strs = [[string componentsSeparatedByString:@" "] lookin_filter:^BOOL(NSString *obj) {
  117. return obj.length > 0;
  118. }];
  119. strs[1];
  120. });
  121. item.detail = ({
  122. NSString *tmpStr = [[string componentsSeparatedByString:@" "].lastObject stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
  123. NSUInteger loc0 = [tmpStr rangeOfString:@" "].location;
  124. NSUInteger loc1 = [tmpStr rangeOfString:@" + "].location;
  125. NSString *str = [tmpStr substringWithRange:NSMakeRange(loc0 + 1, loc1 - loc0)];
  126. str;
  127. });
  128. if ([item.category isEqualToString:@"UIKitCore"] ||
  129. [item.category isEqualToString:@"libdyld.dylib"] ||
  130. [item.category isEqualToString:@"CoreFoundation"]) {
  131. item.isSystemItem = YES;
  132. }
  133. return item;
  134. }
  135. @end