├── BetterBaseClasses ├── Demo │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── BetterBaseClasses-Bridging-Header.h │ ├── AppDelegate.m │ ├── AppDelegate.h │ ├── main.m │ ├── Info.plist │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── SetViewControllerContainerViewController.swift │ └── SetContentViewContainerViewController.swift └── Library │ ├── BetterBaseCategories.h │ ├── BetterBaseConstants.h │ ├── BetterBaseClasses.h │ ├── BetterBaseViews.h │ ├── Views │ ├── BaseView.h │ ├── BaseTableViewCell.h │ ├── BaseView.m │ ├── BaseTableViewCell.m │ ├── BaseToolbar.m │ ├── BaseNavigationBar.m │ ├── BaseToolbar.h │ ├── DynamicFontView.m │ ├── DynamicFontTableViewCell.m │ ├── UIView+BetterBaseClasses.m │ ├── BaseNavigationBar.h │ ├── DynamicFontView.h │ ├── DynamicFontTableViewCell.h │ └── UIView+BetterBaseClasses.h │ ├── BetterBaseControllers.h │ ├── Constants │ ├── AppDelegateNotificationKeys.m │ └── AppDelegateNotificationKeys.h │ ├── Controllers │ ├── BaseViewController.m │ ├── BaseTableViewController.m │ ├── BaseAppDelegate.h │ ├── BaseViewController.h │ ├── BaseTableViewController.h │ ├── BaseAppDelegate.m │ ├── DynamicFontViewController.m │ ├── BaseNavigationController.h │ ├── DynamicFontTableViewController.m │ ├── DynamicFontTableContainerViewController.m │ ├── BaseTabBarController.h │ ├── DynamicFontViewController.h │ ├── DynamicFontTableViewController.h │ ├── BaseTabBarController.m │ ├── DynamicFontTableContainerViewController.h │ ├── UIViewController+BetterBaseClasses.m │ ├── BaseNavigationController.m │ ├── UIViewController+BetterBaseClasses.h │ └── BaseContainerViewController.h │ └── Categories │ ├── UIView+AnimateIfNeeded.m │ └── UIView+AnimateIfNeeded.h ├── Podfile ├── Podfile.lock ├── .gitignore ├── BetterBaseClassesTests ├── BaseTestCase.h ├── Info.plist ├── BaseTestCase.m ├── BaseViewControllerTests.m ├── BaseViewTests.m ├── BaseTableViewCellTests.m ├── BaseTableViewControllerTests.m ├── BaseToolbarTests.m ├── BaseNavigationBarTests.m ├── DynamicFontViewControllerTests.m ├── DynamicFontTableViewControllerTests.m ├── DynamicFontTableContainerViewControllerTests.m ├── BaseAppDelegateTests.m ├── DynamicFontViewTests.m ├── DynamicFontTableViewCellTests.m ├── UIView+BetterBaseClassesTests.m ├── BaseTabBarControllerTests.m ├── BaseNavigationControllerTests.m └── UIViewController+BetterBaseClassesTests.m ├── BetterBaseClassesUITests ├── Info.plist └── BetterBaseClassesUITests.m ├── LICENSE ├── BetterBaseClasses.podspec └── README.md /BetterBaseClasses/Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | 3 | target 'BetterBaseClasses' do 4 | 5 | target 'BetterBaseClassesTests' do 6 | pod 'Expecta', '~> 1.0' 7 | pod 'OCMock', '~> 3.1' 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/BetterBaseClasses-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | // Controllers 6 | #import "BaseContainerViewController.h" 7 | 8 | // View 9 | #import "BaseNavigationBar.h" 10 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Expecta (1.0.6) 3 | - OCMock (3.4.1) 4 | 5 | DEPENDENCIES: 6 | - Expecta (~> 1.0) 7 | - OCMock (~> 3.1) 8 | 9 | SPEC CHECKSUMS: 10 | Expecta: 3b6bd90a64b9a1dcb0b70aa0e10a7f8f631667d5 11 | OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 12 | 13 | PODFILE CHECKSUM: bfe48fb6c2f50f8b3688d881110d50c50226dd73 14 | 15 | COCOAPODS: 1.3.1 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CocoaPods 2 | Pods 3 | *.xcworkspace/ 4 | 5 | # OS X 6 | .DS_Store 7 | 8 | # SVN 9 | *.svn 10 | .svn/* 11 | 12 | # Xcode 13 | build/ 14 | DerivedData 15 | profile 16 | xcuserdata 17 | !default.mode1v3 18 | !default.mode2v3 19 | !default.pbxuser 20 | !default.perspectivev3 21 | *.mode1 22 | *.mode1v3 23 | *.mode2v3 24 | *.moved-aside 25 | *~.nib 26 | *.pbxuser 27 | *.perspective 28 | *.perspectivev3 29 | *.swp 30 | *.xccheckout 31 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseTestCase.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTestCase.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/21/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseTestCase : XCTestCase { 12 | 13 | id notificationCenter; 14 | id thread; 15 | } 16 | 17 | - (void)givenMockNotificationCenter; 18 | 19 | - (void)givenMockThreadWillReturnIsMainThread:(BOOL)isMainThread; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /BetterBaseClassesUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseTestCase.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTestCase.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/21/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | 9 | #import "BaseTestCase.h" 10 | 11 | #import 12 | 13 | @implementation BaseTestCase 14 | 15 | #pragma mark - Test Lifecycle 16 | 17 | - (void)tearDown { 18 | 19 | [notificationCenter stopMocking]; 20 | [thread stopMocking]; 21 | [super tearDown]; 22 | } 23 | 24 | #pragma mark - Given 25 | 26 | - (void)givenMockNotificationCenter { 27 | notificationCenter = OCMPartialMock([NSNotificationCenter defaultCenter]); 28 | } 29 | 30 | - (void)givenMockThreadWillReturnIsMainThread:(BOOL)isMainThread { 31 | 32 | thread = OCMClassMock([NSThread class]); 33 | OCMStub(ClassMethod([thread isMainThread])).andReturn(isMainThread); 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Joshua Greene 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/BetterBaseCategories.h: -------------------------------------------------------------------------------- 1 | // 2 | // BetterBaseCategories.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/28/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // UIView 27 | #import "UIView+AnimateIfNeeded.h" 28 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 7/26/16. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "AppDelegate.h" 27 | 28 | @implementation AppDelegate 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /BetterBaseClasses/Library/BetterBaseConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // BetterBaseConstants.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Notifications 27 | #import "AppDelegateNotificationKeys.h" 28 | -------------------------------------------------------------------------------- /BetterBaseClassesUITests/BetterBaseClassesUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BetterBaseClassesUITests.m 3 | // BetterBaseClassesUITests 4 | // 5 | // Created by Joshua Greene on 7/26/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BetterBaseClassesUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation BetterBaseClassesUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 7/26/16. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | @interface AppDelegate : UIResponder 29 | @property (strong, nonatomic) UIWindow *window; 30 | @end 31 | 32 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/BetterBaseClasses.h: -------------------------------------------------------------------------------- 1 | // 2 | // BetterBaseControllers.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Constants 27 | #import "BetterBaseConstants.h" 28 | 29 | // Controllers 30 | #import "BetterBaseControllers.h" 31 | 32 | // Views 33 | #import "BetterBaseViews.h" 34 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/BetterBaseViews.h: -------------------------------------------------------------------------------- 1 | // 2 | // BetterBaseViews.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Table View Cell 27 | #import "BaseTableViewCell.h" 28 | #import "DynamicFontTableViewCell.h" 29 | 30 | // UIView 31 | #import "BaseView.h" 32 | #import "DynamicFontView.h" 33 | -------------------------------------------------------------------------------- /BetterBaseClasses.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.platform = :ios 3 | s.ios.deployment_target = "7.0" 4 | s.name = "BetterBaseClasses" 5 | s.version = "1.16.1" 6 | s.summary = "BetterBaseClasses are abstract, base classes meant to be subclassed. They make creating CocoaPods easier." 7 | s.homepage = "https://github.com/JRG-Developer/BetterBaseClasses" 8 | s.license = { :type => "MIT", :file => "LICENSE" } 9 | s.author = { "Joshua Greene" => "jrg.developer@gmail.com" } 10 | s.source = { :git => "https://github.com/JRG-Developer/BetterBaseClasses.git", :tag => "#{s.version}"} 11 | s.framework = "UIKit" 12 | s.requires_arc = true 13 | 14 | s.source_files = "BetterBaseClasses/Library/BetterBaseClasses.h" 15 | 16 | s.subspec 'Categories' do |ss| 17 | ss.source_files = "BetterBaseClasses/Library/BetterBaseCategories.h", "BetterBaseClasses/Library/Categories/*.{h,m}" 18 | end 19 | 20 | s.subspec 'Constants' do |ss| 21 | ss.source_files = "BetterBaseClasses/Library/BetterBaseConstants.h", "BetterBaseClasses/Library/Constants/*.{h,m}" 22 | end 23 | 24 | s.subspec 'Controllers' do |ss| 25 | ss.source_files = "BetterBaseClasses/Library/BetterBaseControllers.h", "BetterBaseClasses/Library/Controllers/*.{h,m}" 26 | ss.dependency 'BetterBaseClasses/Categories' 27 | ss.dependency 'BetterBaseClasses/Constants' 28 | end 29 | 30 | s.subspec 'Views' do |ss| 31 | ss.source_files = "BetterBaseClasses/Library/BetterBaseViews.h", "BetterBaseClasses/Library/Views/*.{h,m}" 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 7/26/16. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | #import "AppDelegate.h" 28 | 29 | int main(int argc, char * argv[]) { 30 | @autoreleasepool { 31 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseView.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/25/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIView+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseView` is an abstract, base class meant to be subclassed instead of `UIView`. 32 | * 33 | * @dicussion This class is designed to be used with the `UIView+BetterBaseClasses` category, which adds convenience class instantiation methods. 34 | */ 35 | @interface BaseView : UIView 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewCell.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/26/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIView+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseView` is an abstract, base class meant to be subclassed instead of `UIView`. 32 | * 33 | * @dicussion This class is designed to be used with the `UIView+BetterBaseClasses` category, which adds convenience class instantiation methods. 34 | */ 35 | @interface BaseTableViewCell : UITableViewCell 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseView.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/25/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseView.h" 27 | 28 | @implementation BaseView 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (instancetype)initWithFrame:(CGRect)frame { 33 | 34 | self = [super initWithFrame:frame]; 35 | if (self) { 36 | [self commonInit]; 37 | } 38 | return self; 39 | } 40 | 41 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 42 | 43 | self = [super initWithCoder:aDecoder]; 44 | if (self) { 45 | [self commonInit]; 46 | } 47 | return self; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewCell.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/26/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseTableViewCell.h" 27 | 28 | @implementation BaseTableViewCell 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (instancetype)initWithFrame:(CGRect)frame { 33 | 34 | self = [super initWithFrame:frame]; 35 | if (self) { 36 | [self commonInit]; 37 | } 38 | return self; 39 | } 40 | 41 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 42 | 43 | self = [super initWithCoder:aDecoder]; 44 | if (self) { 45 | [self commonInit]; 46 | } 47 | return self; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/BetterBaseControllers.h: -------------------------------------------------------------------------------- 1 | // 2 | // BetterBaseControllers.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // App Delegate 27 | #import "BaseAppDelegate.h" 28 | 29 | // Container 30 | #import "BaseContainerViewController.h" 31 | 32 | // Navigation Controller 33 | #import "BaseNavigationController.h" 34 | 35 | // Table View Controller 36 | #import "BaseTableViewController.h" 37 | #import "DynamicFontTableViewController.h" 38 | 39 | // TabBarController 40 | #import "BaseTabBarController.h" 41 | 42 | // View Controller 43 | #import "BaseViewController.h" 44 | #import "DynamicFontTableContainerViewController.h" 45 | #import "DynamicFontViewController.h" 46 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Constants/AppDelegateNotificationKeys.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegateNotificationKeys.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "AppDelegateNotificationKeys.h" 27 | 28 | NSString * const ApplicationDidRegisterUserNotificationSettings = @"ApplicationDidRegisterUserNotificationSettings"; 29 | 30 | NSString * const ApplicationDidRegisterForUserNotificationSettingsNotification = 31 | @"ApplicationDidRegisterUserNotificationSettings"; 32 | 33 | NSString * const ApplicationDidRegisterForRemoteNotificationsNotification = 34 | @"ApplicationDidRegisterForRemoteNotifications"; 35 | 36 | NSString * const ApplicationDidReceiveLocalNotification = @"ApplicationDidReceiveLocalNotification"; 37 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseViewController.h" 27 | 28 | @implementation BaseViewController 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 33 | 34 | self = [super initWithCoder:aDecoder]; 35 | if (self) { 36 | [self commonInit]; 37 | } 38 | return self; 39 | } 40 | 41 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 42 | 43 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 44 | if (self) { 45 | [self commonInit]; 46 | } 47 | return self; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/SetViewControllerContainerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SetViewControllerContainerViewController.swift 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/25/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SetViewControllerContainerViewController: BaseContainerViewController { 12 | 13 | // MARK: - Actions 14 | 15 | @IBAction func toggleTopViewControllerPressed(_ sender: AnyObject) { 16 | 17 | guard topViewController == nil else { 18 | setTop(nil, animated: true, completion: nil) 19 | return 20 | } 21 | 22 | let viewController = UIViewController() 23 | viewController.view.backgroundColor = UIColor.green 24 | setTop(viewController, animated: true, completion: nil) 25 | } 26 | 27 | @IBAction func replaceTopViewControllerPressed(_ sender: AnyObject) { 28 | 29 | let viewController = UIViewController() 30 | viewController.view.backgroundColor = UIColor.blue 31 | setTop(viewController, animated: true, completion: nil) 32 | } 33 | 34 | @IBAction func toggleBottomViewControllerPressed(_ sender: AnyObject) { 35 | 36 | guard bottomViewController == nil else { 37 | setBottom(nil, animated: true, completion: nil) 38 | return 39 | } 40 | 41 | let viewController = UIViewController() 42 | viewController.view.backgroundColor = UIColor.red 43 | setBottom(viewController, animated: true, completion: nil) 44 | } 45 | 46 | @IBAction func replaceBottomViewControllerPressed(_ sender: AnyObject) { 47 | let viewController = UIViewController() 48 | viewController.view.backgroundColor = UIColor.blue 49 | setBottom(viewController, animated: true, completion: nil) 50 | } 51 | 52 | @IBAction func toggleBothViewControllersPresed(_ sender: AnyObject) { 53 | 54 | toggleTopViewControllerPressed(sender) 55 | toggleBottomViewControllerPressed(sender) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /BetterBaseClasses/Demo/SetContentViewContainerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SetContentViewContainerViewController.swift 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/24/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SetContentViewContainerViewController: BaseContainerViewController { 12 | 13 | // MARK: - Actions 14 | 15 | @IBAction func hideShowBottomViewPressed(_ sender: AnyObject) { 16 | 17 | let hidden = bottomContainerViewHeightConstraint!.constant != 0 18 | setBottomContainerViewHidden(hidden, animated: true, completion: nil) 19 | } 20 | 21 | @IBAction func hideShowTopViewPressed(_ sender: AnyObject) { 22 | let hidden = topContainerViewHeightConstraint!.constant != 0 23 | setTopContainerViewHidden(hidden, animated: true, completion: nil) 24 | } 25 | 26 | @IBAction func replaceBottomViewPressed(_ sender: AnyObject) { 27 | 28 | let contentView = UIView() 29 | contentView.backgroundColor = UIColor.blue 30 | setBottomContentView(contentView) 31 | } 32 | 33 | @IBAction func replaceTopViewPressed(_ sender: AnyObject) { 34 | let contentView = UIView() 35 | contentView.backgroundColor = UIColor.blue 36 | setTopContentView(contentView) 37 | } 38 | 39 | @IBAction func toggleTopViewPressed(_ sender: AnyObject) { 40 | 41 | guard topContainerView!.subviews.isEmpty else { 42 | setTopContentView(nil, animated: true, completion: nil) 43 | return 44 | } 45 | let contentView = UIView() 46 | contentView.backgroundColor = UIColor.green 47 | setTopContentView(contentView) 48 | } 49 | 50 | @IBAction func toggleBottomViewPressed(_ sender: AnyObject) { 51 | 52 | guard bottomContainerView!.subviews.isEmpty else { 53 | setBottomContentView(nil) 54 | return 55 | } 56 | let contentView = UIView() 57 | contentView.backgroundColor = UIColor.red 58 | setBottomContentView(contentView) 59 | } 60 | 61 | @IBAction func toggleBothPressed(_ sender: AnyObject) { 62 | toggleTopViewPressed(sender) 63 | toggleBottomViewPressed(sender) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseTableViewController.h" 27 | 28 | @implementation BaseTableViewController 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 33 | 34 | self = [super initWithCoder:aDecoder]; 35 | if (self) { 36 | [self commonInit]; 37 | } 38 | return self; 39 | } 40 | 41 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 42 | 43 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 44 | if (self) { 45 | [self commonInit]; 46 | } 47 | return self; 48 | } 49 | 50 | - (instancetype)initWithStyle:(UITableViewStyle)style { 51 | 52 | self = [super initWithStyle:style]; 53 | if (self) { 54 | [self commonInit]; 55 | } 56 | return self; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAppDelegate.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | /** 29 | * @brief `BaseAppDelegate` is an abstract class meant to be subclassed by your app delegate, instead of `UIResponder` directly. 30 | * 31 | * @discussion This class fixes inconsistencies in app notifications. 32 | * 33 | * For example, it sends out a notifications whenever it receives a call to `application: didRegisterUserNotificationSettings:`. 34 | * 35 | * @note This class is intetionally NOT marked as an "audited region" (that is, `NS_ASSUME_NONNULL_BEGIN` / `NS_ASSUME_NONNULL_END`), so that `window` will be a forced unwrapped optional when automatically converted into Swift. 36 | */ 37 | @interface BaseAppDelegate : UIResponder 38 | 39 | /** 40 | * @brief The main application window 41 | */ 42 | @property (strong, nonatomic) UIWindow *window; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseToolbar.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseToolbar.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 11/21/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseToolbar.h" 27 | #import "UIView+BetterBaseClasses.h" 28 | 29 | @implementation BaseToolbar 30 | 31 | #pragma mark - Object Lifecycle 32 | 33 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 34 | self = [super initWithCoder:aDecoder]; 35 | if (!self) { 36 | return nil; 37 | } 38 | [self commonInit]; 39 | return self; 40 | } 41 | 42 | - (instancetype)initWithFrame:(CGRect)frame { 43 | self = [super initWithFrame:frame]; 44 | if (!self) { 45 | return nil; 46 | } 47 | [self commonInit]; 48 | return self; 49 | } 50 | 51 | - (void)commonInit { 52 | [super commonInit]; 53 | [[self class] configureToolbar:self]; 54 | } 55 | 56 | #pragma mark - Configuration 57 | 58 | + (void)configureAppearProxy { 59 | UIToolbar *toolbar = [UIToolbar appearance]; 60 | [self configureToolbar:toolbar]; 61 | } 62 | 63 | + (void)configureToolbar:(UIToolbar *)toolbar { 64 | // meant to be overriden by subclasses 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIViewController+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseViewController` is an abstract, base class meant to be subclassed instead of `UIViewController`. 32 | * 33 | * @discussion Most view controllers will only have *ONE* nib or storyboard scene associated with them. This class, combined with the `UIViewController+BetterBaseClasses` category, lets you specify the `identifier`, `bundle`, and `storyboardName` as part of the class- where it makes more sense for it to be in most cases- and perform common setup code in `commonInit`. 34 | 35 | This also makes creating and consuming a CocoaPod *much* easier. 36 | 37 | In example, instead of having to call `initWithNibName: bundle:`, which requires that the consuming app have knowledge of the nib name and the bundle, you can simply call `instanceFromNib`. 38 | */ 39 | @interface BaseViewController : UIViewController 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIViewController+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseTableViewController` is an abstract, base class meant to be subclassed instead of `UIViewController`. 32 | * 33 | * @discussion Most view controllers will only have *ONE* nib or storyboard scene associated with them. This class, combined with the `UIViewController+BetterBaseClasses` category, lets you specify the `identifier`, `bundle`, and `storyboardName` as part of the class- where it makes more sense for it to be in most cases- and perform common setup code in `commonInit`. 34 | 35 | * This also makes creating and consuming a CocoaPod *much* easier. 36 | 37 | * In example, instead of having to call `initWithNibName: bundle:`, which requires that the consuming app have knowledge of the nib name and the bundle, you can simply call `instanceFromNib`. 38 | */ 39 | @interface BaseTableViewController : UITableViewController 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseNavigationBar.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseNavigationBar.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 11/20/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseNavigationBar.h" 27 | #import "UIView+BetterBaseClasses.h" 28 | 29 | @implementation BaseNavigationBar 30 | 31 | #pragma mark - Object Lifecycle 32 | 33 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 34 | self = [super initWithCoder:aDecoder]; 35 | if (!self) { 36 | return nil; 37 | } 38 | [self commonInit]; 39 | return self; 40 | } 41 | 42 | - (instancetype)initWithFrame:(CGRect)frame { 43 | self = [super initWithFrame:frame]; 44 | if (!self) { 45 | return nil; 46 | } 47 | [self commonInit]; 48 | return self; 49 | } 50 | 51 | - (void)commonInit { 52 | [super commonInit]; 53 | 54 | [[self class] configureNavigationBar:self]; 55 | } 56 | 57 | #pragma mark - Configuration 58 | 59 | + (void)configureAppearProxy { 60 | 61 | UINavigationBar *navigationBar = [UINavigationBar appearance]; 62 | [self configureNavigationBar:navigationBar]; 63 | } 64 | 65 | + (void)configureNavigationBar:(UINavigationBar *)navigationBar { 66 | // meant to be overriden by subclasses 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseToolbar.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 11/21/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIView+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseToolbar` is an abstract, base class meant to be subclassed instead of `UIToolbar`. 32 | * 33 | * @dicussion This class is designed to be used with the `UIView+BetterBaseClasses` category, which adds convenience class instantiation methods and calls `commonInit` from the `UIToolbar` designated initializers. 34 | */ 35 | @interface BaseToolbar : UIToolbar 36 | 37 | #pragma mark - Configuration 38 | 39 | /** 40 | * @brief Use this method to configure/theme the appearance proxy, `[UIToolbar appearance]`. 41 | * 42 | * @discussion This method passes `[UIToolbar appearance]` to `configureToolbar:`. 43 | */ 44 | + (void)configureAppearProxy; 45 | 46 | /** 47 | * @brief Use this method to configure/theme the toolbar. 48 | * 49 | * @discussion This method is called within `commonInit` and meant to be overriden by subclasses. 50 | * 51 | * @param toolbar The toolbar 52 | */ 53 | + (void)configureToolbar:(UIToolbar *)toolbar NS_SWIFT_NAME(configure(_:)); 54 | 55 | @end 56 | 57 | NS_ASSUME_NONNULL_END 58 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Categories/UIView+AnimateIfNeeded.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+AnimateIfNeeded.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/28/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIView+AnimateIfNeeded.h" 27 | 28 | @implementation UIView (AnimateIfNeeded) 29 | 30 | + (void)animateIfNeededWithDuration:(NSTimeInterval)duration 31 | animations:(void (^)(void))animations 32 | completion:(void (^ __nullable)(BOOL finished))completion { 33 | 34 | [self animateIfNeededWithDuration:duration delay:0 options:0 35 | animations:animations completion:completion]; 36 | } 37 | 38 | + (void)animateIfNeededWithDuration:(NSTimeInterval)duration 39 | delay:(NSTimeInterval)delay 40 | options:(UIViewAnimationOptions)options 41 | animations:(void (^)(void))animations 42 | completion:(void (^ __nullable)(BOOL finished))completion { 43 | 44 | if (duration <= 0) { 45 | animations(); 46 | if (completion) { completion(YES); } 47 | return; 48 | } 49 | 50 | [UIView animateWithDuration:duration delay:delay options:options 51 | animations:animations completion:completion]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/DynamicFontView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontView.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "DynamicFontView.h" 27 | 28 | @implementation DynamicFontView 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (void)commonInit { 33 | 34 | [super commonInit]; 35 | 36 | [[NSNotificationCenter defaultCenter] addObserver:self 37 | selector:@selector(contentSizeCategoryDidChange:) 38 | name:UIContentSizeCategoryDidChangeNotification 39 | object:nil]; 40 | } 41 | 42 | - (void)dealloc { 43 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 44 | } 45 | 46 | #pragma mark - Dynamic Font Type 47 | 48 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification { 49 | 50 | if (![NSThread isMainThread]) { 51 | 52 | [self performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 53 | withObject:notification 54 | waitUntilDone:NO]; 55 | return; 56 | } 57 | 58 | [self refreshView]; 59 | } 60 | 61 | - (void)refreshView { 62 | // This method is meant to be overriden by subclasses. 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/DynamicFontTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableViewCell.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "DynamicFontTableViewCell.h" 27 | 28 | @implementation DynamicFontTableViewCell 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (void)commonInit { 33 | 34 | [super commonInit]; 35 | 36 | [[NSNotificationCenter defaultCenter] addObserver:self 37 | selector:@selector(contentSizeCategoryDidChange:) 38 | name:UIContentSizeCategoryDidChangeNotification 39 | object:nil]; 40 | } 41 | 42 | - (void)dealloc { 43 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 44 | } 45 | 46 | #pragma mark - Dynamic Font Type 47 | 48 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification { 49 | 50 | if (![NSThread isMainThread]) { 51 | 52 | [self performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 53 | withObject:notification 54 | waitUntilDone:NO]; 55 | return; 56 | } 57 | 58 | [self refreshView]; 59 | } 60 | 61 | - (void)refreshView { 62 | // This method is meant to be overriden by subclasses. 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/UIView+BetterBaseClasses.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+BetterBaseClasses.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/25/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIView+BetterBaseClasses.h" 27 | 28 | static NSBundle *BBC_bundle = nil; 29 | 30 | @implementation UIView (BetterBaseClasses) 31 | 32 | #pragma mark - Identifiers 33 | 34 | + (NSBundle *)bundle { 35 | 36 | if (!BBC_bundle) { 37 | return [NSBundle bundleForClass:[self class]]; 38 | } 39 | 40 | return BBC_bundle; 41 | } 42 | 43 | + (void)setBundle:(NSBundle *)bundle { 44 | BBC_bundle = bundle; 45 | } 46 | 47 | + (NSString *)nibName { 48 | 49 | NSString *identifier = NSStringFromClass([self class]); 50 | return identifier.pathExtension.length > 0 ? identifier.pathExtension : identifier; 51 | } 52 | 53 | #pragma mark - Instantiation 54 | 55 | + (instancetype)instanceFromNib { 56 | 57 | UINib *nib = [self nib]; 58 | return [[nib instantiateWithOwner:nil options:nil] lastObject]; 59 | } 60 | 61 | + (UINib *)nib { 62 | 63 | NSString *nibName = [self nibName]; 64 | NSBundle *bundle = [self bundle]; 65 | return [UINib nibWithNibName:nibName bundle:bundle]; 66 | } 67 | 68 | #pragma mark - Object Lifecycle 69 | 70 | - (void)commonInit { 71 | // This method is meant to be overriden by subclasses. 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/BaseNavigationBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseNavigationBar.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 11/20/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIView+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseNavigationBar` is an abstract, base class meant to be subclassed instead of `UINavigationBar`. 32 | * 33 | * @dicussion This class is designed to be used with the `UIView+BetterBaseClasses` category, which adds convenience class instantiation methods and calls `commonInit` from the `UINavigationBar` designated initializers. 34 | */ 35 | @interface BaseNavigationBar : UINavigationBar 36 | 37 | #pragma mark - Configuration 38 | 39 | /** 40 | * @brief Use this method to configure/theme the appearance proxy, `[UINavigationBar appearance]`. 41 | * 42 | * @discussion This method passes `[UINavigationBar appearance]` to `configureNavigationBar:`. 43 | */ 44 | + (void)configureAppearProxy; 45 | 46 | /** 47 | * @brief Use this method to configure/theme the navigation bar. 48 | * 49 | * @discussion This method is called within `commonInit` and meant to be overriden by subclasses. 50 | * 51 | * @param navigationBar The navigation bar 52 | */ 53 | + (void)configureNavigationBar:(UINavigationBar *)navigationBar NS_SWIFT_NAME(configure(_:)); 54 | 55 | @end 56 | 57 | NS_ASSUME_NONNULL_END 58 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAppDelegate.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseAppDelegate.h" 27 | #import "AppDelegateNotificationKeys.h" 28 | 29 | @implementation BaseAppDelegate 30 | 31 | #pragma mark - Notifications 32 | 33 | - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { 34 | 35 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 36 | [notificationCenter postNotificationName:ApplicationDidRegisterForUserNotificationSettingsNotification object:notificationSettings]; 37 | } 38 | 39 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 40 | 41 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 42 | [notificationCenter postNotificationName:ApplicationDidRegisterForRemoteNotificationsNotification object:deviceToken]; 43 | } 44 | 45 | - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { 46 | 47 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 48 | [notificationCenter postNotificationName:ApplicationDidReceiveLocalNotification object:notification]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/DynamicFontViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontViewController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "DynamicFontViewController.h" 27 | 28 | @implementation DynamicFontViewController 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (void)dealloc { 33 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 34 | } 35 | 36 | #pragma mark - View Lifecycle 37 | 38 | - (void)viewDidLoad { 39 | 40 | [super viewDidLoad]; 41 | 42 | [[NSNotificationCenter defaultCenter] addObserver:self 43 | selector:@selector(contentSizeCategoryDidChange:) 44 | name:UIContentSizeCategoryDidChangeNotification 45 | object:nil]; 46 | } 47 | 48 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification { 49 | 50 | if (![NSThread isMainThread]) { 51 | 52 | [self performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 53 | withObject:notification 54 | waitUntilDone:NO]; 55 | return; 56 | } 57 | 58 | [self refreshViews]; 59 | } 60 | 61 | #pragma mark - Dyanmic Font Type 62 | 63 | - (void)refreshViews { 64 | // This method is meant to be overriden by subclasses. 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseNavigationController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/23/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIViewController+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseNavigationController` is an abstract, base class meant to be subclassed instead of `UINavigationController`. 32 | * 33 | * @discussion This class is meant to be used with the `UIViewController+BetterBaseClasses` category, which provides convenience instantiation methods. 34 | * 35 | * This class calls `commonInit` in each of the initializers provided by its super class. Additionally, it overrides certain view methods (`preferredInterfaceOrientationForPresentation`, `preferredStatusBarStyle`, `shouldAutorotate`, and `supportedInterfaceOrientations`) to forward these onto the currently showing view controller, which realistically is what you most likely expected it to do anyways... ;] 36 | */ 37 | @interface BaseNavigationController : UINavigationController 38 | 39 | /** 40 | * @brief Use this method to configure the navigation bar. 41 | * 42 | * @discussion This method is called within `viewDidLoad`. 43 | * 44 | * @param navigationBar The navigation bar belonging to this instance 45 | */ 46 | - (void)configureNavigationBar:(UINavigationBar *)navigationBar; 47 | 48 | @end 49 | 50 | NS_ASSUME_NONNULL_END 51 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/DynamicFontTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableViewController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "DynamicFontTableViewController.h" 27 | 28 | @implementation DynamicFontTableViewController 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (void)dealloc { 33 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 34 | } 35 | 36 | #pragma mark - View Lifecycle 37 | 38 | - (void)viewDidLoad { 39 | 40 | [super viewDidLoad]; 41 | 42 | [[NSNotificationCenter defaultCenter] addObserver:self 43 | selector:@selector(contentSizeCategoryDidChange:) 44 | name:UIContentSizeCategoryDidChangeNotification 45 | object:nil]; 46 | } 47 | 48 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification { 49 | 50 | if (![NSThread isMainThread]) { 51 | 52 | [self performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 53 | withObject:notification 54 | waitUntilDone:NO]; 55 | return; 56 | } 57 | 58 | [self.tableView reloadData]; 59 | [self refreshViews]; 60 | } 61 | 62 | #pragma mark - Dyanmic Font Type 63 | 64 | - (void)refreshViews { 65 | // This method is meant to be overriden by subclasses. 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewControllerTests.m 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseViewController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface BaseViewControllerTests : XCTestCase 40 | @end 41 | 42 | @implementation BaseViewControllerTests { 43 | 44 | BaseViewController *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | 53 | [super setUp]; 54 | 55 | sut = [BaseViewController alloc]; 56 | 57 | partialMock = OCMPartialMock(sut); 58 | OCMExpect([partialMock commonInit]); 59 | } 60 | 61 | - (void)tearDown { 62 | 63 | [partialMock stopMocking]; 64 | [super tearDown]; 65 | } 66 | 67 | #pragma mark - Object Lifecycle - Tests 68 | 69 | - (void)test___initWithCoder___calls_commonInit { 70 | 71 | // given 72 | NSCoder *coder = nil; 73 | 74 | // when 75 | sut = [sut initWithCoder:coder]; 76 | 77 | // then 78 | OCMVerifyAll(partialMock); 79 | } 80 | 81 | - (void)test___initWithNibName_bundle___calls_commonInit { 82 | 83 | // when 84 | sut = [sut initWithNibName:nil bundle:nil]; 85 | 86 | // then 87 | OCMVerifyAll(partialMock); 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/DynamicFontTableContainerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableContainerViewController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/4/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "DynamicFontTableContainerViewController.h" 27 | 28 | @implementation DynamicFontTableContainerViewController 29 | 30 | #pragma mark - Object Lifecycle 31 | 32 | - (void)dealloc { 33 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 34 | } 35 | 36 | #pragma mark - View Lifecycle 37 | 38 | - (void)viewDidLoad { 39 | 40 | [super viewDidLoad]; 41 | 42 | [[NSNotificationCenter defaultCenter] addObserver:self 43 | selector:@selector(contentSizeCategoryDidChange:) 44 | name:UIContentSizeCategoryDidChangeNotification 45 | object:nil]; 46 | } 47 | 48 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification { 49 | 50 | if (![NSThread isMainThread]) { 51 | 52 | [self performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 53 | withObject:notification 54 | waitUntilDone:NO]; 55 | return; 56 | } 57 | 58 | [self.tableView reloadData]; 59 | [self refreshViews]; 60 | } 61 | 62 | #pragma mark - Dyanmic Font Type 63 | 64 | - (void)refreshViews { 65 | // This method is meant to be overriden by subclasses. 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/26/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseView.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface BaseViewTests : XCTestCase 40 | @end 41 | 42 | @implementation BaseViewTests { 43 | 44 | BaseView *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | 53 | [super setUp]; 54 | sut = [BaseView alloc]; 55 | 56 | partialMock = OCMPartialMock(sut); 57 | OCMExpect([partialMock commonInit]); 58 | } 59 | 60 | - (void)tearDown { 61 | 62 | [partialMock stopMocking]; 63 | [super tearDown]; 64 | } 65 | 66 | #pragma mark - Object Lifecycle - Tests 67 | 68 | - (void)test___init___calls_commonInit { 69 | 70 | // given 71 | sut = [sut init]; 72 | 73 | // then 74 | OCMVerifyAll(partialMock); 75 | } 76 | 77 | - (void)test___initWithFrame___calls_commonInit { 78 | 79 | // when 80 | sut = [sut initWithFrame:CGRectZero]; 81 | 82 | // then 83 | OCMVerifyAll(partialMock); 84 | } 85 | 86 | - (void)test___initWithCoder___calls_commonInit { 87 | 88 | // given 89 | NSCoder *coder = nil; 90 | 91 | // when 92 | sut = [sut initWithCoder:coder]; 93 | 94 | // then 95 | OCMVerifyAll(partialMock); 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/DynamicFontView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontView.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseView.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `DynamicFontView` is a subclass of `BaseView` that provides support for dynamic font types. 32 | * 33 | * @discussion This is an abstract, base class meant to be subclassed instead of `UIView`. In addition to the benefits gained by using `BaseView` (see said class header for more details), this class provides support for dynamic font types via its `refreshView` method. You should override this method in your custom subclass in order to reset fonts, etc based on the user's preferred font size. 34 | */ 35 | @interface DynamicFontView : BaseView 36 | 37 | /** 38 | * @brief Override this method to refresh views (e.g. set fonts on labels, text views, etc). 39 | * 40 | * @discussion This message is called on the main thread. 41 | */ 42 | - (void)refreshView; 43 | 44 | @end 45 | 46 | @interface DynamicFontView (Protected) 47 | 48 | /** 49 | * @brief This method is called in response to receiving `UIContentSizeCategoryDidChangeNotification`. 50 | * 51 | * @discussion In general, you should *not* need to override this method. Instead, you should override `refreshViews`. 52 | * 53 | * @param notification The `UIContentSizeCategoryDidChangeNotification` notification 54 | */ 55 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification; 56 | 57 | @end 58 | 59 | NS_ASSUME_NONNULL_END 60 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseTabBarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTabBarController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/23/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIViewController+BetterBaseClasses.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseTabBarController` is an abstract, base class meant to be subclassed instead of `UITabBarController`. 32 | * 33 | * @discussion This class is meant to be used with the `UIViewController+BetterBaseClasses` category, which provides convenience instantiation methods. 34 | * 35 | * This class calls `commonInit` in each of the initializers provided by its super class. Additionally, it overrides certain view methods (`preferredInterfaceOrientationForPresentation`, `preferredStatusBarStyle`, `shouldAutorotate`, and `supportedInterfaceOrientations`) to forward these onto the currently showing view controller, which realistically is what you most likely expected it to do anyways... ;] 36 | */ 37 | @interface BaseTabBarController : UITabBarController 38 | 39 | /** 40 | * @brief Use this method to configure the tab bar appearance. 41 | * 42 | * @discussion This method is called within `viewDidLoad`. 43 | * 44 | * @warning Per Apple's documentation, you should NOT attempt to add any bar button items to this tab bar. Instead, you may only use it for appearance configuration (`barTintColor`, etc). 45 | * 46 | * @param tabBar The tab bar belonging to this instance 47 | */ 48 | - (void)configureTabBar:(UITabBar *)tabBar; 49 | 50 | @end 51 | 52 | NS_ASSUME_NONNULL_END 53 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseTableViewCellTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/26/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseTableViewCell.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface BaseTableViewCellTests : XCTestCase 40 | @end 41 | 42 | @implementation BaseTableViewCellTests { 43 | 44 | BaseTableViewCell *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | 53 | [super setUp]; 54 | sut = [BaseTableViewCell alloc]; 55 | 56 | partialMock = OCMPartialMock(sut); 57 | OCMExpect([partialMock commonInit]); 58 | } 59 | 60 | - (void)tearDown { 61 | 62 | [partialMock stopMocking]; 63 | [super tearDown]; 64 | } 65 | 66 | #pragma mark - Object Lifecycle - Tests 67 | 68 | - (void)test___init___calls_commonInit { 69 | 70 | // given 71 | sut = [sut init]; 72 | 73 | // then 74 | OCMVerifyAll(partialMock); 75 | } 76 | 77 | - (void)test___initWithFrame___calls_commonInit { 78 | 79 | // when 80 | sut = [sut initWithFrame:CGRectZero]; 81 | 82 | // then 83 | OCMVerifyAll(partialMock); 84 | } 85 | 86 | - (void)test___initWithCoder___calls_commonInit { 87 | 88 | // given 89 | NSCoder *coder = nil; 90 | 91 | // when 92 | sut = [sut initWithCoder:coder]; 93 | 94 | // then 95 | OCMVerifyAll(partialMock); 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/DynamicFontTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableViewCell.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseTableViewCell.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `DynamicFontTableViewCell` is a subclass of `BaseTableViewCell` that provides support for dynamic font types. 32 | * 33 | * @discussion This is an abstract, base class meant to be subclassed instead of `UITableViewCell`. In addition to the benefits gained by using `BaseTableViewCell` (see said class header for more details), this class provides support for dynamic font types via its `refreshView` method. You should override this method in your custom subclass in order to reset fonts, etc based on the user's preferred font size. 34 | */ 35 | @interface DynamicFontTableViewCell : BaseTableViewCell 36 | 37 | /** 38 | * @brief Override this method to refresh views (e.g. set fonts on labels, text views, etc). 39 | * 40 | * @discussion This message is called on the main thread. 41 | */ 42 | - (void)refreshView; 43 | 44 | @end 45 | 46 | @interface DynamicFontTableViewCell (Protected) 47 | 48 | /** 49 | * @brief This method is called in response to receiving `UIContentSizeCategoryDidChangeNotification`. 50 | * 51 | * @discussion In general, you should *not* need to override this method. Instead, you should override `refreshViews`. 52 | * 53 | * @param notification The `UIContentSizeCategoryDidChangeNotification` notification 54 | */ 55 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification; 56 | 57 | @end 58 | 59 | NS_ASSUME_NONNULL_END 60 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseTableViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewControllerTests.m 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseTableViewController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface BaseTableViewControllerTests : XCTestCase 40 | @end 41 | 42 | @implementation BaseTableViewControllerTests { 43 | 44 | BaseTableViewController *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp 52 | { 53 | [super setUp]; 54 | 55 | sut = [BaseTableViewController alloc]; 56 | 57 | partialMock = OCMPartialMock(sut); 58 | OCMExpect([partialMock commonInit]); 59 | } 60 | 61 | - (void)tearDown { 62 | 63 | [partialMock stopMocking]; 64 | [super tearDown]; 65 | } 66 | 67 | #pragma mark - Object Lifecycle - Tests 68 | 69 | - (void)test___initWithCoder___calls_commonInit { 70 | 71 | // given 72 | NSCoder *coder; 73 | 74 | // when 75 | sut = [sut initWithCoder:coder]; 76 | 77 | // then 78 | OCMVerifyAll(partialMock); 79 | } 80 | 81 | - (void)test___initWithNibName_bundle___calls_commonInit { 82 | 83 | // when 84 | sut = [sut initWithNibName:nil bundle:nil]; 85 | 86 | // then 87 | OCMVerifyAll(partialMock); 88 | } 89 | 90 | - (void)test___initWithStyle___calls_commonInit { 91 | 92 | // when 93 | sut = [sut initWithStyle:UITableViewStylePlain]; 94 | 95 | // then 96 | OCMVerifyAll(partialMock); 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/DynamicFontViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontViewController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseViewController.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `DynamicFontViewController` is a subclass of `BaseViewController` that provides support for dynamic font types. 32 | * 33 | * @discussion This is an abstract, base controller meant to be subclassed instead of `UIViewController`. In addition to the benefits gained by using `BaseViewController` (see said class header for more details), this class provides support for dynamic font types via its `refreshViews` method. You should override this method in your custom subclass in order to reset fonts, etc based on the user's preferred font size. 34 | */ 35 | @interface DynamicFontViewController : BaseViewController 36 | 37 | #pragma mark - Dynamic Font Type 38 | 39 | /** 40 | * @brief Override this method to refresh views (e.g. set fonts on labels, text views, etc). 41 | * 42 | * @discussion This message is called on the main thread (dispatched to main) in response to receiving a `UIContentSizeCategoryDidChangeNotification` notification. 43 | */ 44 | - (void)refreshViews; 45 | 46 | @end 47 | 48 | @interface DynamicFontViewController (Protected) 49 | 50 | /** 51 | * @brief This method is called in response to receiving `UIContentSizeCategoryDidChangeNotification`. 52 | * 53 | * @discussion In general, you should *not* need to override this method. Instead, you should override `refreshViews`. 54 | * 55 | * @param notification The `UIContentSizeCategoryDidChangeNotification` notification 56 | */ 57 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification; 58 | 59 | @end 60 | 61 | NS_ASSUME_NONNULL_END 62 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/DynamicFontTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableViewController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseTableViewController.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `DynamicFontTableViewController` is a subclass of `BaseTableViewController` that provides support for dynamic font types. 32 | * 33 | * @discussion This is an abstract, base controller meant to be subclassed instead of `UITableViewController`. In addition to the benefits gained by using `BaseTableViewController` (see said class header for more details), this class provides support for dynamic font types via its `refreshViews` method. You should override this method in your custom subclass in order to reset fonts, etc based on the user's preferred font size. 34 | */ 35 | @interface DynamicFontTableViewController : BaseTableViewController 36 | 37 | #pragma mark - Dynamic Font Type 38 | 39 | /** 40 | * @brief Override this method to refresh views (e.g. set fonts on labels, text views, etc). 41 | * 42 | * @discussion This message is called on the main thread. 43 | * 44 | * Prior to this method, `[self.tableView reloadData]` is called. 45 | */ 46 | - (void)refreshViews; 47 | 48 | @end 49 | 50 | @interface DynamicFontTableViewController (Protected) 51 | 52 | /** 53 | * @brief This method is called in response to receiving `UIContentSizeCategoryDidChangeNotification`. 54 | * 55 | * @discussion In general, you should *not* need to override this method. Instead, you should override `refreshViews`. 56 | * 57 | * @param notification The `UIContentSizeCategoryDidChangeNotification` notification 58 | */ 59 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification; 60 | 61 | @end 62 | 63 | NS_ASSUME_NONNULL_END 64 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Constants/AppDelegateNotificationKeys.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegateNotificationKeys.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief This notification is sent when the app delegate is notified that the user has registered for notification settings. 32 | * 33 | * @discusission This notification is sent within `application: didRegisterUserNotificationSettings:`. 34 | * 35 | * The object is the `notificationSettings`. 36 | */ 37 | UIKIT_EXTERN NSString * const ApplicationDidRegisterUserNotificationSettings __deprecated_msg("Use ApplicationDidRegisterForUserNotificationSettingsNotification instead."); 38 | 39 | /** 40 | * @brief This notification is sent when the app delegate is notified that the user has registered for notification settings. 41 | * 42 | * @discusission This notification is sent within `application: didRegisterUserNotificationSettings:`. 43 | * 44 | * The object is the `notificationSettings`. 45 | */ 46 | UIKIT_EXTERN NSString * const ApplicationDidRegisterForUserNotificationSettingsNotification; 47 | 48 | /** 49 | * @brief This notification is sent when the app delegate is notified that the user has registered for remote notifications. 50 | * 51 | * @discusission This notification is sent within `application: didRegisterForRemoteNotificationsWithDeviceToken:`. 52 | * 53 | * The `object` contains the `deviceToken` data that was received from APNS. 54 | */ 55 | UIKIT_EXTERN NSString * const ApplicationDidRegisterForRemoteNotificationsNotification; 56 | 57 | /** 58 | * @brief This notification is sent when the app delegate receives a call to `application: didReceiveLocalNotification:`. 59 | * 60 | * @discussion The object is the `UILocalNotification` object itself. 61 | */ 62 | UIKIT_EXTERN NSString * const ApplicationDidReceiveLocalNotification; 63 | 64 | NS_ASSUME_NONNULL_END 65 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Categories/UIView+AnimateIfNeeded.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+AnimateIfNeeded.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/28/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * `UIView+AnimateIfNeeded` provides convenience methods to perform animations if needed (`duration` greater than zero). 32 | */ 33 | @interface UIView (AnimateIfNeeded) 34 | 35 | /** 36 | * Use this method to perform animations ONLY if the `duration` is greater than zero. Otherwise, 37 | * the animations and completion block are called immediately, without animating. 38 | * 39 | * @param duration The animation duration 40 | * @param animations The animations to be performed 41 | * @param completion The completion to be performed after the animations 42 | */ 43 | + (void)animateIfNeededWithDuration:(NSTimeInterval)duration 44 | animations:(void (^)(void))animations 45 | completion:(void (^ __nullable)(BOOL finished))completion; 46 | 47 | /** 48 | * Use this method to perform animations ONLY if the `duration` is greater than zero. Otherwise, 49 | * the animations and completion block are called immediately, without animating. 50 | * 51 | * @param duration The animation duration 52 | * @param delay The delay before the animation should be performed 53 | * @param options The animation options 54 | * @param animations The animations to be performed 55 | * @param completion The completion to be performed after the animations 56 | */ 57 | + (void)animateIfNeededWithDuration:(NSTimeInterval)duration 58 | delay:(NSTimeInterval)delay 59 | options:(UIViewAnimationOptions)options 60 | animations:(void (^)(void))animations 61 | completion:(void (^ __nullable)(BOOL finished))completion; 62 | 63 | @end 64 | 65 | NS_ASSUME_NONNULL_END 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## BetterBaseClasses 2 | 3 | `BetterBaseClasses` are abstract, base classes meant to be subclassed. 4 | 5 | Most view controllers will only have *ONE* nib or storyboard scene associated with them. `BetterBaseClasses` lets you specify the `identifier`, `bundle`, and `storyboardName` as part of the class- where it makes more sense for it to be in most cases. 6 | 7 | This also makes creating and consuming a CocoaPod *much* easier. 8 | 9 | In example, instead of having to call `initWithNibName: bundle:`, which requires that the consuming app have knowledge of the nib name and the bundle, you can simply call the class method `instanceFromNib`. 10 | 11 | `BetterBaseClasses` also provides convenience methods for working with views, too. 12 | 13 | ### Installation with CocoaPods 14 | 15 | The easiest way to add `BetterBaseClasses` to your project is using CocoaPods. 16 | 17 | Simply add the following line to your Podfile: 18 | 19 | pod 'BetterBaseClasses', '~> 1.0' 20 | 21 | Then run `pod install` as you normally would. 22 | 23 | ### Manual Installation 24 | 25 | Follow these steps for manual installation: 26 | 27 | 1) Clone this repo locally onto your computer, or press `Download ZIP` to download the latest master commit. 28 | 29 | 2) Drag the `BetterBaseClasses` folder into your project. 30 | 31 | 3) Delete the `BetterBaseClasses.h` file (it's a public header for when this included as a library/CocoaPod). 32 | 33 | ### How to Use 34 | 35 | 1) Instead of subclassing `UIViewController` or `UITableViewController`, you should subclass `BaseViewController` or `BaseTableViewController`, respectively. 36 | 37 | 2) (Optional) override `commonInit`, which is called by *all* designated initializers, to run common setup code. 38 | 39 | 3) (Optional) override the class methods `bundle`, `identifier`, or `storyboardName`. This allows you to specify the nib name or storyboard identifier *right in the view controller*. 40 | 41 | In most cases, however, you won't need to override these as reasonable default values are already provided (e.g. nib name is expected to match the view controller's name, etc). 42 | 43 | 4) Call the class method `instanceFromNib` to instantiate a view controller from its nib or `instanceFromStoryboard` to instantiate a view controller from its storyboard scene. 44 | 45 | For example, 46 | 47 | ------ **TestViewController.h** ------ 48 | 49 | #import "BaseViewController.h" 50 | 51 | @interface TestViewController : BaseViewController 52 | @property (assign, nonatomic) NSUInteger exampleValue; 53 | @end 54 | 55 | ------ **TestViewController.m** ------ 56 | 57 | #import "TestViewController.h" 58 | 59 | @implementation TestViewController 60 | 61 | - (void)commonInit { 62 | 63 | [super commonInit]; 64 | _exampleValue = 42; 65 | } 66 | 67 | @end 68 | 69 | You could then instantiate a new `TestViewController` from a nib named `TestViewController.xib` like this: 70 | 71 | TestViewController *viewController = [TestViewController instanceFromNib]; 72 | 73 | Win. :] 74 | 75 | There are also convenience methods for working with views, too. See `BaseView` and `BaseTableView` for in-line documentation for more details. 76 | 77 | ### License 78 | 79 | `BetterBaseClasses` is available under the MIT license (see the LICENSE file for more details). 80 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseTabBarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTabBarController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/23/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseTabBarController.h" 27 | #import "UIViewController+BetterBaseClasses.h" 28 | 29 | @implementation BaseTabBarController 30 | 31 | #pragma mark - Object Lifecycle 32 | 33 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 34 | self = [super initWithCoder:aDecoder]; 35 | if (!self) { 36 | return nil; 37 | } 38 | 39 | [self commonInit]; 40 | return self; 41 | } 42 | 43 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 44 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 45 | if (!self) { 46 | return nil; 47 | } 48 | [self commonInit]; 49 | return self; 50 | } 51 | 52 | #pragma mark - View Lifecycle 53 | 54 | - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { 55 | 56 | UIViewController *viewController = self.selectedViewController; 57 | return viewController != nil ? [viewController preferredInterfaceOrientationForPresentation] : 58 | [super preferredInterfaceOrientationForPresentation]; 59 | } 60 | 61 | - (UIStatusBarStyle)preferredStatusBarStyle { 62 | UIViewController *viewController = self.selectedViewController; 63 | return viewController != nil ? [viewController preferredStatusBarStyle] : [super preferredStatusBarStyle]; 64 | } 65 | 66 | - (BOOL)shouldAutorotate { 67 | UIViewController *viewController = self.selectedViewController; 68 | return viewController != nil ? [viewController shouldAutorotate] : [super shouldAutorotate]; 69 | } 70 | 71 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations { 72 | 73 | UIViewController *viewController = self.selectedViewController; 74 | return viewController != nil ? [viewController supportedInterfaceOrientations] : [super supportedInterfaceOrientations]; 75 | } 76 | 77 | - (void)viewDidLoad { 78 | [super viewDidLoad]; 79 | [self configureTabBar:self.tabBar]; 80 | } 81 | 82 | - (void)configureTabBar:(UITabBar *)tabBar { 83 | // This method is meant to be overriden by subclasses. 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseToolbarTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseToolbarTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 11/21/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // System Under Test 27 | #import "BaseToolbar.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | #import 34 | 35 | @interface BaseToolbarTests : XCTestCase 36 | @end 37 | 38 | @implementation BaseToolbarTests { 39 | 40 | BaseToolbar *sut; 41 | 42 | id partialMock; 43 | } 44 | 45 | #pragma mark - Test Lifecycle 46 | 47 | - (void)setUp { 48 | [super setUp]; 49 | sut = [BaseToolbar alloc]; 50 | } 51 | 52 | - (void)tearDown { 53 | [partialMock stopMocking]; 54 | [super tearDown]; 55 | } 56 | 57 | #pragma mark - Given 58 | 59 | - (void)givenPartialMock { 60 | partialMock = OCMPartialMock(sut); 61 | } 62 | 63 | - (void)givenExpectWillCallCommonInit { 64 | [self givenPartialMock]; 65 | OCMExpect([partialMock commonInit]); 66 | } 67 | 68 | #pragma mark - Object Lifecycle - Tests 69 | 70 | - (void)test___init__calls_commonInit { 71 | 72 | // given 73 | [self givenExpectWillCallCommonInit]; 74 | 75 | // when 76 | sut = [sut init]; 77 | 78 | // then 79 | OCMVerifyAll(partialMock); 80 | } 81 | 82 | - (void)test___initWithFrame___calls_commonInit { 83 | 84 | // given 85 | [self givenExpectWillCallCommonInit]; 86 | 87 | // when 88 | sut = [sut initWithFrame:CGRectZero]; 89 | 90 | // then 91 | OCMVerifyAll(partialMock); 92 | } 93 | 94 | - (void)test___initWithCoder___calls_commonInit { 95 | 96 | // given 97 | NSCoder *coder = nil; 98 | [self givenExpectWillCallCommonInit]; 99 | 100 | // when 101 | sut = [sut initWithCoder:coder]; 102 | 103 | // then 104 | OCMVerifyAll(partialMock); 105 | } 106 | 107 | - (void)test___commonInit___calls_configureNavigationBar { 108 | 109 | // given 110 | sut = [sut init]; 111 | OCMExpect([partialMock configureToolbar:sut]); 112 | 113 | // when 114 | [sut commonInit]; 115 | 116 | // then 117 | OCMVerifyAll(partialMock); 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseNavigationBarTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseNavigationBarTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 11/21/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // System Under Test 27 | #import "BaseNavigationBar.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | #import 34 | 35 | @interface BaseNavigationBarTests : XCTestCase 36 | @end 37 | 38 | @implementation BaseNavigationBarTests { 39 | 40 | BaseNavigationBar *sut; 41 | 42 | id partialMock; 43 | } 44 | 45 | #pragma mark - Test Lifecycle 46 | 47 | - (void)setUp { 48 | [super setUp]; 49 | sut = [BaseNavigationBar alloc]; 50 | } 51 | 52 | - (void)tearDown { 53 | [partialMock stopMocking]; 54 | [super tearDown]; 55 | } 56 | 57 | #pragma mark - Given 58 | 59 | - (void)givenPartialMock { 60 | partialMock = OCMPartialMock(sut); 61 | } 62 | 63 | - (void)givenExpectWillCallCommonInit { 64 | [self givenPartialMock]; 65 | OCMExpect([partialMock commonInit]); 66 | } 67 | 68 | #pragma mark - Object Lifecycle - Tests 69 | 70 | - (void)test___init__calls_commonInit { 71 | 72 | // given 73 | [self givenExpectWillCallCommonInit]; 74 | 75 | // when 76 | sut = [sut init]; 77 | 78 | // then 79 | OCMVerifyAll(partialMock); 80 | } 81 | 82 | - (void)test___initWithFrame___calls_commonInit { 83 | 84 | // given 85 | [self givenExpectWillCallCommonInit]; 86 | 87 | // when 88 | sut = [sut initWithFrame:CGRectZero]; 89 | 90 | // then 91 | OCMVerifyAll(partialMock); 92 | } 93 | 94 | - (void)test___initWithCoder___calls_commonInit { 95 | 96 | // given 97 | NSCoder *coder = nil; 98 | [self givenExpectWillCallCommonInit]; 99 | 100 | // when 101 | sut = [sut initWithCoder:coder]; 102 | 103 | // then 104 | OCMVerifyAll(partialMock); 105 | } 106 | 107 | - (void)test___commonInit___calls_configureNavigationBar { 108 | 109 | // given 110 | sut = [sut init]; 111 | OCMExpect([partialMock configureNavigationBar:sut]); 112 | 113 | // when 114 | [sut commonInit]; 115 | 116 | // then 117 | OCMVerifyAll(partialMock); 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/DynamicFontTableContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableContainerViewController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/4/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseViewController.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `DynamicFontTableContainerViewController` is a subclass of `BaseViewController` that provides support for dynamic font types. 32 | * 33 | * @discussion This is an abstract, base controller meant to be subclassed instead of `UIViewController`. In addition to the benefits gained by using `BaseViewController` (see said class header for more details), this class provides support for dynamic font types via its `refreshViews` method. You should override this method in your custom subclass in order to reset fonts, etc based on the user's preferred font size. 34 | * 35 | * The difference between `DynamicFontTableContainerViewController` and `DynamicFontViewController` is this controller is expected to have a `tableView` has a subview. This is signifiant due to the way responding to font change notifications works- it's dispatched to the main queue to give other views (e.g. table view cells) a chance to update their subviews first before the table view is reloaded. 36 | */ 37 | @interface DynamicFontTableContainerViewController : BaseViewController 38 | 39 | #pragma mark - Outlets 40 | 41 | /** 42 | * @brief The table view 43 | */ 44 | @property (nonatomic, weak) IBOutlet UITableView *tableView; 45 | 46 | #pragma mark - Dynamic Font Type 47 | 48 | /** 49 | * @brief Override this method to refresh views (e.g. set fonts on labels, text views, etc). 50 | * 51 | * @discussion This message is called on the main thread. 52 | * 53 | * Prior to this method, `[self.tableView reloadData]` is called. 54 | */ 55 | - (void)refreshViews; 56 | 57 | @end 58 | 59 | @interface DynamicFontTableContainerViewController (Protected) 60 | 61 | /** 62 | * @brief This method is called in response to receiving `UIContentSizeCategoryDidChangeNotification`. 63 | * 64 | * @discussion In general, you should *not* need to override this method. Instead, you should override `refreshViews`. 65 | * 66 | * @param notification The `UIContentSizeCategoryDidChangeNotification` notification 67 | */ 68 | - (void)contentSizeCategoryDidChange:(NSNotification *)notification; 69 | 70 | @end 71 | 72 | NS_ASSUME_NONNULL_END 73 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/UIViewController+BetterBaseClasses.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BetterBaseClasses.m 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "UIViewController+BetterBaseClasses.h" 27 | 28 | static NSBundle *BBC_bundle = nil; 29 | static BOOL BBC_preferStoryboards = NO; 30 | 31 | @implementation UIViewController (BetterBaseClasses) 32 | 33 | #pragma mark - Identifiers 34 | 35 | + (NSBundle *)bundle { 36 | 37 | if (!BBC_bundle) { 38 | return [NSBundle bundleForClass:[self class]]; 39 | } 40 | 41 | return BBC_bundle; 42 | } 43 | 44 | + (void)setBundle:(NSBundle *)bundle { 45 | BBC_bundle = bundle; 46 | } 47 | 48 | + (NSString *)identifier { 49 | 50 | NSString *identifier = NSStringFromClass([self class]); 51 | return identifier.pathExtension.length > 0 ? identifier.pathExtension : identifier; 52 | } 53 | 54 | + (NSString *)navigationControllerIdentifier { 55 | return [[self identifier] stringByAppendingString:@"NavigationController"]; 56 | } 57 | 58 | + (UIStoryboard *)storyboard { 59 | 60 | NSBundle *bundle = [self bundle]; 61 | NSString *name = [self storyboardName]; 62 | return [UIStoryboard storyboardWithName:name bundle:bundle]; 63 | } 64 | 65 | + (NSString *)storyboardName { 66 | return @"Main"; 67 | } 68 | 69 | #pragma mark - Instantiation 70 | 71 | + (instancetype)instanceFromNib { 72 | 73 | NSBundle *bundle = [[self class] bundle]; 74 | NSString *nibName = [[self class] identifier]; 75 | return [[self alloc] initWithNibName:nibName bundle:bundle]; 76 | } 77 | 78 | + (instancetype)instanceFromStoryboard { 79 | 80 | NSString *identifier = [[self class] identifier]; 81 | UIStoryboard *storyboard = [[self class] storyboard]; 82 | return [storyboard instantiateViewControllerWithIdentifier:identifier]; 83 | } 84 | 85 | + (UINavigationController *)navigationControllerInstanceFromStoryboard { 86 | 87 | NSString *identifier = [[self class] navigationControllerIdentifier]; 88 | UIStoryboard *storyboard = [[self class] storyboard]; 89 | return [storyboard instantiateViewControllerWithIdentifier:identifier]; 90 | } 91 | 92 | #pragma mark - Preferred Instance 93 | 94 | + (instancetype)preferredInstance { 95 | return [self preferStoryboards] ? [self instanceFromStoryboard] : [self instanceFromNib]; 96 | } 97 | 98 | + (void)setPreferStoryboards:(BOOL)preferStoryboards { 99 | BBC_preferStoryboards = preferStoryboards; 100 | } 101 | 102 | + (BOOL)preferStoryboards { 103 | return BBC_preferStoryboards; 104 | } 105 | 106 | #pragma mark - Object Lifecycle 107 | 108 | - (void)commonInit { 109 | // This method is meant to be overriden by subclasses. 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseNavigationController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/23/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseNavigationController.h" 27 | #import "UIViewController+BetterBaseClasses.h" 28 | 29 | @implementation BaseNavigationController 30 | 31 | #pragma mark - Object Lifecycle 32 | 33 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 34 | self = [super initWithCoder:aDecoder]; 35 | if (!self) { 36 | return nil; 37 | } 38 | [self commonInit]; 39 | return self; 40 | } 41 | 42 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 43 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 44 | if (!self) { 45 | return nil; 46 | } 47 | [self commonInit]; 48 | return self; 49 | } 50 | 51 | - (instancetype)initWithRootViewController:(UIViewController *)rootViewController { 52 | self = [super initWithRootViewController:rootViewController]; 53 | if (!self) { 54 | return nil; 55 | } 56 | [self commonInit]; 57 | return self; 58 | } 59 | 60 | - (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass { 61 | self = [super initWithNavigationBarClass:navigationBarClass toolbarClass:toolbarClass]; 62 | if (!self) { 63 | return nil; 64 | } 65 | [self commonInit]; 66 | return self; 67 | } 68 | 69 | #pragma mark - View Lifecycle 70 | 71 | - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { 72 | 73 | UIViewController *viewController = self.visibleViewController; 74 | return viewController != nil ? [viewController preferredInterfaceOrientationForPresentation] : 75 | [super preferredInterfaceOrientationForPresentation]; 76 | } 77 | 78 | - (UIStatusBarStyle)preferredStatusBarStyle { 79 | UIViewController *viewController = self.visibleViewController; 80 | return viewController != nil ? [viewController preferredStatusBarStyle] : [super preferredStatusBarStyle]; 81 | } 82 | 83 | - (BOOL)shouldAutorotate { 84 | 85 | UIViewController *viewController = self.visibleViewController; 86 | return viewController != nil ? [viewController shouldAutorotate] : [super shouldAutorotate]; 87 | } 88 | 89 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations { 90 | 91 | UIViewController *viewController = self.visibleViewController; 92 | return viewController != nil ? [viewController supportedInterfaceOrientations] : [super supportedInterfaceOrientations]; 93 | } 94 | 95 | - (void)viewDidLoad { 96 | [super viewDidLoad]; 97 | [self configureNavigationBar:self.navigationBar]; 98 | } 99 | 100 | - (void)configureNavigationBar:(UINavigationBar *)navigationBar { 101 | // This method is meant to be overriden by subclasses. 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/DynamicFontViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontViewControllerTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "DynamicFontViewController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import "BaseTestCase.h" 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface DynamicFontViewControllerTests : BaseTestCase 40 | @end 41 | 42 | @implementation DynamicFontViewControllerTests { 43 | 44 | DynamicFontViewController *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | 53 | [super setUp]; 54 | 55 | sut = [[DynamicFontViewController alloc] init]; 56 | } 57 | 58 | - (void)tearDown { 59 | 60 | [partialMock stopMocking]; 61 | [super tearDown]; 62 | } 63 | 64 | #pragma mark - Given 65 | 66 | - (void)givenPartialMock { 67 | partialMock = OCMPartialMock(sut); 68 | } 69 | 70 | #pragma mark - View Lifecycle - Tests 71 | 72 | - (void)test___viewDidLoad__registerFor_UIContentSizeCategoryDidChangeNotification { 73 | 74 | // given 75 | [self givenMockNotificationCenter]; 76 | OCMExpect([notificationCenter addObserver:sut 77 | selector:@selector(contentSizeCategoryDidChange:) 78 | name:UIContentSizeCategoryDidChangeNotification 79 | object:nil]); 80 | 81 | // when 82 | [sut viewDidLoad]; 83 | 84 | // then 85 | OCMVerifyAll(notificationCenter); 86 | } 87 | 88 | #pragma mark - Dynamic Font Type - Tests 89 | 90 | - (void)test___contentSizeCategoryDidChange___calls_refreshViews { 91 | 92 | // given 93 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 94 | 95 | [self givenPartialMock]; 96 | OCMExpect([partialMock refreshViews]); 97 | 98 | // when 99 | [sut contentSizeCategoryDidChange:notification]; 100 | 101 | // then 102 | OCMVerifyAllWithDelay(partialMock, 0.01); 103 | } 104 | 105 | - (void)test___contentSizeCategoryDidChange___givenIsNotMainThread_calls_performSelectorOnMainThread { 106 | 107 | // given 108 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 109 | 110 | [self givenMockThreadWillReturnIsMainThread:NO]; 111 | [self givenPartialMock]; 112 | OCMExpect([partialMock performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 113 | withObject:notification 114 | waitUntilDone:NO]); 115 | 116 | // when 117 | [sut contentSizeCategoryDidChange:notification]; 118 | 119 | // then 120 | OCMVerifyAll(partialMock); 121 | } 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/DynamicFontTableViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableViewControllerTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "DynamicFontTableViewController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import "BaseTestCase.h" 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface DynamicFontTableViewControllerTests : BaseTestCase 40 | @end 41 | 42 | @implementation DynamicFontTableViewControllerTests { 43 | 44 | DynamicFontTableViewController *sut; 45 | 46 | id partialMock; 47 | id tableView; 48 | } 49 | 50 | #pragma mark - Test Lifecycle 51 | 52 | - (void)setUp { 53 | 54 | [super setUp]; 55 | 56 | sut = [[DynamicFontTableViewController alloc] init]; 57 | } 58 | 59 | - (void)tearDown { 60 | 61 | [partialMock stopMocking]; 62 | [tableView stopMocking]; 63 | 64 | [super tearDown]; 65 | } 66 | 67 | #pragma mark - Given 68 | 69 | - (void)givenPartialMockWillReturnMockTableView { 70 | 71 | [self givenPartialMock]; 72 | 73 | tableView = OCMClassMock([UITableView class]); 74 | OCMStub([partialMock tableView]).andReturn(tableView); 75 | } 76 | 77 | - (void)givenPartialMock { 78 | partialMock = OCMPartialMock(sut); 79 | } 80 | 81 | #pragma mark - View Lifecycle - Tests 82 | 83 | - (void)test___viewDidLoad__registerFor_UIContentSizeCategoryDidChangeNotification { 84 | 85 | // given 86 | [self givenMockNotificationCenter]; 87 | OCMExpect([notificationCenter addObserver:sut 88 | selector:@selector(contentSizeCategoryDidChange:) 89 | name:UIContentSizeCategoryDidChangeNotification 90 | object:nil]); 91 | 92 | // when 93 | [sut viewDidLoad]; 94 | 95 | // then 96 | OCMVerifyAll(notificationCenter); 97 | } 98 | 99 | #pragma mark - Dynamic Font Type - Tests 100 | 101 | - (void)test___contentSizeCategoryDidChange___calls_tableView_reloadData { 102 | 103 | // given 104 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 105 | 106 | [self givenPartialMockWillReturnMockTableView]; 107 | OCMExpect([tableView reloadData]); 108 | 109 | // when 110 | [sut contentSizeCategoryDidChange:notification]; 111 | 112 | // then 113 | OCMVerifyAllWithDelay(tableView, 0.01); 114 | } 115 | 116 | - (void)test___contentSizeCategoryDidChange___calls_refreshViews { 117 | 118 | // given 119 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 120 | 121 | [self givenPartialMock]; 122 | OCMExpect([partialMock refreshViews]); 123 | 124 | // when 125 | [sut contentSizeCategoryDidChange:notification]; 126 | 127 | // then 128 | OCMVerifyAllWithDelay(partialMock, 0.01); 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/DynamicFontTableContainerViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableContainerViewControllerTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/4/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "DynamicFontTableContainerViewController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import "BaseTestCase.h" 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface DynamicFontTableContainerViewControllerTests : BaseTestCase 40 | @end 41 | 42 | @implementation DynamicFontTableContainerViewControllerTests { 43 | 44 | DynamicFontTableContainerViewController *sut; 45 | 46 | id partialMock; 47 | id tableView; 48 | } 49 | 50 | #pragma mark - Test Lifecycle 51 | 52 | - (void)setUp { 53 | 54 | [super setUp]; 55 | 56 | sut = [[DynamicFontTableContainerViewController alloc] init]; 57 | } 58 | 59 | - (void)tearDown { 60 | 61 | [partialMock stopMocking]; 62 | [tableView stopMocking]; 63 | 64 | [super tearDown]; 65 | } 66 | 67 | #pragma mark - Given 68 | 69 | - (void)givenPartialMockWillReturnMockTableView { 70 | 71 | [self givenPartialMock]; 72 | 73 | tableView = OCMClassMock([UITableView class]); 74 | OCMStub([partialMock tableView]).andReturn(tableView); 75 | } 76 | 77 | - (void)givenPartialMock { 78 | partialMock = OCMPartialMock(sut); 79 | } 80 | 81 | #pragma mark - View Lifecycle - Tests 82 | 83 | - (void)test___viewDidLoad__registerFor_UIContentSizeCategoryDidChangeNotification { 84 | 85 | // given 86 | [self givenMockNotificationCenter]; 87 | OCMExpect([notificationCenter addObserver:sut 88 | selector:@selector(contentSizeCategoryDidChange:) 89 | name:UIContentSizeCategoryDidChangeNotification 90 | object:nil]); 91 | 92 | // when 93 | [sut viewDidLoad]; 94 | 95 | // then 96 | OCMVerifyAll(notificationCenter); 97 | } 98 | 99 | #pragma mark - Dynamic Font Type - Tests 100 | 101 | - (void)test___contentSizeCategoryDidChange___calls_tableView_reloadData { 102 | 103 | // given 104 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 105 | 106 | [self givenPartialMockWillReturnMockTableView]; 107 | OCMExpect([tableView reloadData]); 108 | 109 | // when 110 | [sut contentSizeCategoryDidChange:notification]; 111 | 112 | // then 113 | OCMVerifyAllWithDelay(tableView, 0.01); 114 | } 115 | 116 | - (void)test___contentSizeCategoryDidChange___calls_refreshViews { 117 | 118 | // given 119 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 120 | 121 | [self givenPartialMock]; 122 | OCMExpect([partialMock refreshViews]); 123 | 124 | // when 125 | [sut contentSizeCategoryDidChange:notification]; 126 | 127 | // then 128 | OCMVerifyAllWithDelay(partialMock, 0.01); 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseAppDelegateTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAppDelegateTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 4/16/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseAppDelegate.h" 28 | 29 | // Collaborators 30 | #import "AppDelegateNotificationKeys.h" 31 | 32 | // Test Support 33 | #import "BaseTestCase.h" 34 | 35 | #define EXP_SHORTHAND YES 36 | #import 37 | 38 | #import 39 | 40 | @interface BaseAppDelegateTests : BaseTestCase 41 | @end 42 | 43 | @implementation BaseAppDelegateTests { 44 | 45 | BaseAppDelegate *sut; 46 | } 47 | 48 | #pragma mark - Test Lifecycle 49 | 50 | - (void)setUp { 51 | [super setUp]; 52 | 53 | sut = [[BaseAppDelegate alloc] init]; 54 | } 55 | 56 | - (void)tearDown { 57 | 58 | [notificationCenter stopMocking]; 59 | [super tearDown]; 60 | } 61 | 62 | #pragma mark - Notifications - Tests 63 | 64 | - (void)test___application_didRegisterUserNotificationSettings___postsNotification { 65 | 66 | // given 67 | UIApplication *application = nil; 68 | UIUserNotificationSettings *notificationSetting = [UIUserNotificationSettings 69 | settingsForTypes:UIUserNotificationTypeAlert 70 | categories:nil]; 71 | 72 | [self givenMockNotificationCenter]; 73 | OCMExpect([notificationCenter postNotificationName:ApplicationDidRegisterForUserNotificationSettingsNotification 74 | object:notificationSetting]); 75 | 76 | // when 77 | [sut application:application didRegisterUserNotificationSettings:notificationSetting]; 78 | 79 | // then 80 | OCMVerifyAll(notificationCenter); 81 | } 82 | 83 | - (void)test___application_didRegisterForRemoteNotificationsWithDeviceToken___postsNotification { 84 | 85 | // given 86 | UIApplication *application = nil; 87 | NSData *data = [NSData data]; 88 | 89 | [self givenMockNotificationCenter]; 90 | OCMExpect([notificationCenter postNotificationName:ApplicationDidRegisterForRemoteNotificationsNotification 91 | object:data]); 92 | 93 | // when 94 | [sut application:application didRegisterForRemoteNotificationsWithDeviceToken:data]; 95 | 96 | // then 97 | OCMVerifyAll(notificationCenter); 98 | } 99 | 100 | - (void)test___application_didReceiveLocalNotification___postsNotification { 101 | 102 | // given 103 | UIApplication *application = nil; 104 | UILocalNotification *notification = [[UILocalNotification alloc] init]; 105 | 106 | [self givenMockNotificationCenter]; 107 | OCMExpect([notificationCenter postNotificationName:ApplicationDidReceiveLocalNotification 108 | object:notification]); 109 | 110 | // when 111 | [sut application:application didReceiveLocalNotification:notification]; 112 | 113 | // then 114 | OCMVerifyAll(notificationCenter); 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Views/UIView+BetterBaseClasses.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+BetterBaseClasses.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/25/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `UIView+BetterBaseClasses` adds class convenience methods to instantiate a view defined by `bundle` and `nibName` values. 32 | * 33 | * @discussion You should use this category in combination with subclassing either `BaseView` or `BaseTableViewCell`. 34 | */ 35 | @interface UIView (BetterBaseClasses) 36 | 37 | #pragma mark - Identifiers 38 | 39 | /** 40 | * @brief Use this method to get the bundle for the view. 41 | * 42 | * @discussion If you don't set the bundle via `setBundle:`, or override this method in a subclass, the bundle 43 | * defaults to the bundle for the view's class. 44 | * 45 | * If your view controller and its corresponding view are in the same bundle, this is 46 | * likely the correct behavior. However, if needed, you can optionally override this 47 | * method in a subclass. 48 | * 49 | * @return The share conference info bundle 50 | */ 51 | + (nullable NSBundle *)bundle; 52 | 53 | /** 54 | * @brief Use this method to set the bundle for the view. 55 | * 56 | * @discussion This method is useful, for example, in unit testing. 57 | * 58 | * @param bundle The bundle to set for the view 59 | */ 60 | + (void)setBundle:(nullable NSBundle *)bundle; 61 | 62 | /** 63 | * @brief This method returns the nib name associated with the view. 64 | * 65 | * @discussion This method returns the name of the view by default. 66 | * 67 | * @return The nib name 68 | */ 69 | + (NSString *)nibName; 70 | 71 | #pragma mark - Instantiation 72 | 73 | /** 74 | * @brief Use this method to get a view instantiated from the nib called `nibName` in the given `bundle`. 75 | * 76 | * @return A new instance of this view 77 | */ 78 | + (instancetype)instanceFromNib; 79 | 80 | /** 81 | * @brief Use this method to get the nib associated with the view. 82 | * 83 | * @discussion This method returns the nib with the `nibName` in the `bundle` by default. 84 | * 85 | * @return The nib associated with the view 86 | */ 87 | + (UINib *)nib; 88 | 89 | #pragma mark - Object Lifecycle 90 | 91 | /** 92 | * @brief Use this method to perform common initialization, regardless of the designiated initializer used to create the view. 93 | * 94 | * @discussion This class leaves it up to subclasses to actually call this method from all designated intializers. If you subclass `BaseView`, `BaseTableViewCell`, or any subclasses thereof, this has alredy been done for you with the default initializers. 95 | * 96 | * @note If you introduce a new designated initializer in your subclass of said classes, you should make sure to call `commonInit` with it. 97 | */ 98 | - (void)commonInit __attribute((objc_requires_super)); 99 | 100 | @end 101 | 102 | NS_ASSUME_NONNULL_END 103 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/DynamicFontViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontViewTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "DynamicFontView.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import "BaseTestCase.h" 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface DynamicFontViewTests : BaseTestCase 40 | @end 41 | 42 | @implementation DynamicFontViewTests { 43 | 44 | DynamicFontView *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | 53 | [super setUp]; 54 | sut = [[DynamicFontView alloc] init]; 55 | } 56 | 57 | - (void)tearDown { 58 | 59 | [partialMock stopMocking]; 60 | [super tearDown]; 61 | } 62 | 63 | #pragma mark - Given 64 | 65 | - (void)givenPartialMock { 66 | partialMock = OCMPartialMock(sut); 67 | } 68 | 69 | #pragma mark - Object Lifecycle - Tests 70 | 71 | - (void)test___commonInit__registersFor_UIContentSizeCategoryDidChangeNotification { 72 | 73 | // given 74 | sut = [DynamicFontView alloc]; 75 | 76 | [self givenMockNotificationCenter]; 77 | OCMExpect([notificationCenter addObserver:sut selector:@selector(contentSizeCategoryDidChange:) name:UIContentSizeCategoryDidChangeNotification object:nil]); 78 | 79 | // when 80 | sut = [sut init]; 81 | 82 | // then 83 | OCMVerifyAll(notificationCenter); 84 | } 85 | 86 | - (void)test___dealloc___removes_notificationCenterObserver { 87 | 88 | // given 89 | __weak DynamicFontView *object = nil; 90 | 91 | // When 92 | @autoreleasepool { 93 | id silenceWarning = [[DynamicFontView alloc] init]; 94 | object = silenceWarning; 95 | } 96 | 97 | // then 98 | expect(object).to.beNil(); // doesn't crash, so must have removed observer ;) 99 | } 100 | 101 | #pragma mark - Dynamic Font Type - Tests 102 | 103 | - (void)test___contentSizeCategoryDidChange___ifIsMainThread_calls_refreshView { 104 | 105 | // given 106 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 107 | 108 | [self givenMockThreadWillReturnIsMainThread:YES]; 109 | [self givenPartialMock]; 110 | OCMExpect([partialMock refreshView]); 111 | 112 | // when 113 | [sut contentSizeCategoryDidChange:notification]; 114 | 115 | // then 116 | OCMVerifyAll(partialMock); 117 | } 118 | 119 | - (void)test___contentSizeCategoryDidChange___givenIsNotMainThread_calls_performSelectorOnMainThread { 120 | 121 | // given 122 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 123 | 124 | [self givenMockThreadWillReturnIsMainThread:NO]; 125 | [self givenPartialMock]; 126 | OCMExpect([partialMock performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 127 | withObject:notification 128 | waitUntilDone:NO]); 129 | 130 | // when 131 | [sut contentSizeCategoryDidChange:notification]; 132 | 133 | // then 134 | OCMVerifyAll(partialMock); 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/DynamicFontTableViewCellTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicFontTableViewCellTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 3/2/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "DynamicFontTableViewCell.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import "BaseTestCase.h" 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface DynamicFontTableViewCellTests : BaseTestCase 40 | @end 41 | 42 | @implementation DynamicFontTableViewCellTests { 43 | 44 | DynamicFontTableViewCell *sut; 45 | 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | 53 | [super setUp]; 54 | sut = [[DynamicFontTableViewCell alloc] init]; 55 | } 56 | 57 | - (void)tearDown { 58 | 59 | [partialMock stopMocking]; 60 | [super tearDown]; 61 | } 62 | 63 | #pragma mark - Given 64 | 65 | - (void)givenPartialMock { 66 | partialMock = OCMPartialMock(sut); 67 | } 68 | 69 | #pragma mark - Object Lifecycle - Tests 70 | 71 | - (void)test___commonInit__registersFor_UIContentSizeCategoryDidChangeNotification { 72 | 73 | // given 74 | sut = [DynamicFontTableViewCell alloc]; 75 | 76 | [self givenMockNotificationCenter]; 77 | OCMExpect([notificationCenter addObserver:sut selector:@selector(contentSizeCategoryDidChange:) name:UIContentSizeCategoryDidChangeNotification object:nil]); 78 | 79 | // when 80 | sut = [sut init]; 81 | 82 | // then 83 | OCMVerifyAll(notificationCenter); 84 | } 85 | 86 | - (void)test___dealloc___removes_notificationCenterObserver { 87 | 88 | // given 89 | __weak DynamicFontTableViewCell *object = nil; 90 | 91 | // when 92 | @autoreleasepool { 93 | id silenceWarning = [[DynamicFontTableViewCell alloc] init]; 94 | object = silenceWarning; 95 | } 96 | 97 | // then 98 | expect(object).to.beNil(); // doesn't crash, so must have removed observer ;) 99 | } 100 | 101 | #pragma mark - Dynamic Font Type - Tests 102 | 103 | - (void)test___contentSizeCategoryDidChange___ifIsMainThread_calls_refreshView { 104 | 105 | // given 106 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 107 | 108 | [self givenMockThreadWillReturnIsMainThread:YES]; 109 | [self givenPartialMock]; 110 | OCMExpect([partialMock refreshView]); 111 | 112 | // when 113 | [sut contentSizeCategoryDidChange:notification]; 114 | 115 | // then 116 | OCMVerifyAll(partialMock); 117 | } 118 | 119 | - (void)test___contentSizeCategoryDidChange___ifIsNotMainThread_calls_performSelectorOnMainThread { 120 | 121 | // given 122 | NSNotification *notification = [NSNotification notificationWithName:@"" object:nil]; 123 | 124 | [self givenMockThreadWillReturnIsMainThread:NO]; 125 | [self givenPartialMock]; 126 | OCMExpect([partialMock performSelectorOnMainThread:@selector(contentSizeCategoryDidChange:) 127 | withObject:notification 128 | waitUntilDone:NO]); 129 | 130 | // when 131 | [sut contentSizeCategoryDidChange:notification]; 132 | 133 | // then 134 | OCMVerifyAll(partialMock); 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/UIView+BetterBaseClassesTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+BetterBaseClassesTests.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 2/25/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | 27 | // Test Class 28 | #import "UIView+BetterBaseClasses.h" 29 | 30 | // Collaborators 31 | 32 | // Test Support 33 | #import 34 | 35 | #define EXP_SHORTHAND YES 36 | #import 37 | 38 | #import 39 | 40 | @interface UIView_BetterBaseClassesTests : XCTestCase 41 | @end 42 | 43 | @implementation UIView_BetterBaseClassesTests { 44 | 45 | id mockBundle; 46 | id mockSutClass; 47 | id mockNibClass; 48 | } 49 | 50 | #pragma mark - Test Lifecycle 51 | 52 | - (void)tearDown { 53 | 54 | [mockBundle stopMocking]; 55 | [mockSutClass stopMocking]; 56 | [mockNibClass stopMocking]; 57 | [super tearDown]; 58 | } 59 | 60 | #pragma mark - Given 61 | 62 | - (void)givenMockBundle { 63 | mockBundle = OCMClassMock([NSBundle class]); 64 | } 65 | 66 | - (void)givenMockNibClass { 67 | mockNibClass = OCMClassMock([UINib class]); 68 | } 69 | 70 | - (void)givenMockSutClass { 71 | mockSutClass = OCMClassMock([UIView class]); 72 | } 73 | 74 | #pragma mark - Identifiers - Tests 75 | 76 | - (void)test___bundle___returns_bundleForClass { 77 | 78 | // given 79 | NSBundle *expected = [NSBundle bundleForClass:[self class]]; 80 | [self givenMockBundle]; 81 | OCMExpect([mockBundle bundleForClass:OCMOCK_ANY]).andReturn(expected); 82 | 83 | // when 84 | NSBundle *actual = [UIView bundle]; 85 | 86 | // then 87 | expect(actual).to.equal(expected); 88 | } 89 | 90 | - (void)test___setBundle___afterSettingBundle_bundle_returnsSetBundle { 91 | 92 | // given 93 | [self givenMockBundle]; 94 | NSBundle *expected = mockBundle; 95 | 96 | // when 97 | [UIView setBundle:mockBundle]; 98 | NSBundle *actual = [UIView bundle]; 99 | 100 | // then 101 | XCTAssertEqual(actual, expected); 102 | 103 | // clean up 104 | [UIView setBundle:nil]; 105 | } 106 | 107 | - (void)test___identifier___ifClassNameDoesntHavePathExtension_returnsClassName { 108 | 109 | // given 110 | NSString *expected = @"UIView"; 111 | 112 | // when 113 | NSString *actual = [UIView nibName]; 114 | 115 | // then 116 | expect(actual).to.equal(expected); 117 | } 118 | 119 | - (void)test___identifier___ifClassNameHasPathExtension_returnsClassPathExtension { 120 | 121 | // TO-DO: Figure out an easy way to test this... 122 | } 123 | 124 | #pragma mark - Instantiation - Tests 125 | 126 | - (void)test___instanceFromNib___instantiatesViewFromNib { 127 | 128 | // given 129 | UIView *expected = [UIView new]; 130 | NSArray *objects = @[expected]; 131 | 132 | [self givenMockSutClass]; 133 | [self givenMockNibClass]; 134 | OCMStub([mockSutClass nib]).andReturn(mockNibClass); 135 | OCMStub([mockNibClass instantiateWithOwner:nil options:nil]).andReturn(objects); 136 | 137 | // when 138 | UIView *actual = [UIView instanceFromNib]; 139 | 140 | // then 141 | expect(actual).to.equal(expected); 142 | } 143 | 144 | - (void)test___nib___returnsNibWithNibNameAndBundle { 145 | 146 | // given 147 | NSString *nibName = [UIView nibName]; 148 | NSBundle *bundle = [UIView bundle]; 149 | 150 | UINib *expected = [UINib new]; 151 | 152 | [self givenMockNibClass]; 153 | OCMStub([mockNibClass nibWithNibName:nibName bundle:bundle]).andReturn(expected); 154 | 155 | // when 156 | UINib *actual = [UIView nib]; 157 | 158 | // then 159 | expect(actual).to.equal(expected); 160 | } 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseTabBarControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTabBarController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/23/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseTabBarController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface BaseTabBarControllerTests : XCTestCase 40 | @end 41 | 42 | @implementation BaseTabBarControllerTests { 43 | BaseTabBarController *sut; 44 | 45 | id viewController; 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | [super setUp]; 53 | sut = [[BaseTabBarController alloc] init]; 54 | } 55 | 56 | - (void)tearDown { 57 | 58 | [partialMock stopMocking]; 59 | [super tearDown]; 60 | } 61 | 62 | #pragma mark - Given 63 | 64 | - (void)givenExpectCommonInitToBeCalled { 65 | sut = [BaseTabBarController alloc]; 66 | 67 | [self givenPartialMock]; 68 | OCMExpect([partialMock commonInit]); 69 | } 70 | 71 | - (void)givenMockSelectedViewController { 72 | viewController = OCMClassMock([UIViewController class]); 73 | 74 | [self givenPartialMock]; 75 | OCMStub([partialMock selectedViewController]).andReturn(viewController); 76 | } 77 | 78 | - (void)givenPartialMock { 79 | [partialMock stopMocking]; // in case it's already set 80 | partialMock = OCMPartialMock(sut); 81 | } 82 | 83 | #pragma mark - Object Lifecycle - Tests 84 | 85 | - (void)test___init___calls_commonInit { 86 | 87 | // given 88 | [self givenExpectCommonInitToBeCalled]; 89 | 90 | // when 91 | sut = [sut init]; 92 | 93 | // then 94 | OCMVerifyAll(partialMock); 95 | } 96 | 97 | - (void)test___initWithCoder___calls_commonInit { 98 | 99 | // given 100 | [self givenExpectCommonInitToBeCalled]; 101 | 102 | NSCoder *coder = nil; 103 | 104 | // when 105 | sut = [sut initWithCoder:coder]; 106 | 107 | // then 108 | OCMVerifyAll(partialMock); 109 | } 110 | 111 | - (void)test___initWithNibName_bundle___calls_commonInit { 112 | 113 | // given 114 | [self givenExpectCommonInitToBeCalled]; 115 | 116 | // when 117 | sut = [sut initWithNibName:nil bundle:nil]; 118 | 119 | // then 120 | OCMVerifyAll(partialMock); 121 | } 122 | 123 | #pragma mark - View Lifecycle - Tests 124 | 125 | - (void)test___preferredInterfaceOrientationForPresentation___givenSelectedViewController_returns_viewController_preferredInterfaceOrientationForPresentation { 126 | 127 | // given 128 | UIInterfaceOrientation expected = UIInterfaceOrientationLandscapeLeft; 129 | [self givenMockSelectedViewController]; 130 | OCMStub([viewController preferredInterfaceOrientationForPresentation]).andReturn(expected); 131 | 132 | // when 133 | UIInterfaceOrientation actual = [sut preferredInterfaceOrientationForPresentation]; 134 | 135 | // then 136 | expect(actual).to.equal(expected); 137 | } 138 | 139 | - (void)test___preferredStatusBarStyle___givenSelectedViewController_returns_viewController_preferredStatusBarStyle { 140 | 141 | // given 142 | UIStatusBarStyle expected = UIStatusBarStyleLightContent; 143 | [self givenMockSelectedViewController]; 144 | OCMStub([viewController preferredStatusBarStyle]).andReturn(expected); 145 | 146 | // when 147 | UIStatusBarStyle actual = [sut preferredStatusBarStyle]; 148 | 149 | // then 150 | expect(actual).to.equal(expected); 151 | } 152 | 153 | - (void)test___shouldAutorotate___givenSelectedViewController_returns_viewController_shouldAutorotate { 154 | 155 | // given 156 | BOOL expected = false; 157 | [self givenMockSelectedViewController]; 158 | OCMStub([viewController shouldAutorotate]).andReturn(expected); 159 | 160 | // when 161 | BOOL actual = [sut shouldAutorotate]; 162 | 163 | // then 164 | expect(actual).to.equal(expected); 165 | } 166 | 167 | - (void)test___supportedInterfaceOrientations___givenSelectedViewController_returns_viewController_supportedInterfaceOrientations { 168 | 169 | // given 170 | UIInterfaceOrientationMask expected = UIInterfaceOrientationMaskLandscapeRight; 171 | [self givenMockSelectedViewController]; 172 | OCMStub([viewController supportedInterfaceOrientations]).andReturn(expected); 173 | 174 | // when 175 | UIInterfaceOrientationMask actual = [sut supportedInterfaceOrientations]; 176 | 177 | // then 178 | expect(actual).to.equal(expected); 179 | } 180 | 181 | - (void)test___viewDidLoad___calls_configureTabBar { 182 | 183 | // given 184 | UITabBar *tabBar = sut.tabBar; 185 | [self givenPartialMock]; 186 | OCMExpect([partialMock configureTabBar:tabBar]); 187 | 188 | // when 189 | [sut viewDidLoad]; 190 | 191 | // then 192 | OCMVerify(partialMock); 193 | } 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/BaseNavigationControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTabBarController.m 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/23/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "BaseNavigationController.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface BaseNavigationControllerTests : XCTestCase 40 | @end 41 | 42 | @implementation BaseNavigationControllerTests { 43 | BaseNavigationController *sut; 44 | 45 | id viewController; 46 | id partialMock; 47 | } 48 | 49 | #pragma mark - Test Lifecycle 50 | 51 | - (void)setUp { 52 | [super setUp]; 53 | sut = [[BaseNavigationController alloc] init]; 54 | } 55 | 56 | - (void)tearDown { 57 | 58 | [partialMock stopMocking]; 59 | [super tearDown]; 60 | } 61 | 62 | #pragma mark - Given 63 | 64 | - (void)givenExpectCommonInitToBeCalled { 65 | sut = [BaseNavigationController alloc]; 66 | 67 | [self givenPartialMock]; 68 | OCMExpect([partialMock commonInit]); 69 | } 70 | 71 | - (void)givenMockVisibleViewController { 72 | viewController = OCMClassMock([UIViewController class]); 73 | 74 | [self givenPartialMock]; 75 | OCMStub([partialMock visibleViewController]).andReturn(viewController); 76 | } 77 | 78 | - (void)givenPartialMock { 79 | [partialMock stopMocking]; // in case it's already set 80 | partialMock = OCMPartialMock(sut); 81 | } 82 | 83 | #pragma mark - Object Lifecycle - Tests 84 | 85 | - (void)test___init___calls_commonInit { 86 | 87 | // given 88 | [self givenExpectCommonInitToBeCalled]; 89 | 90 | // when 91 | sut = [sut init]; 92 | 93 | // then 94 | OCMVerifyAll(partialMock); 95 | } 96 | 97 | - (void)test___initWithCoder___calls_commonInit { 98 | 99 | // given 100 | [self givenExpectCommonInitToBeCalled]; 101 | 102 | NSCoder *coder = nil; 103 | 104 | // when 105 | sut = [sut initWithCoder:coder]; 106 | 107 | // then 108 | OCMVerifyAll(partialMock); 109 | } 110 | 111 | - (void)test___initWithNibName_bundle___calls_commonInit { 112 | 113 | // given 114 | [self givenExpectCommonInitToBeCalled]; 115 | 116 | // when 117 | sut = [sut initWithNibName:nil bundle:nil]; 118 | 119 | // then 120 | OCMVerifyAll(partialMock); 121 | } 122 | 123 | - (void)test___initWithRootViewController___calls_commonInit { 124 | 125 | // given 126 | [self givenExpectCommonInitToBeCalled]; 127 | 128 | // when 129 | sut = [sut initWithRootViewController:viewController]; 130 | 131 | // then 132 | OCMVerifyAll(partialMock); 133 | } 134 | 135 | - (void)test___initWithNavigationBarClass_toolbarClass { 136 | 137 | // given 138 | [self givenExpectCommonInitToBeCalled]; 139 | 140 | // when 141 | sut = [sut initWithNavigationBarClass:[UINavigationBar class] toolbarClass:[UIToolbar class]]; 142 | 143 | // then 144 | OCMVerifyAll(partialMock); 145 | } 146 | 147 | #pragma mark - View Lifecycle - Tests 148 | 149 | - (void)test___preferredInterfaceOrientationForPresentation___givenVisibleViewController_returns_viewController_preferredInterfaceOrientationForPresentation { 150 | 151 | // given 152 | UIInterfaceOrientation expected = UIInterfaceOrientationLandscapeLeft; 153 | [self givenMockVisibleViewController]; 154 | OCMStub([viewController preferredInterfaceOrientationForPresentation]).andReturn(expected); 155 | 156 | // when 157 | UIInterfaceOrientation actual = [sut preferredInterfaceOrientationForPresentation]; 158 | 159 | // then 160 | expect(actual).to.equal(expected); 161 | } 162 | 163 | - (void)test___preferredStatusBarStyle___givenVisibleViewController_returns_viewController_preferredStatusBarStyle { 164 | 165 | // given 166 | UIStatusBarStyle expected = UIStatusBarStyleLightContent; 167 | [self givenMockVisibleViewController]; 168 | OCMStub([viewController preferredStatusBarStyle]).andReturn(expected); 169 | 170 | // when 171 | UIStatusBarStyle actual = [sut preferredStatusBarStyle]; 172 | 173 | // then 174 | expect(actual).to.equal(expected); 175 | } 176 | 177 | - (void)test___shouldAutorotate___givenVisibleViewController_returns_viewController_shouldAutorotate { 178 | 179 | // given 180 | BOOL expected = false; 181 | [self givenMockVisibleViewController]; 182 | OCMStub([viewController shouldAutorotate]).andReturn(expected); 183 | 184 | // when 185 | BOOL actual = [sut shouldAutorotate]; 186 | 187 | // then 188 | expect(actual).to.equal(expected); 189 | } 190 | 191 | - (void)test___supportedInterfaceOrientations___givenVisibleViewController_returns_viewController_supportedInterfaceOrientations { 192 | 193 | // given 194 | UIInterfaceOrientationMask expected = UIInterfaceOrientationMaskLandscapeRight; 195 | [self givenMockVisibleViewController]; 196 | OCMStub([viewController supportedInterfaceOrientations]).andReturn(expected); 197 | 198 | // when 199 | UIInterfaceOrientationMask actual = [sut supportedInterfaceOrientations]; 200 | 201 | // then 202 | expect(actual).to.equal(expected); 203 | } 204 | 205 | - (void)test___viewDidLoad___calls_configureTabBar { 206 | 207 | // given 208 | UINavigationBar *navigationBar = sut.navigationBar; 209 | [self givenPartialMock]; 210 | OCMExpect([partialMock configureNavigationBar:navigationBar]); 211 | 212 | // when 213 | [sut viewDidLoad]; 214 | 215 | // then 216 | OCMVerify(partialMock); 217 | } 218 | 219 | @end 220 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/UIViewController+BetterBaseClasses.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BetterBaseClasses.h 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `UIViewController+BetterBaseClasses` adds class convenience methods to instantiate a view controller defined by `bundle`, `identifier`, and `storyboardName` values. 32 | * 33 | * @discussion You should use this category in combination with subclassing either `BaseTableViewController` or `BaseViewController`. 34 | */ 35 | @interface UIViewController (BetterBaseClasses) 36 | 37 | #pragma mark - Identifiers 38 | 39 | /** 40 | * @brief This method returns the bundle for the view controller. 41 | * 42 | * @discussion If you don't set the bundle via `setBundle:`, or override this method in a subclass, the bundle 43 | * defaults to the bundle for the view controller's class. 44 | * 45 | * If your view controller and its corresponding view are in the same bundle, this is 46 | * likely the correct behavior. However, if needed, you can optionally override this 47 | * method in a subclass. 48 | * 49 | * @return The nib bundle to load from 50 | */ 51 | + (nullable NSBundle *)bundle; 52 | 53 | /** 54 | * @brief Use this method to set the bundle for the view controller. 55 | * 56 | * @discussion This method is useful, for example, in unit testing. 57 | * 58 | * @param bundle The bundle to set for the view 59 | */ 60 | + (void)setBundle:(nullable NSBundle *)bundle; 61 | 62 | /** 63 | * @brief Override this method to specify the nib name that `instanceFromNib`, or the storyboard identifier that `instanceFromStoryboard`, should load. 64 | * 65 | * @discussion This method returns the last path component of the class name by default. 66 | * 67 | * @return The nib name/storboard identifier to load 68 | */ 69 | + (NSString *)identifier; 70 | 71 | /** 72 | * @brief Override this method to specify the navigation controller identifier that `navigationControllerInstanceFromStoryboard` should load. 73 | * 74 | * @discussion This method returns the `identifier` appended with "NavigationController" by default. 75 | * 76 | * @warning Its assumed this navigation controller will have this view controller set as its root view controller. 77 | * 78 | * @return The navigation controller identifier to load from the storyboard 79 | */ 80 | + (NSString *)navigationControllerIdentifier; 81 | 82 | /** 83 | * @brief Use this method to get the storyboard that `instanceFromStoryboard` should use. 84 | * 85 | * @discussion This method uses `storyboardName` and `bundle` to create the storyboard. 86 | * 87 | * @return The storyboard to use to load the view controller 88 | */ 89 | + (UIStoryboard *)storyboard; 90 | 91 | /** 92 | * @brief Use this method to specify the storyboard name that `instanceFromStoryboard` should use. 93 | * 94 | * @discussion This method returns "Main" by default. 95 | * 96 | * @return The storyboard name to use to load the view controller 97 | */ 98 | + (NSString *)storyboardName; 99 | 100 | #pragma mark - Instantiation 101 | 102 | /** 103 | * @brief Use this method to instantiate a new view controller from its nib. 104 | * 105 | * @discussion This is a convenience constructor that creates a new view controller using the `bundle` and `identifier` return values. 106 | * 107 | * @return A new instance of this controller 108 | */ 109 | + (instancetype)instanceFromNib; 110 | 111 | /** 112 | * @brief Use this method to instantiate a new view controller from its storyboard. 113 | * 114 | * @discussion This is a convenience constructor that creates a new view controller using the `bundle`, `identifier`, and `storyboardName` return values. 115 | * 116 | * @warning This method will throw a runtime exception if the storyboard or scene can't be loaded. 117 | * 118 | * @return A new instance of this controller 119 | */ 120 | + (instancetype)instanceFromStoryboard; 121 | 122 | /** 123 | * @brief Use this method to instantiate this view controller inside a navigation controller from its storyboard. 124 | * 125 | * @discussion This is a convenience constructor that creates a new navigation controller using the `bundle`, `navigationControllerIdentifier`, and `storyboardName` return values. 126 | * 127 | * @return A new navigation controller with this view controller set as the root view controller 128 | */ 129 | + (UINavigationController *)navigationControllerInstanceFromStoryboard; 130 | 131 | #pragma mark - Preferred Instance 132 | 133 | /** 134 | * @brief Use this method to get the "preferred" instance. 135 | * 136 | * @discussion This method either returns `instanceFromStoryboard` or `instanceFromNib` depending on the value of `preferStoryboards`. 137 | * 138 | * Subclasses may optionally override this method to always return `instanceFromNib` or `instanceFromStoryboard` instead, if desired. 139 | * 140 | * @return The "preferred" instance 141 | */ 142 | + (instancetype)preferredInstance; 143 | 144 | /** 145 | * @brief Use this method to set whether `preferredInstance` should return `instanceFromStoryboard`, if `YES`, or `instanceFromNib`, if `NO`. 146 | * 147 | * @discussion This value defaults to `NO`. 148 | * 149 | * @warning This value affects *all* view controllers. You should set it to `YES` if your target uses storyboards more often than nibs. 150 | * 151 | * @param preferStoryboards Whether or not storyboards are preferred instead of nibs 152 | */ 153 | + (void)setPreferStoryboards:(BOOL)preferStoryboards; 154 | 155 | /** 156 | * @brief Use this method to get whether storyboards are "preferred". 157 | * 158 | * @discussion This affects the behavior of `preferredInstance`. 159 | * 160 | * @return `YES` to prefer storyboards or `NO` to prefer nibs 161 | */ 162 | + (BOOL)preferStoryboards; 163 | 164 | #pragma mark - Object Lifecycle 165 | 166 | /** 167 | * @brief Use this method to perform common initialization, regardless of the designiated initializer used to create the view controller. 168 | * 169 | * @discussion Your custom view controllers that directly subclass `UIViewController` should call this method from all designated intializers. 170 | * 171 | * If you subclass `BaseViewController`, `BaseTableViewController`, or any subclasses thereof, this has already been done for you with the default initializers. 172 | * 173 | * @note If you introduce a new designated initializer in your subclass of said classes, you should make sure to call `commonInit` with it. 174 | */ 175 | - (void)commonInit __attribute((objc_requires_super)); 176 | 177 | @end 178 | 179 | NS_ASSUME_NONNULL_END 180 | -------------------------------------------------------------------------------- /BetterBaseClassesTests/UIViewController+BetterBaseClassesTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BetterBaseClassesTests.m 3 | // BetterBaseControllers 4 | // 5 | // Created by Joshua Greene on 2/22/15. 6 | // Copyright (c) 2015 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | // Test Class 27 | #import "UIViewController+BetterBaseClasses.h" 28 | 29 | // Collaborators 30 | 31 | // Test Support 32 | #import 33 | 34 | #define EXP_SHORTHAND YES 35 | #import 36 | 37 | #import 38 | 39 | @interface UIViewController_BetterBaseClassesTests : XCTestCase 40 | @end 41 | 42 | @implementation UIViewController_BetterBaseClassesTests { 43 | 44 | UIViewController *sut; 45 | 46 | NSBundle *bundle; 47 | NSString *identifier; 48 | NSString *navigationControllerIdentifier; 49 | NSString *storyboardName; 50 | 51 | id mockApp; 52 | id mockBundle; 53 | id mockStoryboard; 54 | id mockSutClass; 55 | 56 | id partialMock; 57 | } 58 | 59 | #pragma mark - Test Lifecycle 60 | 61 | - (void)setUp { 62 | 63 | [super setUp]; 64 | 65 | sut = [[UIViewController alloc] init]; 66 | 67 | bundle = [UIViewController bundle]; 68 | identifier = [UIViewController identifier]; 69 | navigationControllerIdentifier = [UIViewController navigationControllerIdentifier]; 70 | storyboardName = [UIViewController storyboardName]; 71 | } 72 | 73 | - (void)tearDown { 74 | 75 | [mockApp stopMocking]; 76 | [mockBundle stopMocking]; 77 | [mockStoryboard stopMocking]; 78 | [mockSutClass stopMocking]; 79 | 80 | [UIViewController setPreferStoryboards:NO]; 81 | 82 | [super tearDown]; 83 | } 84 | 85 | #pragma mark - Given 86 | 87 | - (void)givenMockBundle { 88 | mockBundle = OCMClassMock([NSBundle class]); 89 | } 90 | 91 | - (void)givenMockStoryboard { 92 | mockStoryboard = OCMClassMock([UIStoryboard class]); 93 | } 94 | 95 | - (void)givenMockSutClass { 96 | mockSutClass = OCMClassMock([UIViewController class]); 97 | } 98 | 99 | #pragma mark - Identifiers - Tests 100 | 101 | - (void)test___bundle___returns_bundleForClass { 102 | 103 | // given 104 | NSBundle *expected = [NSBundle bundleForClass:[self class]]; 105 | [self givenMockBundle]; 106 | OCMExpect([mockBundle bundleForClass:[UIViewController class]]).andReturn(expected); 107 | 108 | // when 109 | NSBundle *actual = [UIViewController bundle]; 110 | 111 | // then 112 | expect(actual).to.equal(expected); 113 | } 114 | 115 | - (void)test___setBundle___afterSettingBundle_bundle_returnsSetBundle { 116 | 117 | // given 118 | [self givenMockBundle]; 119 | NSBundle *expected = mockBundle; 120 | 121 | // when 122 | [UIViewController setBundle:mockBundle]; 123 | NSBundle *actual = [UIViewController bundle]; 124 | 125 | // then 126 | XCTAssertEqual(actual, expected); 127 | 128 | // clean up 129 | [UIViewController setBundle:nil]; 130 | } 131 | 132 | - (void)test___identifier___ifClassNameDoesntHavePathExtension_returnsClassName { 133 | 134 | // given 135 | NSString *expected = @"UIViewController"; 136 | 137 | // when 138 | NSString *actual = [UIViewController identifier]; 139 | 140 | // then 141 | expect(actual).to.equal(expected); 142 | } 143 | 144 | - (void)test___identifier___ifClassNameHasPathExtension_returnsClassPathExtension { 145 | 146 | // TO-DO: Figure out an easy way to test this... 147 | } 148 | 149 | - (void)test___navigationControllerIdentifier___returns_identifier_appendedBy_NavigationController { 150 | 151 | // given 152 | NSString *expected = [[UIViewController identifier] stringByAppendingString:@"NavigationController"]; 153 | 154 | // when 155 | NSString *actual = [UIViewController navigationControllerIdentifier]; 156 | 157 | // then 158 | expect(actual).to.equal(expected); 159 | } 160 | 161 | - (void)test___storyboard___returnsStoryboardUsingStoryboardNameAndBundle { 162 | 163 | // given 164 | [self givenMockStoryboard]; 165 | OCMStub(ClassMethod([mockStoryboard storyboardWithName:storyboardName bundle:bundle])).andReturn(mockStoryboard); 166 | 167 | // when 168 | UIStoryboard *actual = [UIViewController storyboard]; 169 | 170 | // then 171 | expect(actual).to.equal(mockStoryboard); 172 | } 173 | 174 | - (void)test___storyboardName___returns_infoDict_UIMainStoryboardFile { 175 | 176 | // given 177 | NSString *expected = [UIViewController storyboardName]; 178 | 179 | // when 180 | NSString *actual = [UIViewController storyboardName]; 181 | 182 | // then 183 | expect(actual).to.equal(expected); 184 | } 185 | 186 | #pragma mark - Instantiation - Tests 187 | 188 | - (void)test___instanceFromNib___calls_initWithNibName_bundle { 189 | 190 | // given 191 | NSString *nibName = [UIViewController identifier]; 192 | UIViewController *expected = [UIViewController new]; 193 | 194 | [self givenMockSutClass]; 195 | OCMStub([mockSutClass alloc]).andReturn(mockSutClass); 196 | OCMStub([mockSutClass initWithNibName:nibName bundle:bundle]).andReturn(expected); 197 | 198 | // when 199 | UIViewController *actual = [UIViewController instanceFromNib]; 200 | 201 | // then 202 | expect(actual).to.equal(expected); 203 | } 204 | 205 | - (void)test___instanceFromStoryboard___instantiatesViewControllerFromStoryboard { 206 | 207 | // given 208 | UIViewController *expected = [UIViewController new]; 209 | 210 | [self givenMockStoryboard]; 211 | OCMStub([mockStoryboard storyboardWithName:storyboardName bundle:bundle]).andReturn(mockStoryboard); 212 | OCMStub([mockStoryboard instantiateViewControllerWithIdentifier:identifier]).andReturn(expected); 213 | 214 | // when 215 | UIViewController *actual = [UIViewController instanceFromStoryboard]; 216 | 217 | // then 218 | expect(actual).to.equal(expected); 219 | } 220 | 221 | - (void)test___navigationControllerInstanceFromStoryboard___instantiatesNavigationControllerFromStoryboard { 222 | 223 | // given 224 | UINavigationController *expected = [UINavigationController new]; 225 | 226 | [self givenMockStoryboard]; 227 | OCMStub([mockStoryboard storyboardWithName:storyboardName bundle:bundle]).andReturn(mockStoryboard); 228 | OCMStub([mockStoryboard instantiateViewControllerWithIdentifier:navigationControllerIdentifier]).andReturn(expected); 229 | 230 | // when 231 | UINavigationController *actual = [UIViewController navigationControllerInstanceFromStoryboard]; 232 | 233 | // then 234 | expect(actual).to.equal(expected); 235 | } 236 | 237 | #pragma mark - Preferred Instance - Tests 238 | 239 | - (void)test___setPreferStoryboards___YES_setsPreferStoryboardsToYES { 240 | 241 | // given 242 | BOOL expected = YES; 243 | 244 | // when 245 | [UIViewController setPreferStoryboards:expected]; 246 | 247 | // then 248 | expect([UIViewController preferStoryboards]).to.beTruthy(); 249 | } 250 | 251 | - (void)test___preferredInstance___ifDoesntPrefersStoryboards_returns_instanceFromNib { 252 | 253 | // given 254 | [UIViewController setPreferStoryboards:NO]; 255 | 256 | UIViewController *expected = [UIViewController new]; 257 | [self givenMockSutClass]; 258 | 259 | OCMStub([mockSutClass instanceFromNib]).andReturn(expected); 260 | 261 | // when 262 | UIViewController *actual = [UIViewController preferredInstance]; 263 | 264 | // then 265 | expect(actual).to.equal(expected); 266 | } 267 | 268 | - (void)test___preferredInstance___ifPrefersStoryboards_returns_instanceFromStoryboard { 269 | 270 | // given 271 | [UIViewController setPreferStoryboards:YES]; 272 | 273 | UIViewController *expected = [UIViewController new]; 274 | [self givenMockSutClass]; 275 | 276 | OCMStub([mockSutClass instanceFromStoryboard]).andReturn(expected); 277 | 278 | // when 279 | UIViewController *actual = [UIViewController preferredInstance]; 280 | 281 | // then 282 | expect(actual).to.equal(expected); 283 | } 284 | 285 | @end 286 | -------------------------------------------------------------------------------- /BetterBaseClasses/Library/Controllers/BaseContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseContainerViewController.h 3 | // BetterBaseClasses 4 | // 5 | // Created by Joshua Greene on 8/24/16. 6 | // Copyright © 2016 Joshua Greene. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BaseViewController.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | /** 31 | * @brief `BaseContainerViewController` is an abstract, base class meant to be subclassed instead of `UIViewController`. This makes it easier to create container view controllers with a "top" and "bottom" content views or view controllers. 32 | * 33 | * @discussion This class is meant to be used with the `UIViewController+BetterBaseClasses` category, which provides convenience instantiation methods. 34 | * 35 | * This class calls `commonInit` in each of the initializers provided by its super class. Additionally, it overrides certain view methods (`preferredInterfaceOrientationForPresentation`, `preferredStatusBarStyle`, `shouldAutorotate`, and `supportedInterfaceOrientations`) to forward these onto its child view controller. 36 | */ 37 | @interface BaseContainerViewController : BaseViewController 38 | 39 | #pragma mark - Class Configuration 40 | 41 | /** 42 | * Use this method to get the animation duration used for showing and hiding the top and bottom container views. 43 | * 44 | * @return The animation duration 45 | */ 46 | + (CGFloat)animationDuration; 47 | 48 | /** 49 | * Use this method to set the animation duration for showing and hiding the top and bottom container views. 50 | * 51 | * @param animationDuration The animation duration 52 | */ 53 | + (void)setAnimationDuration:(CGFloat)animationDuration; 54 | 55 | 56 | #pragma mark - Constraint Properties 57 | 58 | /** 59 | * Set this constraint if you want the bottom container to automatically show/hide whenever its content view is set via `setBottomContentView` or other related methods. 60 | */ 61 | @property (strong, nonatomic, nullable) IBOutlet NSLayoutConstraint *bottomContainerViewHeightConstraint; 62 | 63 | /** 64 | * Set this constraint if you want the top container to automatically show/hide whenever its content view is set via `setTopContentView` or related methods. 65 | */ 66 | @property (strong, nonatomic, nullable) IBOutlet NSLayoutConstraint *topContainerViewHeightConstraint; 67 | 68 | 69 | #pragma mark - View Properties 70 | 71 | /** 72 | * You MAY set this outlet if you want to have a bottom container view. 73 | */ 74 | @property (strong, nonatomic, nullable) IBOutlet UIView *bottomContainerView; 75 | 76 | 77 | /** 78 | * You MAY set this outlet if you want to have a top container view. 79 | */ 80 | @property (strong, nonatomic, nullable) IBOutlet UIView *topContainerView; 81 | 82 | 83 | #pragma mark - View Controller Properties 84 | 85 | /** 86 | * @brief The bottom view controller 87 | * 88 | * @discussion This method calls `setBottomViewController: animated: completion:`, passing `YES` for `animated` and `nil` for completion. 89 | * 90 | * @warning You MUST set the `bottomContainerView` outlet in order for this view controller to be shown. 91 | */ 92 | @property (strong, nonatomic, nullable) UIViewController *bottomViewController; 93 | 94 | /** 95 | * @brief The top view controller 96 | * 97 | * @discussion This method calls `setTopViewController: animated: completion:`, passing `YES` for `animated` and `nil` for completion. 98 | * 99 | * @warning You MUST set the `topContainerView` outlet in order for this view controller to be shown. 100 | * 101 | */ 102 | @property (strong, nonatomic, nullable) UIViewController *topViewController; 103 | 104 | 105 | #pragma mark - Bottom Container View Methods 106 | 107 | /** 108 | * @brief Use this method to hide/show the bottom container view. 109 | * 110 | * @discussion This is a convenience method that calls `setBottomContainerViewHidden: animated: completion:`, passing `YES` for `animated` and `nil` for `completion`. 111 | * 112 | * @param hidden Whether or not the container view should be hidden 113 | */ 114 | - (void)setBottomContainerViewHidden:(BOOL)hidden; 115 | 116 | /** 117 | * @brief Use this method to hide/show the bottom container view. 118 | * 119 | * @discussion This method hides/shows the `bottomContainerView` by setting the `bottomContainerViewHeightConstraint`'s `constant` value. If this property is `nil`, this method doesn't do anything. 120 | * 121 | * @param hidden Whether or not the container view should be hidden 122 | * @param animated Whether or not the change should be animated 123 | * @param completion The block to be called upon completion 124 | */ 125 | - (void)setBottomContainerViewHidden:(BOOL)hidden 126 | animated:(BOOL)animated 127 | completion:(nullable void(^)(void))completion; 128 | 129 | /** 130 | * @brief Use this method to set `bottomContainerView`'s "content" view. 131 | * 132 | * @discussion If the `bottonContainerView` already has subview(s), they will ALl be replaced by this view. 133 | * 134 | * You may pass `nil` into this method. If you do so, and `bottomContainerViewHeightConstraint` is set, the `bottomContainerViewHeightConstraint`'s `constant` will be animated and set to zero. 135 | * 136 | * @param contentView The new content view 137 | */ 138 | - (void)setBottomContentView:(nullable UIView *)contentView; 139 | 140 | /** 141 | * @brief Use this method to set `bottomContainerView`'s "content" view. 142 | * 143 | * @discussion If the `bottonContainerView` already has subview(s), they will ALL be replaced by this view. 144 | * 145 | * You may pass `nil` into this method. If you do so, and `bottomContainerViewHeightConstraint` is set, the `bottomContainerViewHeightConstraint`'s `constant` will be animated and set to zero. 146 | * 147 | * @param contentView The new content view 148 | * @param animated Whether or not the change should be animated 149 | * @param completion The block to be called upon completion 150 | */ 151 | - (void)setBottomContentView:(nullable UIView *)contentView animated:(BOOL)animated completion:(nullable void(^)(void))completion; 152 | 153 | /** 154 | * @brief Use this method to set the `bottomViewController`. 155 | * 156 | * @discussion This method removes the existing `bottomViewController` and adds the new view controller as a child view controller of this view controller. 157 | * 158 | * You MAY pass `nil` to remove the `bottomViewController` and its `view`. 159 | * 160 | * @warning You MUST set the `bottomContainerView` outlet in order for this view controller to be shown. 161 | * 162 | * @param viewController The new bottom view controller 163 | * @param animated Whether or not the change should be animated 164 | * @param completion The block to be called upon completion 165 | */ 166 | - (void)setBottomViewController:(nullable UIViewController *)viewController animated:(BOOL) animated completion:(nullable void(^)(void))completion; 167 | 168 | 169 | #pragma mark - Top Container View Methods 170 | 171 | /** 172 | * @brief Use this method to hide/show the top container view. 173 | * 174 | * @discussion This is a convenience method that calls `setTopContainerViewHidden: animated: completion:`, passing `YES` for `animated` and `nil` for `completion`. 175 | * 176 | * @param hidden Whether or not the container view should be hidden 177 | */ 178 | - (void)setTopContainerViewHidden:(BOOL)hidden; 179 | 180 | /** 181 | * @brief Use this method to hide/show the top container view. 182 | * 183 | * @discussion This method hides/shows the `topContainerView` by setting the `topContainerViewHeightConstraint`'s `constant` value. If this property is `nil`, this method doesn't do anything. 184 | * 185 | * @param hidden Whether or not the container view should be hidden 186 | * @param animated Whether or not the change should be animated 187 | * @param completion The block to be called upon completion 188 | */ 189 | - (void)setTopContainerViewHidden:(BOOL)hidden 190 | animated:(BOOL)animated 191 | completion:(nullable void(^)(void))completion; 192 | 193 | /** 194 | * @brief Use this method to set `topContainerView`'s "content" view. 195 | * 196 | * @discussion If the `topContainerView` already has subview(s), they will ALl be replaced by this view. 197 | * 198 | * You may pass `nil` into this method. If you do so, and `topContainerViewHeightConstraint` is set, the `topContainerViewHeightConstraint`'s `constant` will be animated and set to zero. 199 | * 200 | * @param contentView The new content view 201 | */ 202 | - (void)setTopContentView:(nullable UIView *)contentView; 203 | 204 | /** 205 | * @brief Use this method to set `topContainerView`'s "content" view. 206 | * 207 | * @discussion If the `topContainerView` already has subview(s), they will ALl be replaced by this view. 208 | * 209 | * You may pass `nil` into this method. If you do so, and `topContainerViewHeightConstraint` is set, the `topContainerViewHeightConstraint`'s `constant` will be animated and set to zero. 210 | * 211 | * @param contentView The new content view 212 | * @param animated Whether or not the change should be animated 213 | * @param completion The block to be called upon completion 214 | */ 215 | - (void)setTopContentView:(nullable UIView *)contentView animated:(BOOL)animated completion:(nullable void(^)(void))completion; 216 | 217 | /** 218 | * @brief Use this method to set the `topViewController`. 219 | * 220 | * @discussion This method removes the existing `topViewController` and adds the new view controller as a child view controller of this view controller. 221 | * 222 | * You MAY pass `nil` to remove the `topViewController` and its `view`. 223 | * 224 | * @warning You MUST set the `topContainerView` outlet in order for this view controller to be shown. 225 | * 226 | * @param viewController The new top view controller 227 | * @param animated Whether or not the change should be animated 228 | * @param completion The block to be called upon completion 229 | */ 230 | - (void)setTopViewController:(nullable UIViewController *)viewController animated:(BOOL) animated completion:(nullable void(^)(void))completion; 231 | 232 | @end 233 | 234 | NS_ASSUME_NONNULL_END 235 | --------------------------------------------------------------------------------