FLEXNetworkHistoryTableViewController.m 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //
  2. // FLEXNetworkHistoryTableViewController.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 2/8/15.
  6. // Copyright (c) 2015 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXNetworkHistoryTableViewController.h"
  9. #import "FLEXNetworkTransaction.h"
  10. #import "FLEXNetworkTransactionTableViewCell.h"
  11. #import "FLEXNetworkRecorder.h"
  12. #import "FLEXNetworkTransactionDetailTableViewController.h"
  13. @interface FLEXNetworkHistoryTableViewController () <UISearchDisplayDelegate>
  14. /// Backing model
  15. @property (nonatomic, copy) NSArray *networkTransactions;
  16. @property (nonatomic, copy) NSArray *filteredNetworkTransactions;
  17. @property (nonatomic, strong) UISearchDisplayController *searchController;
  18. @end
  19. @implementation FLEXNetworkHistoryTableViewController
  20. - (instancetype)initWithStyle:(UITableViewStyle)style
  21. {
  22. self = [super initWithStyle:style];
  23. if (self) {
  24. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNewTransactionRecordedNotification:) name:kFLEXNetworkRecorderNewTransactionNotification object:nil];
  25. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil];
  26. self.title = @"📡 Network";
  27. }
  28. return self;
  29. }
  30. - (void)dealloc
  31. {
  32. [[NSNotificationCenter defaultCenter] removeObserver:self];
  33. }
  34. - (void)viewDidLoad
  35. {
  36. [super viewDidLoad];
  37. [self.tableView registerClass:[FLEXNetworkTransactionTableViewCell class] forCellReuseIdentifier:kFLEXNetworkTransactionCellIdentifier];
  38. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  39. self.tableView.rowHeight = [FLEXNetworkTransactionTableViewCell preferredCellHeight];
  40. UISearchBar *searchBar = [[UISearchBar alloc] init];
  41. [searchBar sizeToFit];
  42. self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
  43. self.searchController.delegate = self;
  44. self.searchController.searchResultsDataSource = self;
  45. self.searchController.searchResultsDelegate = self;
  46. [self.searchController.searchResultsTableView registerClass:[FLEXNetworkTransactionTableViewCell class] forCellReuseIdentifier:kFLEXNetworkTransactionCellIdentifier];
  47. self.searchController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  48. self.searchController.searchResultsTableView.rowHeight = [FLEXNetworkTransactionTableViewCell preferredCellHeight];
  49. self.tableView.tableHeaderView = self.searchController.searchBar;
  50. [self updateTransactions];
  51. }
  52. - (void)updateTransactions
  53. {
  54. self.networkTransactions = [[FLEXNetworkRecorder defaultRecorder] networkTransactions];
  55. }
  56. - (void)handleNewTransactionRecordedNotification:(NSNotification *)notification
  57. {
  58. [self updateTransactions];
  59. [self.tableView reloadData];
  60. if (self.searchController.isActive) {
  61. [self updateSearchResultsWithSearchString:self.searchController.searchBar.text];
  62. }
  63. }
  64. - (void)handleTransactionUpdatedNotification:(NSNotification *)notification
  65. {
  66. FLEXNetworkTransaction *transaction = [notification.userInfo objectForKey:kFLEXNetworkRecorderUserInfoTransactionKey];
  67. UITableView *activeTableView = self.searchController.isActive ? self.searchController.searchResultsTableView : self.tableView;
  68. for (FLEXNetworkTransactionTableViewCell *cell in [activeTableView visibleCells]) {
  69. if ([cell.transaction isEqual:transaction]) {
  70. NSIndexPath *indexPath = [activeTableView indexPathForCell:cell];
  71. if (indexPath) {
  72. [activeTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
  73. }
  74. break;
  75. }
  76. }
  77. }
  78. #pragma mark - Table view data source
  79. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  80. {
  81. return 1;
  82. }
  83. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  84. {
  85. NSInteger numberOfRows = 0;
  86. if (tableView == self.tableView) {
  87. numberOfRows = [self.networkTransactions count];
  88. } else if (tableView == self.searchController.searchResultsTableView) {
  89. numberOfRows = [self.filteredNetworkTransactions count];
  90. }
  91. return numberOfRows;
  92. }
  93. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  94. {
  95. FLEXNetworkTransactionTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXNetworkTransactionCellIdentifier forIndexPath:indexPath];
  96. cell.transaction = [self transactionAtIndexPath:indexPath inTableView:tableView];
  97. if (indexPath.row % 2 == 0) {
  98. cell.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
  99. } else {
  100. cell.backgroundColor = [UIColor whiteColor];
  101. }
  102. return cell;
  103. }
  104. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  105. {
  106. FLEXNetworkTransactionDetailTableViewController *detailViewController = [[FLEXNetworkTransactionDetailTableViewController alloc] init];
  107. detailViewController.transaction = [self transactionAtIndexPath:indexPath inTableView:tableView];
  108. [self.navigationController pushViewController:detailViewController animated:YES];
  109. }
  110. - (FLEXNetworkTransaction *)transactionAtIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView
  111. {
  112. FLEXNetworkTransaction *transaction = nil;
  113. if (tableView == self.tableView) {
  114. transaction = [self.networkTransactions objectAtIndex:indexPath.row];
  115. } else if (tableView == self.searchController.searchResultsTableView) {
  116. transaction = [self.filteredNetworkTransactions objectAtIndex:indexPath.row];
  117. }
  118. return transaction;
  119. }
  120. #pragma mark - Search display delegate
  121. - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
  122. {
  123. [self updateSearchResultsWithSearchString:searchString];
  124. // Reload done after the data is filtered asynchronously
  125. return NO;
  126. }
  127. - (void)updateSearchResultsWithSearchString:(NSString *)searchString
  128. {
  129. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  130. NSArray *filteredNetworkTransactions = [self.networkTransactions filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(FLEXNetworkTransaction *transaction, NSDictionary *bindings) {
  131. return [[transaction.request.URL absoluteString] rangeOfString:searchString options:NSCaseInsensitiveSearch].length > 0;
  132. }]];
  133. dispatch_async(dispatch_get_main_queue(), ^{
  134. if ([self.searchDisplayController.searchBar.text isEqual:searchString]) {
  135. self.filteredNetworkTransactions = filteredNetworkTransactions;
  136. [self.searchDisplayController.searchResultsTableView reloadData];
  137. }
  138. });
  139. });
  140. }
  141. @end