| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- //
- // RMHeapStackDetailTableViewController.m
- // HeapInspectorExample
- //
- // Created by Christian Menschel on 29.08.14.
- // Copyright (c) 2014 tapwork. All rights reserved.
- //
- #import "HINSPHeapStackDetailTableViewController.h"
- #import "HINSPResponderChainViewController.h"
- #import "HINSPShowViewController.h"
- #import "HINSPTableViewCell.h"
- #import "HINSPClassDumpTableViewController.h"
- #import "HINSPRefHistoryTableViewController.h"
- #import "NSObject+HeapInspector.h"
- static NSString *const kCellTitleShow = @"Show";
- static NSString *const kCellTitleResponderChain = @"Responder Chain";
- static NSString *const kCellTitleMethods = @"Methods";
- static NSString *const kCellTitleReferenceHistory = @"Reference History";
- static NSString *const kCellTitleIvars = @"iVars";
- static NSString *const kCellTitleProperties = @"Properties";
- static NSString *const kCellTitleRecursiveDesc = @"Recursive Description";
- static const CGFloat kHeaderViewHeight = 100.0f;
- @interface HINSPHeapStackDetailTableViewController ()
- @end
- @implementation HINSPHeapStackDetailTableViewController
- {
- UITextView *_headerTextView;
- UIFont *_boldFont;
- UIFont *_regFont;
- }
- #pragma mark - View Life Cycle
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.title = @"Object Inspector";
- _boldFont = [UIFont boldSystemFontOfSize:12];
- _regFont = [UIFont systemFontOfSize:12];
-
- [self setupHeaderView];
- [self prepareDataSource];
- }
- - (void)setupHeaderView
- {
- CGRect headerViewFrame = CGRectMake(0.0, 0.0,
- self.tableView.bounds.size.width,
- kHeaderViewHeight);
- UIView *headerView = [[UIView alloc] initWithFrame:headerViewFrame];
- headerView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
-
- CGRect titleLabelFrame = CGRectMake(5.0, 5.0,
- headerView.bounds.size.width - 10.0,
- 15.0);
- UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleLabelFrame];
- CGRect textViewFrame = CGRectMake(0.0, CGRectGetMaxY(titleLabel.frame),
- headerView.bounds.size.width,
- headerView.bounds.size.height - CGRectGetMaxY(titleLabel.frame));
- UITextView *textView = [[UITextView alloc] initWithFrame:textViewFrame];
- titleLabel.text = [NSString stringWithFormat:@"%s: %p",
- object_getClassName(self.inspectingObject),
- self.inspectingObject];
- titleLabel.font = [UIFont boldSystemFontOfSize:12];
- titleLabel.backgroundColor = [UIColor clearColor];
- [headerView addSubview:titleLabel];
-
- // Add a switch if the object is of bool type
- if ([self.inspectingObject respondsToSelector:@selector(boolValue)] &&
- [NSStringFromClass([self.inspectingObject class]) isEqualToString:@"__NSCFBoolean"]) {
- UISwitch *boolSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
- CGRect switchFrame = boolSwitch.frame;
- switchFrame.origin.x = headerViewFrame.size.width - switchFrame.size.width - 10.0;
- switchFrame.origin.y = 5.0;
- boolSwitch.frame = switchFrame;
- [boolSwitch addTarget:self action:@selector(boolSwitchToggle:) forControlEvents:UIControlEventValueChanged];
- boolSwitch.on = [self.inspectingObject boolValue];
- [headerView addSubview:boolSwitch];
- }
-
- textView.editable = NO;
- textView.backgroundColor = [UIColor clearColor];
- _headerTextView = textView;
- [headerView addSubview:textView];
-
- textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
-
- self.tableView.tableHeaderView = headerView;
- [self updateHeaderView];
- }
- - (void)updateHeaderView
- {
- if ([self.inspectingObject conformsToProtocol:@protocol(NSObject)] &&
- [self.inspectingObject respondsToSelector:@selector(description)]) {
- NSInteger retainCount = CFGetRetainCount((__bridge CFTypeRef)self.inspectingObject);
- NSString *retainCountString = [NSString stringWithFormat:@"Retain count: %ld\n", (long)retainCount];
- NSString *infoHeaderText = [retainCountString stringByAppendingString:[self.inspectingObject description]];
- _headerTextView.text = infoHeaderText;
- }
- }
- #pragma mark - Actions
- - (void)boolSwitchToggle:(UISwitch *)boolSwitch
- {
- self.inspectingObject = @(boolSwitch.on);
- [self updateHeaderView];
- }
- #pragma mark - DataSource
- - (void)prepareDataSource
- {
- NSMutableArray *dataSource = [@[] mutableCopy];
-
- NSArray *refHistory = [NSObject referenceHistoryForObject:self.inspectingObject];
- if ([refHistory count]) {
- [dataSource addObject:kCellTitleReferenceHistory];
- }
-
- if ([self.inspectingObject isKindOfClass:[UIResponder class]]) {
- [dataSource addObject:kCellTitleResponderChain];
- }
- if ([self.inspectingObject isKindOfClass:[UIView class]] ||
- [self.inspectingObject isKindOfClass:[UIImage class]] ||
- [self.inspectingObject isKindOfClass:[UIViewController class]]) {
- [dataSource addObject:kCellTitleShow];
- if ([self.inspectingObject isKindOfClass:[UIView class]]) {
- [dataSource addObject:kCellTitleRecursiveDesc];
- }
- }
-
- [dataSource addObject:kCellTitleMethods];
- [dataSource addObject:kCellTitleProperties];
- [dataSource addObject:kCellTitleIvars];
-
- self.dataSource = [dataSource copy];
- [self.tableView reloadData];
- }
- #pragma mark - UITableview dataSource & Delegate
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellIdent
- forIndexPath:indexPath];
-
- NSString *item = self.dataSource[indexPath.row];
- cell.textLabel.text = item;
- cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
- if ([item isEqualToString:kCellTitleReferenceHistory]) {
- cell.textLabel.font = _boldFont;
- } else {
- cell.textLabel.font = _regFont;
- }
-
- return cell;
- }
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UIViewController *targetController = nil;
- NSString *item = self.dataSource[indexPath.row];
- if ([item isEqualToString:kCellTitleResponderChain]) {
- targetController = [[HINSPResponderChainViewController alloc] initWithObject:self.inspectingObject];
- } else if ([item isEqualToString:kCellTitleShow]) {
- targetController = [[HINSPShowViewController alloc] initWithObject:self.inspectingObject];
- } else if ([item isEqualToString:kCellTitleMethods]) {
- targetController = [[HINSPClassDumpTableViewController alloc] initWithObject:self.inspectingObject type:RMClassDumpMethods];
- } else if ([item isEqualToString:kCellTitleIvars]) {
- targetController = [[HINSPClassDumpTableViewController alloc] initWithObject:self.inspectingObject type:RMClassDumpIvar];
- } else if ([item isEqualToString:kCellTitleProperties]) {
- targetController = [[HINSPClassDumpTableViewController alloc] initWithObject:self.inspectingObject type:RMClassDumpProperties];
- } else if ([item isEqualToString:kCellTitleRecursiveDesc]) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wundeclared-selector"
- NSString *recursiveDesc = [self.inspectingObject performSelector:@selector(recursiveDescription)];
- targetController = [[HINSPShowViewController alloc] initWithObject:recursiveDesc];
- ((HINSPShowViewController *)targetController).shouldShowEditButton = NO;
- } else if ([item isEqualToString:kCellTitleReferenceHistory]) {
- targetController = [[HINSPRefHistoryTableViewController alloc] initWithObject:self.inspectingObject];
- }
- #pragma clang diagnostic pop
- [tableView deselectRowAtIndexPath:indexPath animated:YES];
- [self.navigationController pushViewController:targetController animated:YES];
- }
- @end
|