HINSPRefHistoryTableViewController.m 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //
  2. // RMRefHistoryTableViewController.m
  3. // HeapInspectorExample
  4. //
  5. // Created by Christian Menschel on 11.09.14.
  6. // Copyright (c) 2014 tapwork. All rights reserved.
  7. //
  8. #import "HINSPRefHistoryTableViewController.h"
  9. #import "NSObject+HeapInspector.h"
  10. #import "HINSPTableViewCell.h"
  11. #import "HINSPTableViewController.h"
  12. @interface HINSPRefHistoryTableViewController ()
  13. @end
  14. @implementation HINSPRefHistoryTableViewController
  15. #pragma mark - Init
  16. - (instancetype)initWithObject:(id)object
  17. {
  18. self = [super initWithObject:object];
  19. if (self) {
  20. self.title = [NSString stringWithFormat:@"%s: %p",
  21. object_getClassName(self.inspectingObject),
  22. self.inspectingObject];
  23. NSArray *dataSource = [NSObject referenceHistoryForObject:object];
  24. self.dataSource = dataSource;
  25. }
  26. return self;
  27. }
  28. #pragma mark - View Life Cycle
  29. static const CGFloat kHeaderViewHeight = 70;
  30. - (void)viewDidLoad
  31. {
  32. [super viewDidLoad];
  33. UIView *headerView = [[UIView alloc] init];
  34. headerView.frame = CGRectMake(0, 0, self.view.bounds.size.width, kHeaderViewHeight);
  35. headerView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
  36. headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  37. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,8,headerView.bounds.size.width,20.0)];
  38. label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
  39. label.font = [UIFont systemFontOfSize:10];
  40. label.numberOfLines = 1;
  41. label.textAlignment = NSTextAlignmentCenter;
  42. NSInteger retainCount = CFGetRetainCount((__bridge CFTypeRef)self.inspectingObject);
  43. label.text = [NSString stringWithFormat:@"Retain Count: %ld ", (long)retainCount];
  44. [headerView addSubview:label];
  45. UIView *superTableHeaderView = self.tableView.tableHeaderView;
  46. self.tableView.tableHeaderView = nil;
  47. CGRect tableHeaderViewFrame = superTableHeaderView.frame;
  48. tableHeaderViewFrame.origin.y = CGRectGetMaxY(label.frame);
  49. superTableHeaderView.frame = tableHeaderViewFrame;
  50. [headerView addSubview:superTableHeaderView];
  51. self.tableView.tableHeaderView = headerView;
  52. }
  53. #pragma mark - TableView
  54. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  55. {
  56. HINSPTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellIdent
  57. forIndexPath:indexPath];
  58. NSDictionary *item = self.dataSource[indexPath.row];
  59. cell.textLabel.text = [NSString stringWithFormat:@"%ld %@",(long)indexPath.row, item[@"type"]];
  60. NSString *symbol = [NSObject symbolForPointerValue:item[@"last_frame"]];
  61. cell.detailTextLabel.text = symbol;
  62. NSArray *backtrace = item[@"all_frames"];
  63. if ([backtrace count] > 0) {
  64. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  65. cell.userInteractionEnabled = YES;
  66. } else {
  67. cell.accessoryType = UITableViewCellAccessoryNone;
  68. cell.userInteractionEnabled = NO;
  69. }
  70. return cell;
  71. }
  72. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  73. {
  74. NSDictionary *item = self.dataSource[indexPath.row];
  75. NSArray *backtraceSymbols = [self symbolsFromPointers:item[@"all_frames"]];
  76. if ([backtraceSymbols count] > 0) {
  77. HINSPTableViewController *detailVC = [[HINSPTableViewController alloc] initWithDataSource:backtraceSymbols];
  78. detailVC.title = [NSString stringWithFormat:@"%@'s backtrace",item[@"type"]];
  79. [self.navigationController pushViewController:detailVC animated:YES];
  80. }
  81. [tableView deselectRowAtIndexPath:indexPath animated:NO];
  82. }
  83. #pragma mark - Search
  84. - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
  85. {
  86. NSMutableArray *dataSource = [self.dataSourceUnfiltered mutableCopy];
  87. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  88. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type contains[cd] %@ OR last_frame contains[cd] %@",
  89. searchText,searchText];
  90. [dataSource filterUsingPredicate:predicate];
  91. dispatch_async(dispatch_get_main_queue(), ^{
  92. self.dataSource = dataSource;
  93. [self.tableView reloadData];
  94. });
  95. });
  96. }
  97. #pragma mark - Helper
  98. - (NSArray *)symbolsFromPointers:(NSArray *)pointers
  99. {
  100. NSMutableArray *symbols = [NSMutableArray array];
  101. for (NSValue *pointerValue in pointers) {
  102. NSString *symbol = [NSObject symbolForPointerValue:pointerValue];
  103. [symbols addObject:symbol];
  104. }
  105. return symbols;
  106. }
  107. @end