NetworkRequestsViewController.m 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 "NetworkRequestsViewController.h"
  16. #import "../Networking/NetworkConnectionsFactory.h"
  17. #import "NetworkConnectionViewController.h"
  18. static NSString *const kConnectionsConfigurationFileName = @"network_connections";
  19. static const CGFloat kNetworkConnectionViewHeight = 70.f;
  20. static const CGFloat kConnectionsListTopOffset = 30.f;
  21. @interface NetworkRequestsViewController ()
  22. @property(nonatomic, strong) NSMutableArray<UIViewController *> *connectionControllers;
  23. @property(nonatomic, weak) UIScrollView *scrollView;
  24. @property(nonatomic, strong) NSDictionary<NSString *, id<NetworkConnection>> *titleConnectionPairs;
  25. @end
  26. @implementation NetworkRequestsViewController
  27. - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
  28. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  29. if (self) {
  30. self.titleConnectionPairs = [NetworkConnectionsFactory
  31. titleConnectionPairsFromConfigFile:kConnectionsConfigurationFileName];
  32. self.connectionControllers = [[NSMutableArray alloc] init];
  33. }
  34. return self;
  35. }
  36. #pragma mark - View Life Cycle
  37. - (void)loadView {
  38. UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  39. view.backgroundColor = [UIColor whiteColor];
  40. self.view = view;
  41. [self createViewTree];
  42. [self constrainViews];
  43. }
  44. #pragma mark - Private methods
  45. - (CGSize)scrollContentViewSize {
  46. return CGSizeMake(
  47. [UIScreen mainScreen].bounds.size.width,
  48. self.titleConnectionPairs.count * kNetworkConnectionViewHeight + kConnectionsListTopOffset);
  49. }
  50. - (void)createViewTree {
  51. UIScrollView *scrollView = [[UIScrollView alloc] init];
  52. scrollView.translatesAutoresizingMaskIntoConstraints = NO;
  53. CGSize contentViewSize = [self scrollContentViewSize];
  54. UIView *contentView = [[UIView alloc]
  55. initWithFrame:CGRectMake(0., 0., contentViewSize.width, contentViewSize.height)];
  56. [self.view addSubview:scrollView];
  57. self.scrollView = scrollView;
  58. scrollView.scrollEnabled = YES;
  59. scrollView.contentSize = contentViewSize;
  60. scrollView.accessibilityIdentifier = @"RequestsScrollView";
  61. [self.titleConnectionPairs enumerateKeysAndObjectsUsingBlock:^(
  62. NSString *_Nonnull title,
  63. id<NetworkConnection> _Nonnull connection, BOOL *_Nonnull stop) {
  64. NetworkConnectionViewController *connectionController =
  65. [[NetworkConnectionViewController alloc] initWithNetworkConnection:connection title:title];
  66. [self.connectionControllers addObject:connectionController];
  67. [contentView addSubview:connectionController.view];
  68. }];
  69. [scrollView addSubview:contentView];
  70. }
  71. - (void)constraintScrollView {
  72. NSArray *horizontalConstraints =
  73. [NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[_scrollView]-0-|"
  74. options:0
  75. metrics:nil
  76. views:NSDictionaryOfVariableBindings(_scrollView)];
  77. [self.view addConstraints:horizontalConstraints];
  78. NSArray *verticalConstraints =
  79. [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_scrollView]"
  80. options:0
  81. metrics:nil
  82. views:NSDictionaryOfVariableBindings(_scrollView)];
  83. [self.view addConstraints:verticalConstraints];
  84. [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_scrollView
  85. attribute:NSLayoutAttributeBottom
  86. relatedBy:NSLayoutRelationEqual
  87. toItem:self.bottomLayoutGuide
  88. attribute:NSLayoutAttributeTop
  89. multiplier:1.0
  90. constant:0.0]];
  91. }
  92. - (void)constrainViews {
  93. [self constraintScrollView];
  94. __block UIView *previousView = nil;
  95. [self.connectionControllers enumerateObjectsUsingBlock:^(
  96. UIViewController *_Nonnull connectionController, NSUInteger idx,
  97. BOOL *_Nonnull stop) {
  98. UIView *connectionView = connectionController.view;
  99. connectionView.translatesAutoresizingMaskIntoConstraints = NO;
  100. [self.scrollView addConstraints:[self horizontalConstraintsForConnectionView:connectionView]];
  101. [self.scrollView addConstraints:[self verticalConstraintsForConnectionView:connectionView
  102. previousViewIfExists:previousView]];
  103. previousView = connectionView;
  104. }];
  105. }
  106. - (NSArray *)horizontalConstraintsForConnectionView:(UIView *)connectionView {
  107. return [NSLayoutConstraint
  108. constraintsWithVisualFormat:@"|-0-[connectionView]-0-|"
  109. options:0
  110. metrics:nil
  111. views:NSDictionaryOfVariableBindings(connectionView)];
  112. }
  113. - (NSArray *)verticalConstraintsForConnectionView:(UIView *)connectionView
  114. previousViewIfExists:(UIView *)previousView {
  115. NSArray *constraints = nil;
  116. NSDictionary *metrics = @{
  117. @"viewHeight" : @(kNetworkConnectionViewHeight),
  118. @"topOffset" : @(kConnectionsListTopOffset)
  119. };
  120. NSString *visualFormat = nil;
  121. if (previousView) {
  122. NSDictionary *viewsBindings = NSDictionaryOfVariableBindings(connectionView, previousView);
  123. visualFormat = @"V:[previousView]-0-[connectionView(viewHeight)]";
  124. constraints = [NSLayoutConstraint constraintsWithVisualFormat:visualFormat
  125. options:0
  126. metrics:metrics
  127. views:viewsBindings];
  128. } else {
  129. NSDictionary *viewsBindings = NSDictionaryOfVariableBindings(connectionView);
  130. visualFormat = @"V:|-(topOffset)-[connectionView(viewHeight)]";
  131. constraints = [NSLayoutConstraint constraintsWithVisualFormat:visualFormat
  132. options:0
  133. metrics:metrics
  134. views:viewsBindings];
  135. }
  136. return constraints;
  137. }
  138. @end