From fed6670e642b0ac65f93dcd2ecdf4872f6126580 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Mon, 10 Nov 2014 11:29:25 +0100 Subject: [PATCH 01/12] fix(travis): set fix cocoapods version also point to the current development version in the readme --- .travis.yml | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6e72878..f1d9fc3 100755 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: objective-c before_install: - brew update # workaround for #2836 + - gem install cocoapods -v '0.34.4' - if brew outdated | grep -qx xctool; then brew upgrade xctool; fi # workaround for #2836 - cd Example && pod install && cd - script: diff --git a/README.md b/README.md index 5a1b784..3fefa66 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # HRSCustomErrorHandling -[![CI Status](http://img.shields.io/travis/Hotel-Reservation-Service/HRSCustomErrorHandling.svg?style=flat-square)](https://travis-ci.org/Hotel-Reservation-Service/HRSCustomErrorHandling) +[![CI Status](http://img.shields.io/travis/Hotel-Reservation-Service/HRSCustomErrorHandling/develop.svg?style=flat-square)](https://travis-ci.org/Hotel-Reservation-Service/HRSCustomErrorHandling) [![Version](https://img.shields.io/cocoapods/v/HRSCustomErrorHandling.svg?style=flat-square)](http://cocoadocs.org/docsets/HRSCustomErrorHandling) [![License](https://img.shields.io/cocoapods/l/HRSCustomErrorHandling.svg?style=flat-square)](http://cocoadocs.org/docsets/HRSCustomErrorHandling) [![Platform](https://img.shields.io/cocoapods/p/HRSCustomErrorHandling.svg?style=flat-square)](http://cocoadocs.org/docsets/HRSCustomErrorHandling) From 52d2851b9828c32be4f4b34a74aec25ac17c9ca8 Mon Sep 17 00:00:00 2001 From: Roland Lindner Date: Mon, 16 Mar 2015 15:09:30 +0100 Subject: [PATCH 02/12] Fix compiler error on uncasted objc_msgSend calls in Xcode 6.2 --- Pod/Classes/HRSErrorRecoveryAttempter.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pod/Classes/HRSErrorRecoveryAttempter.m b/Pod/Classes/HRSErrorRecoveryAttempter.m index 1f32d50..d3e59f3 100755 --- a/Pod/Classes/HRSErrorRecoveryAttempter.m +++ b/Pod/Classes/HRSErrorRecoveryAttempter.m @@ -95,7 +95,7 @@ - (void)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recove // method signature: // - (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo; BOOL didRecover = [self attemptRecoveryFromError:error optionIndex:recoveryOptionIndex]; - objc_msgSend(delegate, didRecoverSelector, didRecover, contextInfo); + ((void (*)(id delegate, SEL selector, BOOL didRecover, void *contextInfo))objc_msgSend)(delegate, didRecoverSelector, didRecover, contextInfo); } @end From 2178b6f7f63be9ff3c13307876cc20022a5c93e4 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Fri, 13 Mar 2015 14:09:20 +0100 Subject: [PATCH 03/12] chore: add gemfile to ensure a well defined environment --- Example/Gemfile | 3 +++ Example/Gemfile.lock | 57 ++++++++++++++++++++++++++++++++++++++++++++ Example/Podfile.lock | 4 ++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 Example/Gemfile create mode 100644 Example/Gemfile.lock diff --git a/Example/Gemfile b/Example/Gemfile new file mode 100644 index 0000000..7738900 --- /dev/null +++ b/Example/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gem 'cocoapods', '~> 0.36' diff --git a/Example/Gemfile.lock b/Example/Gemfile.lock new file mode 100644 index 0000000..647fa02 --- /dev/null +++ b/Example/Gemfile.lock @@ -0,0 +1,57 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (4.2.0) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + claide (0.8.1) + cocoapods (0.36.0) + activesupport (>= 3.2.15) + claide (~> 0.8.1) + cocoapods-core (= 0.36.0) + cocoapods-downloader (~> 0.8.1) + cocoapods-plugins (~> 0.4.1) + cocoapods-trunk (~> 0.6.0) + cocoapods-try (~> 0.4.3) + colored (~> 1.2) + escape (~> 0.0.4) + molinillo (~> 0.2.1) + nap (~> 0.8) + open4 (~> 1.3) + xcodeproj (~> 0.23.0) + cocoapods-core (0.36.0) + activesupport (>= 3.2.15) + fuzzy_match (~> 2.0.4) + nap (~> 0.8.0) + cocoapods-downloader (0.8.1) + cocoapods-plugins (0.4.1) + nap + cocoapods-trunk (0.6.0) + nap (>= 0.8) + netrc (= 0.7.8) + cocoapods-try (0.4.3) + colored (1.2) + escape (0.0.4) + fuzzy_match (2.0.4) + i18n (0.7.0) + json (1.8.2) + minitest (5.5.1) + molinillo (0.2.1) + nap (0.8.0) + netrc (0.7.8) + open4 (1.3.4) + thread_safe (0.3.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) + xcodeproj (0.23.0) + activesupport (>= 3) + colored (~> 1.2) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (~> 0.36) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 0991f63..be99d1d 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -11,7 +11,7 @@ EXTERNAL SOURCES: :path: ../ SPEC CHECKSUMS: - HRSCustomErrorHandling: c32762417a44c2c749f5a008d1e1b73c80f0fb36 + HRSCustomErrorHandling: f9024663a3fa494e5bdb3675cced91a953c6109c OCMock: f6cb8c162ab9d5620dddf411282c7b2c0ee78854 -COCOAPODS: 0.34.4 +COCOAPODS: 0.36.0 From fa946e7dbbd824c4cbfef83005c2cd5942e53c49 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Sat, 21 Mar 2015 14:48:40 +0100 Subject: [PATCH 04/12] feat: add equality checks for error recovery attempter This is needed for the coalescing feature so that it can be checked whether a recovery attempter is equal to another or not. As we can not check the internals of the recovery block, we are making a best guess here in checking whether the localised recovery options are equal on both recovery attempters. --- .../Tests/HRSErrorRecoveryAttempterTests.m | 26 +++++++++++++++++++ Pod/Classes/HRSErrorRecoveryAttempter.h | 5 ++++ Pod/Classes/HRSErrorRecoveryAttempter.m | 19 ++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/Example/Tests/HRSErrorRecoveryAttempterTests.m b/Example/Tests/HRSErrorRecoveryAttempterTests.m index fc08cd0..62eddde 100755 --- a/Example/Tests/HRSErrorRecoveryAttempterTests.m +++ b/Example/Tests/HRSErrorRecoveryAttempterTests.m @@ -100,4 +100,30 @@ - (void)testAsynchronousRecoveryAttemptUnsuccessful [attempter attemptRecoveryFromError:nil optionIndex:0 delegate:self didRecoverSelector:@selector(_testAsynchronousRecoveryAttemptUnsuccessful_didPresentErrorWithRecovery:contextInfo:) contextInfo:NULL]; } +- (void)testEquality { + BOOL(^recoveryBlock)(void) = ^BOOL{ + return NO; + }; + BOOL(^otherRecoveryBlock)(void) = ^BOOL{ + return YES; + }; + + HRSErrorRecoveryAttempter *attempter = [HRSErrorRecoveryAttempter new]; + [attempter addRecoveryOptionWithTitle:@"Foo" recoveryAttempt:recoveryBlock]; + + HRSErrorRecoveryAttempter *equalAttempter = [HRSErrorRecoveryAttempter new]; + [equalAttempter addRecoveryOptionWithTitle:@"Foo" recoveryAttempt:otherRecoveryBlock]; + + HRSErrorRecoveryAttempter *unequalAttempter = [HRSErrorRecoveryAttempter new]; + [unequalAttempter addRecoveryOptionWithTitle:@"Bar" recoveryAttempt:otherRecoveryBlock]; + + HRSErrorRecoveryAttempter *advancedAttempter = [HRSErrorRecoveryAttempter new]; + [advancedAttempter addRecoveryOptionWithTitle:@"Foo" recoveryAttempt:otherRecoveryBlock]; + [advancedAttempter addRecoveryOptionWithTitle:@"Bar" recoveryAttempt:otherRecoveryBlock]; + + XCTAssertTrue([attempter isEqual:equalAttempter], @"Both attempter should be equal according to the definition of isEqual:"); + XCTAssertFalse([attempter isEqual:unequalAttempter], @"Both attempter should not be equal according to the definition of isEqual:"); + XCTAssertFalse([attempter isEqual:advancedAttempter], @"Both attempter should not be equal according to the definition of isEqual:"); +} + @end diff --git a/Pod/Classes/HRSErrorRecoveryAttempter.h b/Pod/Classes/HRSErrorRecoveryAttempter.h index 6a4891a..6950319 100755 --- a/Pod/Classes/HRSErrorRecoveryAttempter.h +++ b/Pod/Classes/HRSErrorRecoveryAttempter.h @@ -24,6 +24,11 @@ attempter. The first option that is added should be the default option. The default option shout *not* be a destructive operation. + The recovery attempter can be checked for equality, however as it is not + possible to compare two blocks for being logically equal, we are guessing that + a recovery attempter is equal to another one, if they both have the same + localized recovery options. + @warning Make sure to add at least one recovery block that returns `NO`, such as a cancel recovery option, to make sure the user can break the error presentation cycle in the case your error recovery was not diff --git a/Pod/Classes/HRSErrorRecoveryAttempter.m b/Pod/Classes/HRSErrorRecoveryAttempter.m index d3e59f3..9a4f615 100755 --- a/Pod/Classes/HRSErrorRecoveryAttempter.m +++ b/Pod/Classes/HRSErrorRecoveryAttempter.m @@ -98,4 +98,23 @@ - (void)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recove ((void (*)(id delegate, SEL selector, BOOL didRecover, void *contextInfo))objc_msgSend)(delegate, didRecoverSelector, didRecover, contextInfo); } + + +#pragma mark - equality + +- (NSUInteger)hash { + return self.recoveryOptions.hash; +} + +- (BOOL)isEqual:(id)object { + if (object == self) { + return YES; + } + if ([object isKindOfClass:[self class]] == NO) { + return NO; + } + HRSErrorRecoveryAttempter *otherRecoveryAttempter = object; + return [self.recoveryOptions isEqual:otherRecoveryAttempter.recoveryOptions]; +} + @end From 40daa90da4d593549db0bbced5acaa981d5e0dfb Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Sat, 21 Mar 2015 14:50:19 +0100 Subject: [PATCH 05/12] feat: add queue item Add a class that contains an error and the completion handler that was passed through the responder chain together with this error. This is later used in side a queue. --- .../Private/HRSErrorCoalescingQueueItem.h | 24 +++++++ .../Private/HRSErrorCoalescingQueueItem.m | 71 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 Pod/Classes/Private/HRSErrorCoalescingQueueItem.h create mode 100644 Pod/Classes/Private/HRSErrorCoalescingQueueItem.m diff --git a/Pod/Classes/Private/HRSErrorCoalescingQueueItem.h b/Pod/Classes/Private/HRSErrorCoalescingQueueItem.h new file mode 100644 index 0000000..7444571 --- /dev/null +++ b/Pod/Classes/Private/HRSErrorCoalescingQueueItem.h @@ -0,0 +1,24 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface HRSErrorCoalescingQueueItem : NSObject + +@property (nonatomic, strong, readonly) NSError *error; +@property (nonatomic, copy, readonly) void(^completionHandler)(BOOL didRecover); + ++ (instancetype)itemWithError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler; + +@end diff --git a/Pod/Classes/Private/HRSErrorCoalescingQueueItem.m b/Pod/Classes/Private/HRSErrorCoalescingQueueItem.m new file mode 100644 index 0000000..92934e0 --- /dev/null +++ b/Pod/Classes/Private/HRSErrorCoalescingQueueItem.m @@ -0,0 +1,71 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "HRSErrorCoalescingQueueItem.h" + +@implementation HRSErrorCoalescingQueueItem + ++ (instancetype)itemWithError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler { + return [[self alloc] initWithError:error completionHandler:completionHandler]; +} + +- (instancetype)initWithError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler { + self = [super init]; + if (self) { + _error = error; + _completionHandler = [completionHandler copy]; + } + return self; +} + + + +#pragma mark - equality + +- (NSUInteger)hash { + NSUInteger hash = self.error.domain.hash + ^ self.error.code << 2; + if (self.error.recoveryAttempter && [self.error.recoveryAttempter conformsToProtocol:@protocol(NSObject)]) { + id recoveryAttempter = self.error.recoveryAttempter; + hash ^= recoveryAttempter.hash << 4; + } + return hash; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if ([object isKindOfClass:[self class]] == NO) { + return NO; + } + + HRSErrorCoalescingQueueItem *otherItem = object; + BOOL isEqualError = [self.error.domain isEqualToString:otherItem.error.domain] && self.error.code == otherItem.error.code; + + BOOL isEqualRecoveryAttempter = NO; + if (self.error.recoveryAttempter && [self.error.recoveryAttempter conformsToProtocol:@protocol(NSObject)] + && otherItem.error.recoveryAttempter && [otherItem.error.recoveryAttempter conformsToProtocol:@protocol(NSObject)]) { + id recoveryAttempter = self.error.recoveryAttempter; + id otherRecoveryAttempter = otherItem.error.recoveryAttempter; + isEqualRecoveryAttempter = [recoveryAttempter isEqual:otherRecoveryAttempter]; + + } else { + isEqualRecoveryAttempter = (self.error.recoveryAttempter == otherItem.error.recoveryAttempter); + } + + return isEqualError && isEqualRecoveryAttempter; +} + +@end From 409dd986f9102b50a3784d2f556e1499b4d832e3 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Sat, 21 Mar 2015 14:59:06 +0100 Subject: [PATCH 06/12] feat: add coalescing queue Add a queue that is used for enqueueing and dequeuing errors and their corresponding completion handlers from the responder chain. --- .../project.pbxproj | 1896 +++++------------ Example/Tests/HRSErrorCoalescingQueueTests.m | 116 + Pod/Classes/HRSErrorCoalescingQueue.h | 56 + Pod/Classes/HRSErrorCoalescingQueue.m | 120 ++ 4 files changed, 864 insertions(+), 1324 deletions(-) create mode 100644 Example/Tests/HRSErrorCoalescingQueueTests.m create mode 100644 Pod/Classes/HRSErrorCoalescingQueue.h create mode 100644 Pod/Classes/HRSErrorCoalescingQueue.m diff --git a/Example/HRSCustomErrorHandling.xcodeproj/project.pbxproj b/Example/HRSCustomErrorHandling.xcodeproj/project.pbxproj index d4755f3..3c2e5d5 100755 --- a/Example/HRSCustomErrorHandling.xcodeproj/project.pbxproj +++ b/Example/HRSCustomErrorHandling.xcodeproj/project.pbxproj @@ -1,1324 +1,572 @@ - - - - - archiveVersion - 1 - classes - - objectVersion - 46 - objects - - 0FF4CDACD2204BDEB24B79DC - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-HRSCustomErrorHandling.a - sourceTree - BUILT_PRODUCTS_DIR - - 21896E7EF61E475FB09343AA - - buildActionMask - 2147483647 - files - - inputPaths - - isa - PBXShellScriptBuildPhase - name - Check Pods Manifest.lock - outputPaths - - runOnlyForDeploymentPostprocessing - 0 - shellPath - /bin/sh - shellScript - diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null -if [[ $? != 0 ]] ; then - cat << EOM -error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. -EOM - exit 1 -fi - - showEnvVarsInLog - 0 - - 4C08F24819AA431C00B8B6EC - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - HRSErrorPresenterTests.m - sourceTree - <group> - - 4C08F24919AA431C00B8B6EC - - fileRef - 4C08F24819AA431C00B8B6EC - isa - PBXBuildFile - - 4C08F24A19AA442400B8B6EC - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - HRSErrorPresenterDelegateTests.m - sourceTree - <group> - - 4C08F24B19AA442400B8B6EC - - fileRef - 4C08F24A19AA442400B8B6EC - isa - PBXBuildFile - - 4C08F24C19AA4A7100B8B6EC - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - HRSErrorRecoveryAttempterTests.m - sourceTree - <group> - - 4C08F24D19AA4A7100B8B6EC - - fileRef - 4C08F24C19AA4A7100B8B6EC - isa - PBXBuildFile - - 4CD6839A19AA345500999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - HRSAppDelegate.h - sourceTree - <group> - - 4CD6839B19AA345500999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - HRSAppDelegate.m - sourceTree - <group> - - 4CD6839C19AA345500999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - file.storyboard - path - Main.storyboard - sourceTree - <group> - - 4CD6839D19AA345500999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - HRSViewController.h - sourceTree - <group> - - 4CD6839E19AA345500999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - HRSViewController.m - sourceTree - <group> - - 4CD6839F19AA345500999A50 - - fileRef - 4CD6839B19AA345500999A50 - isa - PBXBuildFile - - 4CD683A019AA345500999A50 - - fileRef - 4CD6839C19AA345500999A50 - isa - PBXBuildFile - - 4CD683A119AA345500999A50 - - fileRef - 4CD6839E19AA345500999A50 - isa - PBXBuildFile - - 4CD683A719AA39ED00999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - text - name - CONTRIBUTING.md - path - ../CONTRIBUTING.md - sourceTree - <group> - - 4CD683A819AA39ED00999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - text - name - CREDITS.md - path - ../CREDITS.md - sourceTree - <group> - - 4CD683A919AA39ED00999A50 - - fileRef - 4CD683A719AA39ED00999A50 - isa - PBXBuildFile - - 4CD683AA19AA39ED00999A50 - - fileRef - 4CD683A819AA39ED00999A50 - isa - PBXBuildFile - - 4CD683AB19AA3EB400999A50 - - fileEncoding - 4 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - HRSResponderChainTests.m - sourceTree - <group> - - 4CD683AC19AA3EB400999A50 - - fileRef - 4CD683AB19AA3EB400999A50 - isa - PBXBuildFile - - 4EA25FCFB694F28D4A2371AF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-Tests.debug.xcconfig - path - Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig - sourceTree - <group> - - 5CF700A7F3064FA2BF895B9B - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-Tests.a - sourceTree - BUILT_PRODUCTS_DIR - - 6003F581195388D10070C39A - - children - - 60FF7A9C1954A5C5007DD14C - 6003F593195388D20070C39A - 6003F5B5195388D20070C39A - 6003F58C195388D20070C39A - 6003F58B195388D20070C39A - AFB8EFB0F79D01F558CF6C49 - - isa - PBXGroup - sourceTree - <group> - - 6003F582195388D10070C39A - - attributes - - CLASSPREFIX - HRS - LastUpgradeCheck - 0510 - ORGANIZATIONNAME - Michael Ochs - TargetAttributes - - 6003F5AD195388D20070C39A - - TestTargetID - 6003F589195388D20070C39A - - - - buildConfigurationList - 6003F585195388D10070C39A - compatibilityVersion - Xcode 3.2 - developmentRegion - English - hasScannedForEncodings - 0 - isa - PBXProject - knownRegions - - en - Base - - mainGroup - 6003F581195388D10070C39A - productRefGroup - 6003F58B195388D20070C39A - projectDirPath - - projectReferences - - projectRoot - - targets - - 6003F589195388D20070C39A - 6003F5AD195388D20070C39A - - - 6003F585195388D10070C39A - - buildConfigurations - - 6003F5BD195388D20070C39A - 6003F5BE195388D20070C39A - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 6003F586195388D20070C39A - - buildActionMask - 2147483647 - files - - 4CD683A119AA345500999A50 - 4CD6839F19AA345500999A50 - 6003F59A195388D20070C39A - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6003F587195388D20070C39A - - buildActionMask - 2147483647 - files - - 6003F590195388D20070C39A - 6003F592195388D20070C39A - 6003F58E195388D20070C39A - E88BBB059A3441C69BB31C99 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6003F588195388D20070C39A - - buildActionMask - 2147483647 - files - - 4CD683AA19AA39ED00999A50 - 4CD683A019AA345500999A50 - 4CD683A919AA39ED00999A50 - - isa - PBXResourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6003F589195388D20070C39A - - buildConfigurationList - 6003F5BF195388D20070C39A - buildPhases - - 21896E7EF61E475FB09343AA - 6003F586195388D20070C39A - 6003F587195388D20070C39A - 6003F588195388D20070C39A - 94A8A00043D8422B9972DEF3 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - HRSCustomErrorHandling - productName - HRSCustomErrorHandling - productReference - 6003F58A195388D20070C39A - productType - com.apple.product-type.application - - 6003F58A195388D20070C39A - - explicitFileType - wrapper.application - includeInIndex - 0 - isa - PBXFileReference - path - HRSCustomErrorHandling.app - sourceTree - BUILT_PRODUCTS_DIR - - 6003F58B195388D20070C39A - - children - - 6003F58A195388D20070C39A - 6003F5AE195388D20070C39A - - isa - PBXGroup - name - Products - sourceTree - <group> - - 6003F58C195388D20070C39A - - children - - 6003F58D195388D20070C39A - 6003F58F195388D20070C39A - 6003F591195388D20070C39A - 6003F5AF195388D20070C39A - 0FF4CDACD2204BDEB24B79DC - 5CF700A7F3064FA2BF895B9B - - isa - PBXGroup - name - Frameworks - sourceTree - <group> - - 6003F58D195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Foundation.framework - path - System/Library/Frameworks/Foundation.framework - sourceTree - SDKROOT - - 6003F58E195388D20070C39A - - fileRef - 6003F58D195388D20070C39A - isa - PBXBuildFile - - 6003F58F195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - CoreGraphics.framework - path - System/Library/Frameworks/CoreGraphics.framework - sourceTree - SDKROOT - - 6003F590195388D20070C39A - - fileRef - 6003F58F195388D20070C39A - isa - PBXBuildFile - - 6003F591195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - UIKit.framework - path - System/Library/Frameworks/UIKit.framework - sourceTree - SDKROOT - - 6003F592195388D20070C39A - - fileRef - 6003F591195388D20070C39A - isa - PBXBuildFile - - 6003F593195388D20070C39A - - children - - 4CD6839A19AA345500999A50 - 4CD6839B19AA345500999A50 - 4CD6839C19AA345500999A50 - 4CD6839D19AA345500999A50 - 4CD6839E19AA345500999A50 - 6003F594195388D20070C39A - - isa - PBXGroup - path - HRSCustomErrorHandling - sourceTree - <group> - - 6003F594195388D20070C39A - - children - - 6003F595195388D20070C39A - 6003F599195388D20070C39A - 6003F59B195388D20070C39A - - isa - PBXGroup - name - Supporting Files - sourceTree - <group> - - 6003F595195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - HRSCustomErrorHandling-Info.plist - sourceTree - <group> - - 6003F599195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - main.m - sourceTree - <group> - - 6003F59A195388D20070C39A - - fileRef - 6003F599195388D20070C39A - isa - PBXBuildFile - - 6003F59B195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - HRSCustomErrorHandling-Prefix.pch - sourceTree - <group> - - 6003F5AA195388D20070C39A - - buildActionMask - 2147483647 - files - - 4C08F24D19AA4A7100B8B6EC - 4CD683AC19AA3EB400999A50 - 4C08F24B19AA442400B8B6EC - 4C08F24919AA431C00B8B6EC - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6003F5AB195388D20070C39A - - buildActionMask - 2147483647 - files - - 6003F5B0195388D20070C39A - 6003F5B2195388D20070C39A - 6003F5B1195388D20070C39A - DF1A052F4D1C460B8E787271 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6003F5AC195388D20070C39A - - buildActionMask - 2147483647 - files - - isa - PBXResourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6003F5AD195388D20070C39A - - buildConfigurationList - 6003F5C2195388D20070C39A - buildPhases - - B7A60EF23693413DA281CBF7 - 6003F5AA195388D20070C39A - 6003F5AB195388D20070C39A - 6003F5AC195388D20070C39A - 6B10C81F541B401ABBE6B17F - - buildRules - - dependencies - - 6003F5B4195388D20070C39A - - isa - PBXNativeTarget - name - Tests - productName - HRSCustomErrorHandlingTests - productReference - 6003F5AE195388D20070C39A - productType - com.apple.product-type.bundle.unit-test - - 6003F5AE195388D20070C39A - - explicitFileType - wrapper.cfbundle - includeInIndex - 0 - isa - PBXFileReference - path - Tests.xctest - sourceTree - BUILT_PRODUCTS_DIR - - 6003F5AF195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - XCTest.framework - path - Library/Frameworks/XCTest.framework - sourceTree - DEVELOPER_DIR - - 6003F5B0195388D20070C39A - - fileRef - 6003F5AF195388D20070C39A - isa - PBXBuildFile - - 6003F5B1195388D20070C39A - - fileRef - 6003F58D195388D20070C39A - isa - PBXBuildFile - - 6003F5B2195388D20070C39A - - fileRef - 6003F591195388D20070C39A - isa - PBXBuildFile - - 6003F5B3195388D20070C39A - - containerPortal - 6003F582195388D10070C39A - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 6003F589195388D20070C39A - remoteInfo - HRSCustomErrorHandling - - 6003F5B4195388D20070C39A - - isa - PBXTargetDependency - target - 6003F589195388D20070C39A - targetProxy - 6003F5B3195388D20070C39A - - 6003F5B5195388D20070C39A - - children - - 4CD683AB19AA3EB400999A50 - 4C08F24819AA431C00B8B6EC - 4C08F24A19AA442400B8B6EC - 4C08F24C19AA4A7100B8B6EC - 6003F5B6195388D20070C39A - - isa - PBXGroup - path - Tests - sourceTree - <group> - - 6003F5B6195388D20070C39A - - children - - 6003F5B7195388D20070C39A - 606FC2411953D9B200FFA9A0 - - isa - PBXGroup - name - Supporting Files - sourceTree - <group> - - 6003F5B7195388D20070C39A - - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Tests-Info.plist - sourceTree - <group> - - 6003F5BD195388D20070C39A - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - YES - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES_ERROR - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES_ERROR - CLANG_WARN__DUPLICATE_METHOD_MATCH - YES - CODE_SIGN_IDENTITY[sdk=iphoneos*] - iPhone Developer - COPY_PHASE_STRIP - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES_ERROR - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES_AGGRESSIVE - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - IPHONEOS_DEPLOYMENT_TARGET - 7.1 - ONLY_ACTIVE_ARCH - YES - SDKROOT - iphoneos - TARGETED_DEVICE_FAMILY - 1,2 - - isa - XCBuildConfiguration - name - Debug - - 6003F5BE195388D20070C39A - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - YES - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES_ERROR - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES_ERROR - CLANG_WARN__DUPLICATE_METHOD_MATCH - YES - CODE_SIGN_IDENTITY[sdk=iphoneos*] - iPhone Developer - COPY_PHASE_STRIP - YES - ENABLE_NS_ASSERTIONS - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES_ERROR - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES_AGGRESSIVE - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - IPHONEOS_DEPLOYMENT_TARGET - 7.1 - SDKROOT - iphoneos - TARGETED_DEVICE_FAMILY - 1,2 - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 6003F5BF195388D20070C39A - - buildConfigurations - - 6003F5C0195388D20070C39A - 6003F5C1195388D20070C39A - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 6003F5C0195388D20070C39A - - baseConfigurationReference - D59D2EF080598976BDADD7B1 - buildSettings - - ASSETCATALOG_COMPILER_APPICON_NAME - AppIcon - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME - LaunchImage - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - HRSCustomErrorHandling/HRSCustomErrorHandling-Prefix.pch - INFOPLIST_FILE - HRSCustomErrorHandling/HRSCustomErrorHandling-Info.plist - PRODUCT_NAME - $(TARGET_NAME) - WRAPPER_EXTENSION - app - - isa - XCBuildConfiguration - name - Debug - - 6003F5C1195388D20070C39A - - baseConfigurationReference - D9E6719BFDF43BF089C9DA1F - buildSettings - - ASSETCATALOG_COMPILER_APPICON_NAME - AppIcon - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME - LaunchImage - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - HRSCustomErrorHandling/HRSCustomErrorHandling-Prefix.pch - INFOPLIST_FILE - HRSCustomErrorHandling/HRSCustomErrorHandling-Info.plist - PRODUCT_NAME - $(TARGET_NAME) - WRAPPER_EXTENSION - app - - isa - XCBuildConfiguration - name - Release - - 6003F5C2195388D20070C39A - - buildConfigurations - - 6003F5C3195388D20070C39A - 6003F5C4195388D20070C39A - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 6003F5C3195388D20070C39A - - baseConfigurationReference - 4EA25FCFB694F28D4A2371AF - buildSettings - - BUNDLE_LOADER - $(BUILT_PRODUCTS_DIR)/HRSCustomErrorHandling.app/HRSCustomErrorHandling - FRAMEWORK_SEARCH_PATHS - - $(SDKROOT)/Developer/Library/Frameworks - $(inherited) - $(DEVELOPER_FRAMEWORKS_DIR) - - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Tests/Tests-Prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - INFOPLIST_FILE - Tests/Tests-Info.plist - PRODUCT_NAME - $(TARGET_NAME) - TEST_HOST - $(BUNDLE_LOADER) - WRAPPER_EXTENSION - xctest - - isa - XCBuildConfiguration - name - Debug - - 6003F5C4195388D20070C39A - - baseConfigurationReference - 622E4935C48B5D435B77F678 - buildSettings - - BUNDLE_LOADER - $(BUILT_PRODUCTS_DIR)/HRSCustomErrorHandling.app/HRSCustomErrorHandling - FRAMEWORK_SEARCH_PATHS - - $(SDKROOT)/Developer/Library/Frameworks - $(inherited) - $(DEVELOPER_FRAMEWORKS_DIR) - - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Tests/Tests-Prefix.pch - INFOPLIST_FILE - Tests/Tests-Info.plist - PRODUCT_NAME - $(TARGET_NAME) - TEST_HOST - $(BUNDLE_LOADER) - WRAPPER_EXTENSION - xctest - - isa - XCBuildConfiguration - name - Release - - 606FC2411953D9B200FFA9A0 - - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Tests-Prefix.pch - sourceTree - <group> - - 60FF7A9C1954A5C5007DD14C - - children - - E88FD4B58E254D3F81E9B571 - 9AB14EB49B7C48D39909D9F6 - 4CD683A719AA39ED00999A50 - 4CD683A819AA39ED00999A50 - BD2EC1999F8340C9B40F77C9 - - isa - PBXGroup - name - Podspec Metadata - sourceTree - <group> - - 622E4935C48B5D435B77F678 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-Tests.release.xcconfig - path - Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig - sourceTree - <group> - - 6B10C81F541B401ABBE6B17F - - buildActionMask - 2147483647 - files - - inputPaths - - isa - PBXShellScriptBuildPhase - name - Copy Pods Resources - outputPaths - - runOnlyForDeploymentPostprocessing - 0 - shellPath - /bin/sh - shellScript - "${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh" - - showEnvVarsInLog - 0 - - 94A8A00043D8422B9972DEF3 - - buildActionMask - 2147483647 - files - - inputPaths - - isa - PBXShellScriptBuildPhase - name - Copy Pods Resources - outputPaths - - runOnlyForDeploymentPostprocessing - 0 - shellPath - /bin/sh - shellScript - "${SRCROOT}/Pods/Target Support Files/Pods-HRSCustomErrorHandling/Pods-HRSCustomErrorHandling-resources.sh" - - showEnvVarsInLog - 0 - - 9AB14EB49B7C48D39909D9F6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - README.md - path - ../README.md - sourceTree - <group> - - AFB8EFB0F79D01F558CF6C49 - - children - - D59D2EF080598976BDADD7B1 - D9E6719BFDF43BF089C9DA1F - 4EA25FCFB694F28D4A2371AF - 622E4935C48B5D435B77F678 - - isa - PBXGroup - name - Pods - sourceTree - <group> - - B7A60EF23693413DA281CBF7 - - buildActionMask - 2147483647 - files - - inputPaths - - isa - PBXShellScriptBuildPhase - name - Check Pods Manifest.lock - outputPaths - - runOnlyForDeploymentPostprocessing - 0 - shellPath - /bin/sh - shellScript - diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null -if [[ $? != 0 ]] ; then - cat << EOM -error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. -EOM - exit 1 -fi - - showEnvVarsInLog - 0 - - BD2EC1999F8340C9B40F77C9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - LICENSE - path - ../LICENSE - sourceTree - <group> - - D59D2EF080598976BDADD7B1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-HRSCustomErrorHandling.debug.xcconfig - path - Pods/Target Support Files/Pods-HRSCustomErrorHandling/Pods-HRSCustomErrorHandling.debug.xcconfig - sourceTree - <group> - - D9E6719BFDF43BF089C9DA1F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-HRSCustomErrorHandling.release.xcconfig - path - Pods/Target Support Files/Pods-HRSCustomErrorHandling/Pods-HRSCustomErrorHandling.release.xcconfig - sourceTree - <group> - - DF1A052F4D1C460B8E787271 - - fileRef - 5CF700A7F3064FA2BF895B9B - isa - PBXBuildFile - - E88BBB059A3441C69BB31C99 - - fileRef - 0FF4CDACD2204BDEB24B79DC - isa - PBXBuildFile - - E88FD4B58E254D3F81E9B571 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - HRSCustomErrorHandling.podspec - path - ../HRSCustomErrorHandling.podspec - sourceTree - <group> - - - rootObject - 6003F582195388D10070C39A - - +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4C08F24919AA431C00B8B6EC /* HRSErrorPresenterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C08F24819AA431C00B8B6EC /* HRSErrorPresenterTests.m */; }; + 4C08F24B19AA442400B8B6EC /* HRSErrorPresenterDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C08F24A19AA442400B8B6EC /* HRSErrorPresenterDelegateTests.m */; }; + 4C08F24D19AA4A7100B8B6EC /* HRSErrorRecoveryAttempterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C08F24C19AA4A7100B8B6EC /* HRSErrorRecoveryAttempterTests.m */; }; + 4CD6839F19AA345500999A50 /* HRSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD6839B19AA345500999A50 /* HRSAppDelegate.m */; }; + 4CD683A019AA345500999A50 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4CD6839C19AA345500999A50 /* Main.storyboard */; }; + 4CD683A119AA345500999A50 /* HRSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD6839E19AA345500999A50 /* HRSViewController.m */; }; + 4CD683A919AA39ED00999A50 /* CONTRIBUTING.md in Resources */ = {isa = PBXBuildFile; fileRef = 4CD683A719AA39ED00999A50 /* CONTRIBUTING.md */; }; + 4CD683AA19AA39ED00999A50 /* CREDITS.md in Resources */ = {isa = PBXBuildFile; fileRef = 4CD683A819AA39ED00999A50 /* CREDITS.md */; }; + 4CD683AC19AA3EB400999A50 /* HRSResponderChainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD683AB19AA3EB400999A50 /* HRSResponderChainTests.m */; }; + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; + 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; + 79E2B2591ABDA97F003CCCC2 /* HRSErrorCoalescingQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 79E2B2581ABDA97F003CCCC2 /* HRSErrorCoalescingQueueTests.m */; }; + DF1A052F4D1C460B8E787271 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF700A7F3064FA2BF895B9B /* libPods-Tests.a */; }; + E88BBB059A3441C69BB31C99 /* libPods-HRSCustomErrorHandling.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0FF4CDACD2204BDEB24B79DC /* libPods-HRSCustomErrorHandling.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6003F582195388D10070C39A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6003F589195388D20070C39A; + remoteInfo = HRSCustomErrorHandling; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0FF4CDACD2204BDEB24B79DC /* libPods-HRSCustomErrorHandling.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HRSCustomErrorHandling.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C08F24819AA431C00B8B6EC /* HRSErrorPresenterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSErrorPresenterTests.m; sourceTree = ""; }; + 4C08F24A19AA442400B8B6EC /* HRSErrorPresenterDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSErrorPresenterDelegateTests.m; sourceTree = ""; }; + 4C08F24C19AA4A7100B8B6EC /* HRSErrorRecoveryAttempterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSErrorRecoveryAttempterTests.m; sourceTree = ""; }; + 4CD6839A19AA345500999A50 /* HRSAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRSAppDelegate.h; sourceTree = ""; }; + 4CD6839B19AA345500999A50 /* HRSAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSAppDelegate.m; sourceTree = ""; }; + 4CD6839C19AA345500999A50 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + 4CD6839D19AA345500999A50 /* HRSViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HRSViewController.h; sourceTree = ""; }; + 4CD6839E19AA345500999A50 /* HRSViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSViewController.m; sourceTree = ""; }; + 4CD683A719AA39ED00999A50 /* CONTRIBUTING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CONTRIBUTING.md; path = ../CONTRIBUTING.md; sourceTree = ""; }; + 4CD683A819AA39ED00999A50 /* CREDITS.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CREDITS.md; path = ../CREDITS.md; sourceTree = ""; }; + 4CD683AB19AA3EB400999A50 /* HRSResponderChainTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSResponderChainTests.m; sourceTree = ""; }; + 4EA25FCFB694F28D4A2371AF /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; + 5CF700A7F3064FA2BF895B9B /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F58A195388D20070C39A /* HRSCustomErrorHandling.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HRSCustomErrorHandling.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 6003F595195388D20070C39A /* HRSCustomErrorHandling-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HRSCustomErrorHandling-Info.plist"; sourceTree = ""; }; + 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6003F59B195388D20070C39A /* HRSCustomErrorHandling-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HRSCustomErrorHandling-Prefix.pch"; sourceTree = ""; }; + 6003F5AE195388D20070C39A /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; + 622E4935C48B5D435B77F678 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; + 79E2B2581ABDA97F003CCCC2 /* HRSErrorCoalescingQueueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HRSErrorCoalescingQueueTests.m; sourceTree = ""; }; + 9AB14EB49B7C48D39909D9F6 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = README.md; path = ../README.md; sourceTree = ""; }; + BD2EC1999F8340C9B40F77C9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + D59D2EF080598976BDADD7B1 /* Pods-HRSCustomErrorHandling.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HRSCustomErrorHandling.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HRSCustomErrorHandling/Pods-HRSCustomErrorHandling.debug.xcconfig"; sourceTree = ""; }; + D9E6719BFDF43BF089C9DA1F /* Pods-HRSCustomErrorHandling.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HRSCustomErrorHandling.release.xcconfig"; path = "Pods/Target Support Files/Pods-HRSCustomErrorHandling/Pods-HRSCustomErrorHandling.release.xcconfig"; sourceTree = ""; }; + E88FD4B58E254D3F81E9B571 /* HRSCustomErrorHandling.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = HRSCustomErrorHandling.podspec; path = ../HRSCustomErrorHandling.podspec; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6003F587195388D20070C39A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, + E88BBB059A3441C69BB31C99 /* libPods-HRSCustomErrorHandling.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6003F5AB195388D20070C39A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, + DF1A052F4D1C460B8E787271 /* libPods-Tests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6003F581195388D10070C39A = { + isa = PBXGroup; + children = ( + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, + 6003F593195388D20070C39A /* HRSCustomErrorHandling */, + 6003F5B5195388D20070C39A /* Tests */, + 6003F58C195388D20070C39A /* Frameworks */, + 6003F58B195388D20070C39A /* Products */, + AFB8EFB0F79D01F558CF6C49 /* Pods */, + ); + sourceTree = ""; + }; + 6003F58B195388D20070C39A /* Products */ = { + isa = PBXGroup; + children = ( + 6003F58A195388D20070C39A /* HRSCustomErrorHandling.app */, + 6003F5AE195388D20070C39A /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 6003F58C195388D20070C39A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6003F58D195388D20070C39A /* Foundation.framework */, + 6003F58F195388D20070C39A /* CoreGraphics.framework */, + 6003F591195388D20070C39A /* UIKit.framework */, + 6003F5AF195388D20070C39A /* XCTest.framework */, + 0FF4CDACD2204BDEB24B79DC /* libPods-HRSCustomErrorHandling.a */, + 5CF700A7F3064FA2BF895B9B /* libPods-Tests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6003F593195388D20070C39A /* HRSCustomErrorHandling */ = { + isa = PBXGroup; + children = ( + 4CD6839A19AA345500999A50 /* HRSAppDelegate.h */, + 4CD6839B19AA345500999A50 /* HRSAppDelegate.m */, + 4CD6839C19AA345500999A50 /* Main.storyboard */, + 4CD6839D19AA345500999A50 /* HRSViewController.h */, + 4CD6839E19AA345500999A50 /* HRSViewController.m */, + 6003F594195388D20070C39A /* Supporting Files */, + ); + path = HRSCustomErrorHandling; + sourceTree = ""; + }; + 6003F594195388D20070C39A /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6003F595195388D20070C39A /* HRSCustomErrorHandling-Info.plist */, + 6003F599195388D20070C39A /* main.m */, + 6003F59B195388D20070C39A /* HRSCustomErrorHandling-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6003F5B5195388D20070C39A /* Tests */ = { + isa = PBXGroup; + children = ( + 4CD683AB19AA3EB400999A50 /* HRSResponderChainTests.m */, + 4C08F24819AA431C00B8B6EC /* HRSErrorPresenterTests.m */, + 4C08F24A19AA442400B8B6EC /* HRSErrorPresenterDelegateTests.m */, + 4C08F24C19AA4A7100B8B6EC /* HRSErrorRecoveryAttempterTests.m */, + 79E2B2581ABDA97F003CCCC2 /* HRSErrorCoalescingQueueTests.m */, + 6003F5B6195388D20070C39A /* Supporting Files */, + ); + path = Tests; + sourceTree = ""; + }; + 6003F5B6195388D20070C39A /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6003F5B7195388D20070C39A /* Tests-Info.plist */, + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { + isa = PBXGroup; + children = ( + E88FD4B58E254D3F81E9B571 /* HRSCustomErrorHandling.podspec */, + 9AB14EB49B7C48D39909D9F6 /* README.md */, + 4CD683A719AA39ED00999A50 /* CONTRIBUTING.md */, + 4CD683A819AA39ED00999A50 /* CREDITS.md */, + BD2EC1999F8340C9B40F77C9 /* LICENSE */, + ); + name = "Podspec Metadata"; + sourceTree = ""; + }; + AFB8EFB0F79D01F558CF6C49 /* Pods */ = { + isa = PBXGroup; + children = ( + D59D2EF080598976BDADD7B1 /* Pods-HRSCustomErrorHandling.debug.xcconfig */, + D9E6719BFDF43BF089C9DA1F /* Pods-HRSCustomErrorHandling.release.xcconfig */, + 4EA25FCFB694F28D4A2371AF /* Pods-Tests.debug.xcconfig */, + 622E4935C48B5D435B77F678 /* Pods-Tests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 6003F589195388D20070C39A /* HRSCustomErrorHandling */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "HRSCustomErrorHandling" */; + buildPhases = ( + 21896E7EF61E475FB09343AA /* Check Pods Manifest.lock */, + 6003F586195388D20070C39A /* Sources */, + 6003F587195388D20070C39A /* Frameworks */, + 6003F588195388D20070C39A /* Resources */, + 94A8A00043D8422B9972DEF3 /* Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HRSCustomErrorHandling; + productName = HRSCustomErrorHandling; + productReference = 6003F58A195388D20070C39A /* HRSCustomErrorHandling.app */; + productType = "com.apple.product-type.application"; + }; + 6003F5AD195388D20070C39A /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + B7A60EF23693413DA281CBF7 /* Check Pods Manifest.lock */, + 6003F5AA195388D20070C39A /* Sources */, + 6003F5AB195388D20070C39A /* Frameworks */, + 6003F5AC195388D20070C39A /* Resources */, + 6B10C81F541B401ABBE6B17F /* Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 6003F5B4195388D20070C39A /* PBXTargetDependency */, + ); + name = Tests; + productName = HRSCustomErrorHandlingTests; + productReference = 6003F5AE195388D20070C39A /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6003F582195388D10070C39A /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = HRS; + LastUpgradeCheck = 0510; + ORGANIZATIONNAME = "Michael Ochs"; + TargetAttributes = { + 6003F5AD195388D20070C39A = { + TestTargetID = 6003F589195388D20070C39A; + }; + }; + }; + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "HRSCustomErrorHandling" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6003F581195388D10070C39A; + productRefGroup = 6003F58B195388D20070C39A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6003F589195388D20070C39A /* HRSCustomErrorHandling */, + 6003F5AD195388D20070C39A /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6003F588195388D20070C39A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CD683AA19AA39ED00999A50 /* CREDITS.md in Resources */, + 4CD683A019AA345500999A50 /* Main.storyboard in Resources */, + 4CD683A919AA39ED00999A50 /* CONTRIBUTING.md in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6003F5AC195388D20070C39A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 21896E7EF61E475FB09343AA /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 6B10C81F541B401ABBE6B17F /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 94A8A00043D8422B9972DEF3 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HRSCustomErrorHandling/Pods-HRSCustomErrorHandling-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + B7A60EF23693413DA281CBF7 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 6003F586195388D20070C39A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CD683A119AA345500999A50 /* HRSViewController.m in Sources */, + 4CD6839F19AA345500999A50 /* HRSAppDelegate.m in Sources */, + 6003F59A195388D20070C39A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6003F5AA195388D20070C39A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C08F24D19AA4A7100B8B6EC /* HRSErrorRecoveryAttempterTests.m in Sources */, + 79E2B2591ABDA97F003CCCC2 /* HRSErrorCoalescingQueueTests.m in Sources */, + 4CD683AC19AA3EB400999A50 /* HRSResponderChainTests.m in Sources */, + 4C08F24B19AA442400B8B6EC /* HRSErrorPresenterDelegateTests.m in Sources */, + 4C08F24919AA431C00B8B6EC /* HRSErrorPresenterTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6003F589195388D20070C39A /* HRSCustomErrorHandling */; + targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 6003F5BD195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6003F5BE195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6003F5C0195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D59D2EF080598976BDADD7B1 /* Pods-HRSCustomErrorHandling.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HRSCustomErrorHandling/HRSCustomErrorHandling-Prefix.pch"; + INFOPLIST_FILE = "HRSCustomErrorHandling/HRSCustomErrorHandling-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 6003F5C1195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D9E6719BFDF43BF089C9DA1F /* Pods-HRSCustomErrorHandling.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HRSCustomErrorHandling/HRSCustomErrorHandling-Prefix.pch"; + INFOPLIST_FILE = "HRSCustomErrorHandling/HRSCustomErrorHandling-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 6003F5C3195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4EA25FCFB694F28D4A2371AF /* Pods-Tests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HRSCustomErrorHandling.app/HRSCustomErrorHandling"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "Tests/Tests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 6003F5C4195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 622E4935C48B5D435B77F678 /* Pods-Tests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HRSCustomErrorHandling.app/HRSCustomErrorHandling"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; + INFOPLIST_FILE = "Tests/Tests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 6003F585195388D10070C39A /* Build configuration list for PBXProject "HRSCustomErrorHandling" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5BD195388D20070C39A /* Debug */, + 6003F5BE195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "HRSCustomErrorHandling" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5C0195388D20070C39A /* Debug */, + 6003F5C1195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5C3195388D20070C39A /* Debug */, + 6003F5C4195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6003F582195388D10070C39A /* Project object */; +} diff --git a/Example/Tests/HRSErrorCoalescingQueueTests.m b/Example/Tests/HRSErrorCoalescingQueueTests.m new file mode 100644 index 0000000..49837d3 --- /dev/null +++ b/Example/Tests/HRSErrorCoalescingQueueTests.m @@ -0,0 +1,116 @@ +// +// HRSErrorCoalescingQueueTests.m +// HRSCustomErrorHandling +// +// Created by Michael Ochs on 21/03/15. +// Copyright (c) 2015 Michael Ochs. All rights reserved. +// + +#import +#import + +#import "HRSErrorCoalescingQueue.h" + + +@interface HRSErrorCoalescingQueue (Internal) + +@property (nonatomic, assign, readwrite, getter=isPresenting) BOOL presenting; +@property (nonatomic, strong, readonly) NSMutableArray *queue; + +- (void)enqueueItem:(id)item; +- (id)dequeueItem; +- (NSArray *)dequeueItemsEqualToItem:(id)item; + +@end + + +@interface HRSErrorCoalescingQueueTests : XCTestCase + +@property (nonatomic, strong, readwrite) HRSErrorCoalescingQueue *sut; + +@end + + +@implementation HRSErrorCoalescingQueueTests + +- (void)setUp { + [super setUp]; + + self.sut = [HRSErrorCoalescingQueue new]; +} + +- (void)tearDown { + self.sut = nil; + + [super tearDown]; +} + +- (void)testSinglePushAndPop { + XCTAssertNil(self.sut.dequeueItem, @"Pre condition not met. Queue was not empty."); + + self.sut.presenting = YES; // lock queue + + NSError *error = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error completionHandler:NULL]; + + id item = [self.sut dequeueItem]; + XCTAssertEqual([item valueForKey:@"error"], error, @"Error from first item should be equal to the one just added as was empty before."); +} + +- (void)testMultipleEqualPushAndPop { + XCTAssertNil(self.sut.dequeueItem, @"Pre condition not met. Queue was not empty."); + + self.sut.presenting = YES; // lock queue + + NSError *error1 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error1 completionHandler:NULL]; + + NSError *error2 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error2 completionHandler:NULL]; + + NSError *error3 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error3 completionHandler:NULL]; + + NSError *error4 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error4 completionHandler:NULL]; + + id item = [self.sut dequeueItem]; + NSArray *equalErrors = [self.sut dequeueItemsEqualToItem:item]; + + XCTAssertEqual(equalErrors.count, 3, @"There should be three equal errors."); + XCTAssertEqual([equalErrors[0] valueForKey:@"error"], error2, @"Item at index 0 should contain error 2"); + XCTAssertEqual([equalErrors[1] valueForKey:@"error"], error3, @"Item at index 1 should contain error 3"); + XCTAssertEqual([equalErrors[2] valueForKey:@"error"], error4, @"Item at index 2 should contain error 4"); +} + +- (void)testMultipleEqualUnequalPushAndPop { + XCTAssertNil(self.sut.dequeueItem, @"Pre condition not met. Queue was not empty."); + + self.sut.presenting = YES; // lock queue + + NSError *error1 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error1 completionHandler:NULL]; + + NSError *error2 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error2 completionHandler:NULL]; + + NSError *error3 = [NSError errorWithDomain:@"Test" code:1 userInfo:nil]; + [self.sut addError:error3 completionHandler:NULL]; + + NSError *error4 = [NSError errorWithDomain:@"OtherTest" code:1 userInfo:nil]; + [self.sut addError:error4 completionHandler:NULL]; + + id item = [self.sut dequeueItem]; + NSArray *equalErrors = [self.sut dequeueItemsEqualToItem:item]; + + XCTAssertEqual(equalErrors.count, 2, @"There should be two equal errors."); + XCTAssertEqual([equalErrors[0] valueForKey:@"error"], error2, @"Item at index 0 should contain error 2"); + XCTAssertEqual([equalErrors[1] valueForKey:@"error"], error3, @"Item at index 1 should contain error 3"); + + id lastItem = [self.sut dequeueItem]; + XCTAssertEqual([lastItem valueForKey:@"error"], error4, @"Remaining item should contain error 4"); + + XCTAssertNil([self.sut dequeueItem], @"After popping all added error items, queue should be empty again."); +} + +@end diff --git a/Pod/Classes/HRSErrorCoalescingQueue.h b/Pod/Classes/HRSErrorCoalescingQueue.h new file mode 100644 index 0000000..94340fa --- /dev/null +++ b/Pod/Classes/HRSErrorCoalescingQueue.h @@ -0,0 +1,56 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +/** + The error coalescing queue gathers all errors that are added to itself and then + usees the HRSErrorPresenter to present the errors, one at a time, ensuring that + one error is not displayed over another. + + When an error is dismissed, the queue iterates over the errors in the queue. As + long as the next error is considered equal, it drops this error and calls the + associated completion handler with the result of the error being dismissed. + + This lookup stops as soon as the queue finds the first error that is not + considered equal. This error is then presented as the next error. + + An error is considered equal if the error domain, the error code, and the + recovery attempter - if there is any - is equal. + */ +@interface HRSErrorCoalescingQueue : NSObject + +/** + The default queue used by the default error presentation logic. + + When you do not make any changes to error processing inside your app, all + errors will be added to this queue. + + @return The default queue + */ ++ (instancetype)defaultQueue; + +/** + Adds the given error to the receiver as the last error to be presented. + + If the queue is currently empty, it immediately presents the error, bypassing + the queue. + + @param error The error to be added to the queue + @param completionHandler The completion handler that should be called after + error recovery. + */ +- (void)addError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler; + +@end diff --git a/Pod/Classes/HRSErrorCoalescingQueue.m b/Pod/Classes/HRSErrorCoalescingQueue.m new file mode 100644 index 0000000..b5cdf50 --- /dev/null +++ b/Pod/Classes/HRSErrorCoalescingQueue.m @@ -0,0 +1,120 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "HRSErrorCoalescingQueue.h" + +#import "HRSErrorCoalescingQueueItem.h" +#import "HRSErrorPresenter.h" + + +@interface HRSErrorCoalescingQueue () + +@property (nonatomic, assign, readwrite, getter=isPresenting) BOOL presenting; +@property (nonatomic, strong, readonly) NSMutableArray *queue; + +@end + + +@implementation HRSErrorCoalescingQueue + ++ (instancetype)defaultQueue { + static HRSErrorCoalescingQueue *defaultQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + defaultQueue = [self new]; + }); + return defaultQueue; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _queue = [NSMutableArray new]; + } + return self; +} + + + +#pragma mark - queue + +- (void)enqueueItem:(HRSErrorCoalescingQueueItem *)item { + [self.queue addObject:item]; +} + +- (HRSErrorCoalescingQueueItem *)dequeueItem { + if (self.queue.count == 0) { + return nil; + } + + HRSErrorCoalescingQueueItem *nextItem = [self.queue firstObject]; + [self.queue removeObjectAtIndex:0]; + return nextItem; +} + +- (NSArray *)dequeueItemsEqualToItem:(HRSErrorCoalescingQueueItem *)item { + __block NSRange itemRange = NSMakeRange(0, 0); + [self.queue enumerateObjectsUsingBlock:^(HRSErrorCoalescingQueueItem *obj, NSUInteger idx, BOOL *stop) { + if ([obj isEqual:item]) { + itemRange.length++; + } else { + *stop = YES; + } + }]; + + NSArray *nextItems = [self.queue subarrayWithRange:itemRange]; + [self.queue removeObjectsInRange:itemRange]; + return nextItems; +} + + + +#pragma mark - error handling + +- (void)presentErrorIfPossible { + if (self.isPresenting) { + return; + } + + HRSErrorCoalescingQueueItem *item = [self dequeueItem]; + if (item == nil) { + return; + } + + self.presenting = YES; + + HRSErrorPresenter *presenter = [HRSErrorPresenter presenterWithError:item.error completionHandler:^(BOOL didRecover) { + if (item.completionHandler) { + item.completionHandler(didRecover); + } + + NSArray *equalItems = [self dequeueItemsEqualToItem:item]; + for (HRSErrorCoalescingQueueItem *item in equalItems) { + if (item.completionHandler) { + item.completionHandler(didRecover); + } + } + self.presenting = NO; + [self presentErrorIfPossible]; + }]; + [presenter show]; +} + +- (void)addError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler { + HRSErrorCoalescingQueueItem *item = [HRSErrorCoalescingQueueItem itemWithError:error completionHandler:completionHandler]; + [self enqueueItem:item]; + [self presentErrorIfPossible]; +} + +@end From fcd0a79f924b2502cf5f198d37770c04ccdd2ab2 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Sat, 21 Mar 2015 15:00:50 +0100 Subject: [PATCH 07/12] feat: hook the coalescing queue to the responder chain instead of directly presenting the error --- Pod/Classes/UIResponder+HRSCustomErrorPresentation.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Pod/Classes/UIResponder+HRSCustomErrorPresentation.m b/Pod/Classes/UIResponder+HRSCustomErrorPresentation.m index 1f41c54..d962c8d 100755 --- a/Pod/Classes/UIResponder+HRSCustomErrorPresentation.m +++ b/Pod/Classes/UIResponder+HRSCustomErrorPresentation.m @@ -14,7 +14,7 @@ #import "UIResponder+HRSCustomErrorPresentation.h" -#import "HRSErrorPresenter.h" +#import "HRSErrorCoalescingQueue.h" @implementation UIResponder (HRSCustomErrorPresentation) @@ -34,7 +34,7 @@ - (void)presentError:(NSError *)error completionHandler:(void (^)(BOOL didRecove (application == self && responderDelegateUnavailable)) { // this is the default implementation of the app delegate or the // application itself, if its delegate does not inherit from UIResponder. - [[HRSErrorPresenter presenterWithError:error completionHandler:completionHandler] show]; + [[HRSErrorCoalescingQueue defaultQueue] addError:error completionHandler:completionHandler]; } else { UIResponder *nextResponder = ([self nextResponder] ?: [UIApplication sharedApplication]); @@ -60,7 +60,7 @@ - (void)presentError:(NSError *)error onViewController:(UIViewController *)viewC if (viewController.isViewLoaded && viewController.view.window) { // if the view controller's view is visible, present the error, // otherwise suppress the error! - [[HRSErrorPresenter presenterWithError:error completionHandler:completionHandler] show]; + [[HRSErrorCoalescingQueue defaultQueue] addError:error completionHandler:completionHandler]; } else { if (completionHandler != NULL) { // make sure the completion handler is always called From 90dc1adf342d49e63723684c281e0878d5d41c18 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Sat, 21 Mar 2015 15:03:00 +0100 Subject: [PATCH 08/12] demo: add a button that throws multiple errors to the demo project to show error coalescing --- Example/HRSCustomErrorHandling/HRSViewController.m | 6 ++++++ Example/HRSCustomErrorHandling/Main.storyboard | 14 ++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Example/HRSCustomErrorHandling/HRSViewController.m b/Example/HRSCustomErrorHandling/HRSViewController.m index 2b78c81..18cf4bf 100755 --- a/Example/HRSCustomErrorHandling/HRSViewController.m +++ b/Example/HRSCustomErrorHandling/HRSViewController.m @@ -100,4 +100,10 @@ - (IBAction)saveFile:(id)sender { } } +- (IBAction)saveMultipleTimes:(id)sender { + for (int i = 0; i < 5; i++) { + [self saveFile:sender]; + } +} + @end diff --git a/Example/HRSCustomErrorHandling/Main.storyboard b/Example/HRSCustomErrorHandling/Main.storyboard index aaa6b67..b8475cb 100755 --- a/Example/HRSCustomErrorHandling/Main.storyboard +++ b/Example/HRSCustomErrorHandling/Main.storyboard @@ -1,7 +1,8 @@ - + - + + @@ -33,24 +34,20 @@ - - - This demo writes the text in this text field to the file specified above once you tap 'Save'. @@ -75,6 +72,11 @@ However if the switch is set to off, existing files are not overwritten. If the + + + + + From 929ae3381e54be364a4aba807c11fb9c5b1120a2 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Wed, 6 May 2015 14:21:55 +0200 Subject: [PATCH 09/12] feat: add subclassing hooks for custom coalescing queues --- Pod/Classes/HRSCustomErrorHandling.h | 1 + Pod/Classes/HRSErrorCoalescingQueue.h | 37 +++++++++++++++++++ Pod/Classes/HRSErrorCoalescingQueue.m | 30 +++++++++------ .../UIResponder+HRSCustomErrorPresentation.h | 1 + 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/Pod/Classes/HRSCustomErrorHandling.h b/Pod/Classes/HRSCustomErrorHandling.h index 8bc2044..c3080dc 100755 --- a/Pod/Classes/HRSCustomErrorHandling.h +++ b/Pod/Classes/HRSCustomErrorHandling.h @@ -13,5 +13,6 @@ // #import +#import #import #import diff --git a/Pod/Classes/HRSErrorCoalescingQueue.h b/Pod/Classes/HRSErrorCoalescingQueue.h index 94340fa..55d069d 100644 --- a/Pod/Classes/HRSErrorCoalescingQueue.h +++ b/Pod/Classes/HRSErrorCoalescingQueue.h @@ -28,6 +28,19 @@ An error is considered equal if the error domain, the error code, and the recovery attempter - if there is any - is equal. + + # Subclassing + + You can subclass `HRSErrorCoalescingQueue` to manipulate the way an error is + displayed or enqueued. To use a custom subclass of the error coalescing queue + you also need to override the `presentError:completionHandler:` and/or + `presentError:onViewController:completionHandler:` methods of `UIResponder`. + + To properly use your custom queue, override one or both of these methods in + your last responder in the responder chain. This is your `UIApplicationDelegate` + if it inherits from `UIResponder` or your `UIApplication` otherwise. In this + class, you simply override the mentioned methods and call + `addError:completionHandler:` on your own queue. */ @interface HRSErrorCoalescingQueue : NSObject @@ -54,3 +67,27 @@ - (void)addError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler; @end + + +@interface HRSErrorCoalescingQueue (Subclassing) + +/** + Presents the passed in error. + + You can override this method to perform custom error presentation. The queue + calls this method when it is time to present another error. In your custom + implementation you need to make sure to call the completion handler when you + are done presenting the error, otherwise you will lock up the queue. + + @warning Do not call this method yourself, instead always use the + `addError:completionHandler:` method. This method is only used for + subclassing purpose. + + @param error The error that should be presented + @param completionHandler The completion handler to be called when the error + presentation ends. This completion handler can be + called on any thread. + */ +- (void)presentError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler; + +@end diff --git a/Pod/Classes/HRSErrorCoalescingQueue.m b/Pod/Classes/HRSErrorCoalescingQueue.m index b5cdf50..6a314cf 100644 --- a/Pod/Classes/HRSErrorCoalescingQueue.m +++ b/Pod/Classes/HRSErrorCoalescingQueue.m @@ -94,21 +94,24 @@ - (void)presentErrorIfPossible { self.presenting = YES; - HRSErrorPresenter *presenter = [HRSErrorPresenter presenterWithError:item.error completionHandler:^(BOOL didRecover) { - if (item.completionHandler) { - item.completionHandler(didRecover); - } - - NSArray *equalItems = [self dequeueItemsEqualToItem:item]; - for (HRSErrorCoalescingQueueItem *item in equalItems) { + [self presentError:item.error completionHandler:^(BOOL didRecover) { + dispatch_async(dispatch_get_main_queue(), ^{ if (item.completionHandler) { item.completionHandler(didRecover); } - } - self.presenting = NO; - [self presentErrorIfPossible]; + + NSArray *equalItems = [self dequeueItemsEqualToItem:item]; + for (HRSErrorCoalescingQueueItem *item in equalItems) { + if (item.completionHandler) { + item.completionHandler(didRecover); + } + } + + self.presenting = NO; + + [self presentErrorIfPossible]; + }); }]; - [presenter show]; } - (void)addError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler { @@ -117,4 +120,9 @@ - (void)addError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))co [self presentErrorIfPossible]; } +- (void)presentError:(NSError *)error completionHandler:(void(^)(BOOL didRecover))completionHandler { + HRSErrorPresenter *presenter = [HRSErrorPresenter presenterWithError:error completionHandler:completionHandler]; + [presenter show]; +} + @end diff --git a/Pod/Classes/UIResponder+HRSCustomErrorPresentation.h b/Pod/Classes/UIResponder+HRSCustomErrorPresentation.h index 4e24f81..a98cc41 100755 --- a/Pod/Classes/UIResponder+HRSCustomErrorPresentation.h +++ b/Pod/Classes/UIResponder+HRSCustomErrorPresentation.h @@ -14,6 +14,7 @@ #import +@class HRSErrorCoalescingQueue; @interface UIResponder (HRSCustomErrorPresentation) /** From dfe7a644383985259de606db3a9111e7a1035f55 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Mon, 18 May 2015 14:16:40 +0200 Subject: [PATCH 10/12] chore: bump version to 0.3.0 --- CHANGELOG.md | 2 ++ CREDITS.md | 2 ++ Example/Podfile.lock | 8 ++++---- HRSCustomErrorHandling.podspec | 2 +- VERSION | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac0037a..02d8450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ The versioning in this project is based on [Semantic Versioning](http://semver.org). +## v0.3.0 +Errors will now be queued to prevent several error messages from popping up at the same time. Also multiple error messages of the same type are coalesced and only displayed once. ## v0.2.0 Introduce a new api to present view controller based errors. This api is especially made for overriding and displaying custom error dialogs, such as [TSMessages](https://github.com/toursprung/TSMessages). The default implementation looks the same as the regular api but is only shown if the passed-in view controller is visible. diff --git a/CREDITS.md b/CREDITS.md index 6258a39..5710cd0 100755 --- a/CREDITS.md +++ b/CREDITS.md @@ -11,6 +11,8 @@ The project is available under the Apache 2 license. Please see the LICENSE file ## Contributors +### v0.3.0 +- Roland Lindner - [Fix compiler error on uncasted objc_msgSend calls in Xcode 6.2](https://github.com/Hotel-Reservation-Service/HRSCustomErrorHandling/pull/6) The list of contributors is updated with every new version tag that is added to the project. diff --git a/Example/Podfile.lock b/Example/Podfile.lock index be99d1d..a67c071 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,6 +1,6 @@ PODS: - - HRSCustomErrorHandling (0.2.0) - - OCMock (3.1.1) + - HRSCustomErrorHandling (0.3.0) + - OCMock (3.1.2) DEPENDENCIES: - HRSCustomErrorHandling (from `../`) @@ -11,7 +11,7 @@ EXTERNAL SOURCES: :path: ../ SPEC CHECKSUMS: - HRSCustomErrorHandling: f9024663a3fa494e5bdb3675cced91a953c6109c - OCMock: f6cb8c162ab9d5620dddf411282c7b2c0ee78854 + HRSCustomErrorHandling: 15b590e4da855b718c9f1042defe9c2b54f919d4 + OCMock: a10ea9f0a6e921651f96f78b6faee95ebc813b92 COCOAPODS: 0.36.0 diff --git a/HRSCustomErrorHandling.podspec b/HRSCustomErrorHandling.podspec index 2c71bce..e8c89c7 100644 --- a/HRSCustomErrorHandling.podspec +++ b/HRSCustomErrorHandling.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "HRSCustomErrorHandling" - s.version = "0.2.0" + s.version = "0.3.0" s.summary = "HRSCustomErrorHandling provides an easy way to handle error presentation and creation on iOS." s.description = <<-DESC HRSCustomErrorHandling is a small Framework that provides a base implementation for error handling in iOS applications. It deals with the problem to streamline the presentation of errors in various parts of an application as well as provide APIs to implement error specific recovery options the user of the application can choose from. diff --git a/VERSION b/VERSION index 341cf11..9325c3c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 \ No newline at end of file +0.3.0 \ No newline at end of file From 3d0ed64f9eb6c5eec535e909e86c74370e2ec941 Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Mon, 18 May 2015 14:29:37 +0200 Subject: [PATCH 11/12] chore: use cocoa pods as specified by the gem file --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f1d9fc3..767593e 100755 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,9 @@ language: objective-c before_install: - brew update # workaround for #2836 - - gem install cocoapods -v '0.34.4' - if brew outdated | grep -qx xctool; then brew upgrade xctool; fi # workaround for #2836 +install: + - cd Example && bundle install && cd - - cd Example && pod install && cd - script: - xctool test -workspace Example/HRSCustomErrorHandling.xcworkspace -scheme HRSCustomErrorHandling -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO From e2738a1c95de60407006ccecaa11cbfe6f65f02a Mon Sep 17 00:00:00 2001 From: Michael Ochs Date: Mon, 18 May 2015 14:37:24 +0200 Subject: [PATCH 12/12] fix: suppress warning --- Pod/Classes/HRSErrorPresenter.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Pod/Classes/HRSErrorPresenter.m b/Pod/Classes/HRSErrorPresenter.m index b0f8188..4a480d3 100755 --- a/Pod/Classes/HRSErrorPresenter.m +++ b/Pod/Classes/HRSErrorPresenter.m @@ -27,6 +27,8 @@ @interface HRSErrorPresenter () @implementation HRSErrorPresenter +@dynamic delegate; // prevent warning + + (instancetype)presenterWithError:(NSError *)error completionHandler:(void (^)(BOOL))completionHandler { return [[self alloc] initWithError:error completionHandler:completionHandler];