Skip to content

Commit

Permalink
Fixed network table view management.
Browse files Browse the repository at this point in the history
  • Loading branch information
dbukowski committed Mar 30, 2018
1 parent 3c62509 commit 9ffcd54
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 30 deletions.
45 changes: 30 additions & 15 deletions DBDebugToolkit/Classes/Network/DBNetworkToolkit.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ @interface DBNetworkToolkit () <DBRequestModelDelegate>

@property (nonatomic, copy) NSMutableArray *requests;
@property (nonatomic, strong) NSMapTable *runningRequestsModels;
@property (nonatomic, strong) NSOperationQueue *operationQueue;

@end

Expand All @@ -38,6 +39,7 @@ @implementation DBNetworkToolkit
- (instancetype)init {
self = [super init];
if (self) {
[self setupOperationQueue];
[self resetLoggedData];
}

Expand All @@ -58,6 +60,11 @@ + (void)setupURLProtocol {
[NSURLProtocol registerClass:[DBURLProtocol class]];
}

- (void)setupOperationQueue {
self.operationQueue = [NSOperationQueue new];
self.operationQueue.maxConcurrentOperationCount = 1;
}

#pragma mark - Logging settings

- (void)setLoggingEnabled:(BOOL)loggingEnabled {
Expand All @@ -70,9 +77,11 @@ - (void)setLoggingEnabled:(BOOL)loggingEnabled {
}

- (void)resetLoggedData {
_requests = [NSMutableArray array];
_runningRequestsModels = [NSMapTable strongToWeakObjectsMapTable];
[self removeOldSavedRequests];
[self.operationQueue addOperationWithBlock:^{
_requests = [NSMutableArray array];
_runningRequestsModels = [NSMapTable strongToWeakObjectsMapTable];
[self removeOldSavedRequests];
}];
}

#pragma mark - Saving request data
Expand All @@ -94,19 +103,23 @@ - (NSString *)savedRequestsPath {
}

- (void)saveRequest:(NSURLRequest *)request {
DBRequestModel *requestModel = [DBRequestModel requestModelWithRequest:request];
requestModel.delegate = self;
[self.runningRequestsModels setObject:requestModel forKey:request.description];
[self.requests addObject:requestModel];
[self.delegate networkDebugToolkitDidUpdateRequestsList:self];
[self.operationQueue addOperationWithBlock:^{
DBRequestModel *requestModel = [DBRequestModel requestModelWithRequest:request];
requestModel.delegate = self;
[self.runningRequestsModels setObject:requestModel forKey:request.description];
[self.requests addObject:requestModel];
[self.delegate networkDebugToolkitDidUpdateRequestsList:self];
}];
}

- (void)saveRequestOutcome:(DBRequestOutcome *)requestOutcome forRequest:(NSURLRequest *)request {
DBRequestModel *requestModel = [self.runningRequestsModels objectForKey:request.description];
[requestModel saveOutcome:requestOutcome];
[requestModel saveBodyWithData:request.HTTPBody inputStream:request.HTTPBodyStream];
[self.runningRequestsModels removeObjectForKey:request.description];
[self didUpdateRequestModel:requestModel];
[self.operationQueue addOperationWithBlock:^{
DBRequestModel *requestModel = [self.runningRequestsModels objectForKey:request.description];
[requestModel saveOutcome:requestOutcome];
[requestModel saveBodyWithData:request.HTTPBody inputStream:request.HTTPBodyStream];
[self.runningRequestsModels removeObjectForKey:request.description];
[self didUpdateRequestModel:requestModel];
}];
}

- (NSArray *)savedRequests {
Expand All @@ -120,8 +133,10 @@ - (void)requestModelDidFinishSynchronization:(DBRequestModel *)requestModel {
}

- (void)didUpdateRequestModel:(DBRequestModel *)requestModel {
NSInteger requestIndex = [self.requests indexOfObject:requestModel];
[self.delegate networkDebugToolkit:self didUpdateRequestAtIndex:requestIndex];
[self.operationQueue addOperationWithBlock:^{
NSInteger requestIndex = [self.requests indexOfObject:requestModel];
[self.delegate networkDebugToolkit:self didUpdateRequestAtIndex:requestIndex];
}];
}

@end
40 changes: 25 additions & 15 deletions DBDebugToolkit/Classes/Network/DBNetworkViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@
#import "NSBundle+DBDebugToolkit.h"
#import "DBNetworkSettingsTableViewController.h"
#import "DBRequestDetailsViewController.h"
#import "NSOperationQueue+DBMainQueueOperation.h"

static NSString *const DBNetworkViewControllerRequestCellIdentifier = @"DBRequestTableViewCell";

@interface DBNetworkViewController () <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, DBNetworkToolkitDelegate, DBRequestDetailsViewControllerDelegate>

@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;
@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UILabel *loggingRequestsDisabledLabel;
@property (nonatomic, weak) IBOutlet UILabel *loggingRequestsDisabledLabel;
@property (nonatomic, strong) NSArray *filteredRequests;
@property (nonatomic, strong) DBRequestDetailsViewController *requestDetailsViewController;
@property (nonatomic, strong) DBRequestModel *openedRequest;
@property (nonatomic, strong) NSOperationQueue *operationQueue;

@end

Expand All @@ -53,6 +55,8 @@ - (void)viewDidLoad {
forCellReuseIdentifier:DBNetworkViewControllerRequestCellIdentifier];
self.tableView.tableFooterView = [UIView new];
[self configureViewWithLoggingRequestsEnabled:self.networkToolkit.loggingEnabled];
self.operationQueue = [NSOperationQueue new];
self.operationQueue.maxConcurrentOperationCount = 1;
}

- (void)viewDidAppear:(BOOL)animated {
Expand Down Expand Up @@ -90,8 +94,12 @@ - (void)updateRequests {
}

- (void)reloadData {
[self updateRequests];
[self.tableView reloadData];
__weak DBNetworkViewController *weakSelf = self;
[self.operationQueue addMainQueueOperationWithBlock:^{
__strong DBNetworkViewController *strongSelf = weakSelf;
[strongSelf updateRequests];
[strongSelf.tableView reloadData];
}];
}

- (void)configureViewWithLoggingRequestsEnabled:(BOOL)enabled {
Expand Down Expand Up @@ -187,24 +195,26 @@ - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
#pragma mark - DBNetworkToolkitDelegate

- (void)networkDebugToolkitDidUpdateRequestsList:(DBNetworkToolkit *)networkToolkit {
dispatch_async(dispatch_get_main_queue(), ^{
[self reloadData];
});
[self reloadData];
}

- (void)networkDebugToolkit:(DBNetworkToolkit *)networkToolkit didUpdateRequestAtIndex:(NSInteger)index {
dispatch_async(dispatch_get_main_queue(), ^{
DBRequestModel *requestModel = self.networkToolkit.savedRequests[index];
if (requestModel == self.openedRequest) {
[self.requestDetailsViewController configureWithRequestModel:requestModel];
__weak DBNetworkViewController *weakSelf = self;
[self.operationQueue addMainQueueOperationWithBlock:^{
__strong DBNetworkViewController *strongSelf = weakSelf;
DBRequestModel *requestModel = strongSelf.networkToolkit.savedRequests[index];
if (requestModel == strongSelf.openedRequest) {
[strongSelf.requestDetailsViewController configureWithRequestModel:requestModel];
}
[self updateRequests];
NSInteger updatedRequestIndex = [self.filteredRequests indexOfObject:requestModel];
[strongSelf updateRequests];
NSInteger updatedRequestIndex = [strongSelf.filteredRequests indexOfObject:requestModel];
if (updatedRequestIndex != NSNotFound) {
[self.tableView reloadRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:self.filteredRequests.count - 1 - updatedRequestIndex inSection:0] ]
withRowAnimation:UITableViewRowAnimationAutomatic];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:strongSelf.filteredRequests.count - 1 - updatedRequestIndex inSection:0];
DBRequestTableViewCell *requestCell = [strongSelf.tableView cellForRowAtIndexPath:indexPath];
DBRequestModel *requestModel = strongSelf.filteredRequests[strongSelf.filteredRequests.count - 1 - indexPath.row];
[requestCell configureWithRequestModel:requestModel];
}
});
}];
}

- (void)networkDebugToolkit:(DBNetworkToolkit *)networkToolkit didSetEnabled:(BOOL)enabled {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// The MIT License
//
// Copyright (c) 2016 Dariusz Bukowski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import <Foundation/Foundation.h>

typedef void(^DBMainQueueOperationBlock)(void);

/**
`DBMainQueueOperation` is a `NSOperation` subclass running a given block on a main queue.
*/
@interface DBMainQueueOperation : NSOperation

/**
Initializes `DBMainQueueOperation` object with a block.
@param block The block that will be invoked on the main queue.
*/
- (instancetype)initWithMainQueueOperationBlock:(DBMainQueueOperationBlock)block;

/**
Creates and returns a new `DBMainQueueOperation` instance encapsulating a given block.
@param block The block that will be invoked on the main queue.
*/
+ (instancetype)mainQueueOperationWithBlock:(DBMainQueueOperationBlock)block;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// The MIT License
//
// Copyright (c) 2016 Dariusz Bukowski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import "DBMainQueueOperation.h"

typedef NS_ENUM(NSUInteger, DBMainQueueOperationState) {
DBMainQueueOperationStateNotStarted,
DBMainQueueOperationStateStarted,
DBMainQueueOperationStateFinished
};

@interface DBMainQueueOperation ()

@property (nonatomic, assign) DBMainQueueOperationState state;
@property (nonatomic, copy) DBMainQueueOperationBlock block;

@end

@implementation DBMainQueueOperation

#pragma mark - Initialization

- (instancetype)initWithMainQueueOperationBlock:(DBMainQueueOperationBlock)block {
self = [super init];
if (self) {
self.block = block;
self.state = DBMainQueueOperationStateNotStarted;
}

return self;
}

+ (instancetype)mainQueueOperationWithBlock:(DBMainQueueOperationBlock)block {
return [[self alloc] initWithMainQueueOperationBlock:block];
}

#pragma mark - NSOperation methods

- (void)start {
if (self.isCancelled) {
[self willChangeValueForKey:@"isFinished"];
self.state = DBMainQueueOperationStateFinished;
[self didChangeValueForKey:@"isFinished"];
return;
}

dispatch_async(dispatch_get_main_queue(), ^{
[self willChangeValueForKey:@"isExecuting"];
self.state = DBMainQueueOperationStateStarted;
[self didChangeValueForKey:@"isExecuting"];

if (self.block) {
self.block();
}

[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];

self.state = DBMainQueueOperationStateFinished;

[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];
});
}

- (BOOL)isFinished {
return self.state == DBMainQueueOperationStateFinished;
}

- (BOOL)isExecuting {
return self.state == DBMainQueueOperationStateStarted;
}

- (BOOL)isAsynchronous {
return NO;
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// The MIT License
//
// Copyright (c) 2016 Dariusz Bukowski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import <Foundation/Foundation.h>
#import "DBMainQueueOperation.h"

/**
`NSOperationQueue` category that provides a helper method for adding a single main queue operation.
*/
@interface NSOperationQueue (DBMainQueueOperation)

/**
Adds a single main queue operation encapsulating a given block.
@param block The block that will be invoked on the main queue.
*/
- (void)addMainQueueOperationWithBlock:(DBMainQueueOperationBlock)block;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// The MIT License
//
// Copyright (c) 2016 Dariusz Bukowski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import "NSOperationQueue+DBMainQueueOperation.h"

@implementation NSOperationQueue (DBMainQueueOperation)

- (void)addMainQueueOperationWithBlock:(DBMainQueueOperationBlock)block {
DBMainQueueOperation *operation = [DBMainQueueOperation mainQueueOperationWithBlock:block];
[self addOperation:operation];
}

@end
Loading

0 comments on commit 9ffcd54

Please sign in to comment.