TracesViewController.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // Copyright 2020 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Non-google3 relative import to support building with Xcode.
  15. #import "TracesViewController.h"
  16. #import "../Models/AccessibilityItem.h"
  17. #import "../Models/PerfLogger.h"
  18. #import "../Views/PerfTraceView+Accessibility.h"
  19. #import "../Views/PerfTraceView.h"
  20. #import "TracesViewController+Accessibility.h"
  21. #import "FirebasePerformance/Sources/Public/FIRPerformance.h"
  22. /** Edge insets used by internal subviews. */
  23. static const CGFloat kEdgeInsetsTop = 10.0f;
  24. static const CGFloat kEdgeInsetsBottom = 10.0f;
  25. static const CGFloat kEdgeInsetsLeft = 20.0f;
  26. static const CGFloat kEdgeInsetsRight = 20.0f;
  27. @interface TracesViewController () <PerfTraceViewDelegate>
  28. /** The scroll view where all the PerfTraceViews are added. */
  29. @property(nonatomic) UIScrollView *contentView;
  30. /** Button to add a new PerfTraceView. */
  31. @property(nonatomic) UIButton *addTraceButton;
  32. /** A counter to maintain the number of traces created. Used for the unique names for traces. */
  33. @property(nonatomic, assign) NSInteger traceCounter;
  34. /** The most recently created PerfTraceView. */
  35. @property(nonatomic) PerfTraceView *recentTraceView;
  36. /**
  37. * The bottom constraint which manages the content size of the content view (UIScrollView). This is
  38. * usually the constraint of the most recently added PerfTraceView's bottom to be equal to the
  39. * bottom of the content view.
  40. */
  41. @property(nonatomic) NSLayoutConstraint *bottomConstraint;
  42. @end
  43. @implementation TracesViewController
  44. #pragma mark - View life cycle
  45. - (void)loadView {
  46. UIView *perfView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  47. perfView.backgroundColor = [UIColor whiteColor];
  48. self.view = perfView;
  49. [self createViewTree];
  50. [self constrainViews];
  51. }
  52. #pragma mark - Properties
  53. - (UIScrollView *)contentView {
  54. if (!_contentView) {
  55. _contentView = [[UIScrollView alloc] init];
  56. _contentView.translatesAutoresizingMaskIntoConstraints = NO;
  57. _contentView.backgroundColor = [UIColor whiteColor];
  58. _contentView.showsHorizontalScrollIndicator = NO;
  59. _contentView.showsVerticalScrollIndicator = YES;
  60. _contentView.accessibilityLabel = @"ContentView";
  61. }
  62. return _contentView;
  63. }
  64. - (UIButton *)addTraceButton {
  65. if (!_addTraceButton) {
  66. _addTraceButton = [[UIButton alloc] init];
  67. _addTraceButton.translatesAutoresizingMaskIntoConstraints = NO;
  68. [_addTraceButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  69. [_addTraceButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
  70. _addTraceButton.titleLabel.font = [UIFont systemFontOfSize:12.0];
  71. _addTraceButton.contentEdgeInsets =
  72. UIEdgeInsetsMake(kEdgeInsetsTop, kEdgeInsetsLeft, kEdgeInsetsBottom, kEdgeInsetsRight);
  73. _addTraceButton.layer.cornerRadius = 3.0f;
  74. _addTraceButton.layer.borderColor = [[UIColor blackColor] CGColor];
  75. _addTraceButton.layer.borderWidth = 1.0f;
  76. [_addTraceButton setTitle:@"Add trace" forState:UIControlStateNormal];
  77. AccessibilityItem *item = [[self class] addTraceAccessibilityItem];
  78. _addTraceButton.accessibilityIdentifier = item.accessibilityID;
  79. _addTraceButton.accessibilityLabel = item.accessibilityLabel;
  80. [_addTraceButton addTarget:self
  81. action:@selector(createAndPositionNewTraceView:)
  82. forControlEvents:UIControlEventTouchDown];
  83. }
  84. return _addTraceButton;
  85. }
  86. #pragma mark - Private Methods
  87. #pragma mark - View hierarchy methods
  88. - (void)constrainViews {
  89. [self addConstraintsString:@"H:|-40-[_addTraceButton]-40-|"
  90. forViewsBinding:NSDictionaryOfVariableBindings(_addTraceButton)];
  91. [self addConstraintsString:@"V:|-60-[_addTraceButton(40)]-10-[_contentView]-|"
  92. forViewsBinding:NSDictionaryOfVariableBindings(_addTraceButton, _contentView)];
  93. [self addConstraintsString:@"H:|[_contentView]|"
  94. forViewsBinding:NSDictionaryOfVariableBindings(_contentView)];
  95. }
  96. - (void)addConstraintsString:(NSString *)string forViewsBinding:(NSDictionary *)viewsBinding {
  97. NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:string
  98. options:kNilOptions
  99. metrics:nil
  100. views:viewsBinding];
  101. [self.view addConstraints:constraints];
  102. }
  103. - (void)createViewTree {
  104. [self.view addSubview:self.contentView];
  105. [self.view addSubview:self.addTraceButton];
  106. }
  107. /**
  108. * Creates a new trace and adds a PerfTraceView in the view hierarchy.
  109. *
  110. * @param button Button that initiated the request.
  111. */
  112. - (void)createAndPositionNewTraceView:(UIButton *)button {
  113. PerfTraceView *traceView = [self createTraceView];
  114. if (!traceView) {
  115. NSLog(@"Trace creation disabled.");
  116. return;
  117. }
  118. [self.contentView addSubview:traceView];
  119. // Add constraints to position the new trace view at the bottom of the list of trace views.
  120. if (self.recentTraceView) {
  121. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.recentTraceView
  122. attribute:NSLayoutAttributeTop
  123. relatedBy:NSLayoutRelationEqual
  124. toItem:traceView
  125. attribute:NSLayoutAttributeBottom
  126. multiplier:1.0f
  127. constant:10.0f]];
  128. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:traceView
  129. attribute:NSLayoutAttributeLeft
  130. relatedBy:NSLayoutRelationEqual
  131. toItem:self.recentTraceView
  132. attribute:NSLayoutAttributeLeft
  133. multiplier:1.0f
  134. constant:0.0f]];
  135. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:traceView
  136. attribute:NSLayoutAttributeRight
  137. relatedBy:NSLayoutRelationEqual
  138. toItem:self.recentTraceView
  139. attribute:NSLayoutAttributeRight
  140. multiplier:1.0f
  141. constant:0.0f]];
  142. } else {
  143. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView
  144. attribute:NSLayoutAttributeBottom
  145. relatedBy:NSLayoutRelationEqual
  146. toItem:traceView
  147. attribute:NSLayoutAttributeBottom
  148. multiplier:1.0
  149. constant:10.0f]];
  150. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:traceView
  151. attribute:NSLayoutAttributeLeft
  152. relatedBy:NSLayoutRelationEqual
  153. toItem:self.contentView
  154. attribute:NSLayoutAttributeLeft
  155. multiplier:1.0f
  156. constant:10.0f]];
  157. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:traceView
  158. attribute:NSLayoutAttributeRight
  159. relatedBy:NSLayoutRelationEqual
  160. toItem:self.contentView
  161. attribute:NSLayoutAttributeRight
  162. multiplier:1.0f
  163. constant:-10.0f]];
  164. }
  165. [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:traceView
  166. attribute:NSLayoutAttributeCenterX
  167. relatedBy:NSLayoutRelationEqual
  168. toItem:self.contentView
  169. attribute:NSLayoutAttributeCenterX
  170. multiplier:1.0f
  171. constant:0.0f]];
  172. if (self.bottomConstraint) {
  173. [self.contentView removeConstraint:self.bottomConstraint];
  174. }
  175. self.bottomConstraint = [NSLayoutConstraint constraintWithItem:traceView
  176. attribute:NSLayoutAttributeTop
  177. relatedBy:NSLayoutRelationEqual
  178. toItem:self.contentView
  179. attribute:NSLayoutAttributeTop
  180. multiplier:1.0f
  181. constant:10.0f];
  182. [self.contentView addConstraint:self.bottomConstraint];
  183. self.recentTraceView = traceView;
  184. }
  185. /**
  186. * Creates a new PerfTraceView object with a valid unique name and returns back the object.
  187. *
  188. * @return Instance of PerfTraceView.
  189. */
  190. - (PerfTraceView *)createTraceView {
  191. PerfLog(@"Create trace view");
  192. PerfTraceView *traceView = nil;
  193. NSString *traceName = [NSString stringWithFormat:@"Trace %ld", ++self.traceCounter];
  194. FIRTrace *trace = [[FIRPerformance sharedInstance] traceWithName:traceName];
  195. if (trace) {
  196. [trace start];
  197. traceView = [[PerfTraceView alloc] initWithTrace:trace frame:CGRectZero];
  198. traceView.accessibilityLabel = @"traceView";
  199. traceView.backgroundColor = [UIColor colorWithWhite:0.9f alpha:0.5f];
  200. traceView.translatesAutoresizingMaskIntoConstraints = NO;
  201. traceView.delegate = self;
  202. } else {
  203. --self.traceCounter;
  204. }
  205. return traceView;
  206. }
  207. #pragma mark - PerfTraceViewDelegate methods
  208. - (void)perfTraceViewTraceStopped:(PerfTraceView *)traceView {
  209. PerfLog(@"Stop trace");
  210. [traceView.trace stop];
  211. }
  212. @end