├── .gitignore ├── README.md ├── Sample ├── UUCoreBluetooth │ ├── UUCoreBluetooth.xcodeproj │ │ └── project.pbxproj │ └── UUCoreBluetooth │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-20@2x.png │ │ │ ├── Icon-20@3x.png │ │ │ ├── Icon-29@2x.png │ │ │ ├── Icon-29@3x.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ └── Icon-60@3x.png │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── CharacteristicDetailController.h │ │ ├── CharacteristicDetailController.m │ │ ├── CharacteristicTableCell.h │ │ ├── CharacteristicTableCell.m │ │ ├── Info.plist │ │ ├── PeripheralDetailCell.h │ │ ├── PeripheralDetailCell.m │ │ ├── PeripheralDetailController.h │ │ ├── PeripheralDetailController.m │ │ ├── PeripheralListController.h │ │ ├── PeripheralListController.m │ │ ├── PeripheralListTableCell.h │ │ ├── PeripheralListTableCell.m │ │ ├── ServiceDetailCell.h │ │ ├── ServiceDetailCell.m │ │ ├── ServiceDetailController.h │ │ ├── ServiceDetailController.m │ │ ├── ServiceListController.h │ │ ├── ServiceListController.m │ │ ├── ServiceTableCell.h │ │ ├── ServiceTableCell.m │ │ └── main.m ├── UUInstagramatic.xcodeproj │ └── project.pbxproj ├── UUInstagramatic │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── UUAppDelegate.h │ ├── UUAppDelegate.m │ ├── UUInstagramatic-Info.plist │ ├── UUInstagramatic-Prefix.pch │ ├── UUInstagramaticTableViewCell.xib │ ├── UUInstagramaticViewController.h │ ├── UUInstagramaticViewController.m │ ├── UUInstagramaticViewController.xib │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m └── UUSwift │ ├── UUSwift.xcodeproj │ └── project.pbxproj │ ├── UUSwift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Data │ │ └── WeatherRecord+Ext.swift │ ├── HomeController.swift │ ├── ImageGalleryController.swift │ ├── Info.plist │ ├── RSQuote+Ext.swift │ ├── RSQuoteController.swift │ ├── RSQuoteService.swift │ ├── UUSwift.xcdatamodeld │ │ ├── .xccurrentversion │ │ └── UUSwift.xcdatamodel │ │ │ └── contents │ ├── WeatherController.swift │ └── WeatherService.swift │ ├── UUSwiftTests │ ├── Info.plist │ ├── UUCoreDataTests.swift │ ├── UUCoreDataUnitTests.xcdatamodeld │ │ └── UUCoreDataUnitTests.xcdatamodel │ │ │ └── contents │ ├── UUDataCacheTests.swift │ └── UURemoteDataTests.swift │ └── UUSwiftUITests │ ├── Info.plist │ └── UUSwiftUITests.swift ├── Test └── UUToolbox │ ├── UUToolbox.xcodeproj │ └── project.pbxproj │ ├── UUToolbox │ ├── Info.plist │ └── UUToolbox.h │ └── UUToolboxTests │ ├── Helpers │ ├── XCTestCase+UUTestExtensions.h │ └── XCTestCase+UUTestExtensions.m │ ├── Info.plist │ ├── UUColorTests.m │ ├── UUCompressionTests.m │ ├── UUCoreData │ ├── ModelExtensions │ │ ├── UUPlayer+Extensions.h │ │ └── UUPlayer+Extensions.m │ ├── Models │ │ ├── UUPlayer.h │ │ └── UUPlayer.m │ ├── UUCoreDataTestModels.xcdatamodeld │ │ └── UUCoreDataTestModels.xcdatamodel │ │ │ └── contents │ └── UUCoreDataTests.m │ ├── UUDateTests.m │ ├── UUDictionaryTests.m │ ├── UURandomTests.m │ ├── UUStringTests.m │ └── UUToolboxTests.m ├── UUAccessorySession.h ├── UUAccessorySession.m ├── UUActionSheet.h ├── UUActionSheet.m ├── UUAlert.h ├── UUAlert.m ├── UUAwsS3Client.h ├── UUAwsS3Client.m ├── UUCameraView.h ├── UUCameraView.m ├── UUColor.h ├── UUColor.m ├── UUCompression.h ├── UUCompression.m ├── UUCoreBluetooth.h ├── UUCoreBluetooth.m ├── UUCoreData.h ├── UUCoreData.m ├── UUData.h ├── UUData.m ├── UUDataCache.h ├── UUDataCache.m ├── UUDate.h ├── UUDate.m ├── UUDebug.h ├── UUDebug.m ├── UUDevice.h ├── UUDevice.m ├── UUDictionary.h ├── UUDictionary.m ├── UUDoubleSliderView.h ├── UUDoubleSliderView.m ├── UUDropbox.h ├── UUDropbox.m ├── UUFlickr.h ├── UUFlickr.m ├── UUGradientView.h ├── UUGradientView.m ├── UUHttpClient.h ├── UUHttpClient.m ├── UUHttpResponseHandler.h ├── UUHttpResponseHandler.m ├── UUHttpSession.h ├── UUHttpSession.m ├── UUImage.h ├── UUImage.m ├── UUImageCache.h ├── UUImageCache.m ├── UUImageView.h ├── UUImageView.m ├── UUInstagram.h ├── UUInstagram.m ├── UULocation.h ├── UULocation.m ├── UULocationManager.h ├── UULocationManager.m ├── UUMacros.h ├── UUMapView.h ├── UUMapView.m ├── UUObject.h ├── UUObject.m ├── UUObjectFactory.h ├── UUObjectFactory.m ├── UUOpenALSoundManager.h ├── UUOpenALSoundManager.m ├── UUProgressView.h ├── UUProgressView.m ├── UURandom.h ├── UURandom.m ├── UUReachability.h ├── UUReachability.m ├── UURemoteData.h ├── UURemoteData.m ├── UURemoteImage.h ├── UURemoteImage.m ├── UUString.h ├── UUString.m ├── UUTextField.h ├── UUTextField.m ├── UUTimer.h ├── UUTimer.m ├── UUVerticalSliderView.h ├── UUVerticalSliderView.m ├── UUView.h ├── UUView.m └── swift └── UUToolbox ├── UUToolbox.xcodeproj └── project.pbxproj ├── UUToolbox ├── Info.plist ├── UUCircularImageView.swift ├── UUCircularView.swift ├── UUColor.swift ├── UUCoreData.swift ├── UUData.swift ├── UUDataCache.swift ├── UUDate.swift ├── UUDebugLog.swift ├── UUDictionary.swift ├── UUEditViewController.swift ├── UUGradientView.swift ├── UUHttpSession.swift ├── UUJson.swift ├── UUMapView.swift ├── UUObjectFactory.swift ├── UURandom.swift ├── UURemoteData.swift ├── UURemoteImage.swift ├── UUString.swift ├── UUTextField.swift ├── UUToolbox.h ├── UUView.swift └── UUViewController.swift ├── UUToolboxLib.modulemap ├── UUToolboxLib.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── UUToolbox.xcscheme └── UUToolboxTests ├── Info.plist ├── UUTestCase.swift └── UUToolboxTests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | Sample/UUInstagramatic.xcodeproj/xcuserdata/ 2 | Sample/UUInstagramatic.xcodeproj/project.xcworkspace/ 3 | xcuserdata 4 | project.xcworkspace 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Useful Utilities 2 | ======================== 3 | Useful Utilities is a toolbox of iOS functions and code that can be pulled in as needed for functions that 4 | you repeatedly find yourself doing in your code. 5 | 6 | The central design imperative is that there are no dependencies and that each pair of .h/.m files can simply be dropped into an existing project and be used with a minimal amount of code. 7 | They are intentionally lightweight and need to avoid the "kitchen sink" syndrome that happens to most libraries. 8 | If you have something you'd like to contribute, let me know. Sharing is fun! 9 | 10 | The code is released with no strings attached. You don't even have to give me credit. Just enjoy using them. 11 | I use them almost every day and literally on every project I work on. Feel free to shoot me quesitons, thanks, complaints or suggestions. 12 | I love hearing from people. If you end up shipping a product with any of them, I'd also love to hear about it but it's not required. 13 | 14 | -Jonathan Hays 15 | 16 | @cheesemaker on ADN and Twitter 17 | 18 | jon@threejacks.com 19 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/9/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/9/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application 24 | { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 27 | } 28 | 29 | - (void)applicationDidEnterBackground:(UIApplication *)application 30 | { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | - (void)applicationWillEnterForeground:(UIApplication *)application 36 | { 37 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | - (void)applicationDidBecomeActive:(UIApplication *)application 41 | { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | - (void)applicationWillTerminate:(UIApplication *)application 46 | { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-60@3x.png", 49 | "scale" : "3x" 50 | } 51 | ], 52 | "info" : { 53 | "version" : 1, 54 | "author" : "xcode" 55 | } 56 | } -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesemaker/toolbox/b5d7e0317a48054b64f3236dd64d1099c7cbab6a/Sample/UUCoreBluetooth/UUCoreBluetooth/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/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 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/CharacteristicDetailController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CharacteristicDetailController.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/25/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CharacteristicDetailController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/CharacteristicDetailController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CharacteristicDetailController.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/25/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "CharacteristicDetailController.h" 10 | 11 | @interface CharacteristicDetailController () 12 | 13 | @end 14 | 15 | @implementation CharacteristicDetailController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | /* 28 | #pragma mark - Navigation 29 | 30 | // In a storyboard-based application, you will often want to do a little preparation before navigation 31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 32 | // Get the new view controller using [segue destinationViewController]. 33 | // Pass the selected object to the new view controller. 34 | } 35 | */ 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/CharacteristicTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CharacteristicTableCell.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/18/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef void (^ToggleNotifyClickedBlock)(CBCharacteristic* _Nonnull characteristic); 13 | typedef void (^ReadDataClickedBlock)(CBCharacteristic* _Nonnull characteristic); 14 | typedef void (^WriteDataClickedBlock)(CBCharacteristic* _Nonnull characteristic, NSData* _Nonnull data); 15 | typedef void (^EditViewBlock)(UITextView* _Nonnull textView); 16 | 17 | @interface CharacteristicTableCell : UITableViewCell 18 | 19 | @property (nullable, copy) ToggleNotifyClickedBlock notifyClickedBlock; 20 | @property (nullable, copy) ReadDataClickedBlock readDataClickedBlock; 21 | @property (nullable, copy) WriteDataClickedBlock writeDataClickedBlock; 22 | @property (nullable, copy) WriteDataClickedBlock writeDataWithoutResponseClickedBlock; 23 | @property (nullable, copy) EditViewBlock textViewDidBeginEditingBlock; 24 | @property (nullable, copy) EditViewBlock textViewDidEndEditingBlock; 25 | 26 | - (void) update:(nonnull CBCharacteristic*)characteristic; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/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 | 40 | 41 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/PeripheralDetailCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PeripheralDetailCell.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/19/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UUCoreBluetooth.h" 11 | 12 | @interface PeripheralDetailCell : UITableViewCell 13 | 14 | - (void) update:(nonnull UUPeripheral*)peripheral; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/PeripheralDetailCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PeripheralDetailCell.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/19/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "PeripheralDetailCell.h" 10 | 11 | @interface PeripheralDetailCell () 12 | 13 | @property (strong, nonatomic) IBOutlet UILabel *idLabel; 14 | @property (strong, nonatomic) IBOutlet UILabel *nameLabel; 15 | @property (strong, nonatomic) IBOutlet UILabel *stateLabel; 16 | @property (strong, nonatomic) IBOutlet UILabel *rssiLabel; 17 | 18 | @end 19 | 20 | @implementation PeripheralDetailCell 21 | 22 | - (void) update:(nonnull UUPeripheral*)peripheral 23 | { 24 | self.idLabel.text = peripheral.identifier; 25 | self.nameLabel.text = peripheral.name; 26 | self.stateLabel.text = [NSString stringWithFormat:@"%@ (%@)", UUCBPeripheralStateToString(peripheral.peripheralState), @(peripheral.peripheralState)]; 27 | self.rssiLabel.text = [NSString stringWithFormat:@"%@", peripheral.rssi]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/PeripheralDetailController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PeripheralDetailController.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/19/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UUCoreBluetooth.h" 11 | 12 | @interface PeripheralDetailController : UIViewController 13 | 14 | @property (nonnull, nonatomic, strong) UUPeripheral* peripheral; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/PeripheralListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PeripheralListController.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/19/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PeripheralListController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/PeripheralListTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PeripheralTableCell.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/9/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UUCoreBluetooth.h" 11 | 12 | 13 | @interface PeripheralListTableRow : NSObject 14 | 15 | @property (nonnull, nonatomic, strong) UUPeripheral* peripheral; 16 | @property (assign) BOOL isExpanded; 17 | 18 | @end 19 | 20 | 21 | @interface PeripheralListTableCell : UITableViewCell 22 | 23 | - (void) update:(nonnull PeripheralListTableRow*)cellData; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/PeripheralListTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PeripheralTableCell.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/9/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "PeripheralListTableCell.h" 10 | 11 | @implementation PeripheralListTableRow 12 | 13 | @end 14 | 15 | 16 | @interface PeripheralListTableCell () 17 | 18 | @property (strong, nonatomic) IBOutlet UILabel *nameLabel; 19 | @property (strong, nonatomic) IBOutlet UILabel *idLabel; 20 | @property (strong, nonatomic) IBOutlet UILabel *stateLabel; 21 | @property (strong, nonatomic) IBOutlet UILabel *rssiLabel; 22 | @property (strong, nonatomic) IBOutlet UILabel *timeSinceLastBeaconLabel; 23 | 24 | @end 25 | 26 | @implementation PeripheralListTableCell 27 | 28 | - (void) update:(PeripheralListTableRow*)cellData 29 | { 30 | UUPeripheral* peripheral = cellData.peripheral; 31 | 32 | self.nameLabel.text = peripheral.name; 33 | self.idLabel.text = peripheral.identifier; 34 | self.rssiLabel.text = [peripheral.rssi stringValue]; 35 | self.stateLabel.text = UUCBPeripheralStateToString(peripheral.peripheralState); 36 | self.timeSinceLastBeaconLabel.text = [NSString stringWithFormat:@"%.3f", [[NSDate date] timeIntervalSinceDate:peripheral.lastAdvertisementTime]]; 37 | 38 | if (cellData.isExpanded) 39 | { 40 | self.nameLabel.text = [peripheral.name stringByAppendingString:@" +++ "]; 41 | } 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceDetailCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceDetailCell.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/25/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UUCoreBluetooth.h" 11 | 12 | @interface ServiceDetailCell : UITableViewCell 13 | 14 | - (void) update:(nonnull CBService*)service; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceDetailCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceDetailCell.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/25/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "ServiceDetailCell.h" 10 | 11 | @interface ServiceDetailCell () 12 | 13 | @property (strong, nonatomic) IBOutlet UILabel *uuidLabel; 14 | @property (strong, nonatomic) IBOutlet UILabel *isPrimaryLabel; 15 | @property (strong, nonatomic) IBOutlet UILabel *nameLabel; 16 | 17 | @end 18 | 19 | 20 | @implementation ServiceDetailCell 21 | 22 | - (void) update:(nonnull CBService*)service 23 | { 24 | self.nameLabel.text = [service.UUID uuCommonName]; 25 | self.uuidLabel.text = [service.UUID UUIDString]; 26 | self.isPrimaryLabel.text = service.isPrimary ? @"Y" : @"N"; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceDetailController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceDetailController.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/18/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UUCoreBluetooth.h" 11 | 12 | @interface ServiceDetailController : UIViewController 13 | 14 | @property (nonnull, nonatomic, strong) UUPeripheral* peripheral; 15 | @property (nonnull, nonatomic, strong) CBService* service; 16 | @end 17 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceListController.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/17/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UUCoreBluetooth.h" 11 | 12 | @interface ServiceListController : UIViewController 13 | 14 | @property (nonnull, nonatomic, strong) UUPeripheral* peripheral; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceListController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceListController.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/17/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "ServiceListController.h" 10 | #import "ServiceTableCell.h" 11 | #import "ServiceDetailController.h" 12 | #import "UUMacros.h" 13 | 14 | @interface ServiceListController () 15 | 16 | @property (nonatomic, strong) NSArray* tableData; 17 | @property (strong, nonatomic) IBOutlet UITableView *tableView; 18 | 19 | @end 20 | 21 | @implementation ServiceListController 22 | 23 | - (void)viewDidLoad 24 | { 25 | [super viewDidLoad]; 26 | 27 | self.tableView.rowHeight = UITableViewAutomaticDimension; 28 | self.tableView.estimatedRowHeight = 30; 29 | self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; 30 | 31 | } 32 | 33 | - (void) viewWillAppear:(BOOL)animated 34 | { 35 | [super viewWillAppear:animated]; 36 | 37 | self.title = self.peripheral.name; 38 | 39 | [self updatePeripheralState]; 40 | 41 | if (self.peripheral.peripheralState != CBPeripheralStateConnected) 42 | { 43 | /* 44 | [[UUCoreBluetooth sharedInstance] connectPeripheral:self.peripheral 45 | timeout:30.0f 46 | connected:^(UUPeripheral * _Nonnull peripheral) 47 | { 48 | [self updatePeripheralState]; 49 | [self scanForServices]; 50 | } 51 | disconnected:^(UUPeripheral * _Nonnull peripheral, NSError * _Nullable error) 52 | { 53 | [self updatePeripheralState]; 54 | 55 | }];*/ 56 | } 57 | else 58 | { 59 | [self scanForServices]; 60 | } 61 | } 62 | 63 | - (void) scanForServices 64 | { 65 | [self.peripheral.peripheral uuDiscoverServices:nil 66 | timeout:30.0f 67 | completion:^(CBPeripheral * _Nonnull peripheral, NSError * _Nullable error) 68 | { 69 | UUDispatchMain(^ 70 | { 71 | self.tableData = peripheral.services; 72 | [self.tableView reloadData]; 73 | }); 74 | }]; 75 | } 76 | 77 | - (void) updatePeripheralState 78 | { 79 | dispatch_async(dispatch_get_main_queue(), ^ 80 | { 81 | //self.navigationItem.prompt = UUCBPeripheralStateToString(self.peripheral.peripheralState); 82 | }); 83 | } 84 | 85 | 86 | - (void)didReceiveMemoryWarning { 87 | [super didReceiveMemoryWarning]; 88 | // Dispose of any resources that can be recreated. 89 | } 90 | 91 | 92 | #pragma mark - Navigation 93 | 94 | // In a storyboard-based application, you will often want to do a little preparation before navigation 95 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 96 | { 97 | // Get the new view controller using [segue destinationViewController]. 98 | // Pass the selected object to the new view controller. 99 | 100 | if ([@"showServiceDetail" isEqualToString:segue.identifier]) 101 | { 102 | ServiceDetailController* c = [segue destinationViewController]; 103 | //c.peripheral = self.peripheral; 104 | c.service = sender; 105 | } 106 | } 107 | 108 | 109 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 110 | { 111 | return self.tableData.count; 112 | } 113 | 114 | - (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 115 | { 116 | ServiceTableCell* cell = [tableView dequeueReusableCellWithIdentifier:@"ServiceTableCell" forIndexPath:indexPath]; 117 | CBService* service = self.tableData[indexPath.row]; 118 | [cell update:service]; 119 | return cell; 120 | } 121 | 122 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 123 | { 124 | CBService* service = self.tableData[indexPath.row]; 125 | [self performSegueWithIdentifier:@"showServiceDetail" sender:service]; 126 | } 127 | 128 | 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceTableCell.h 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/17/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ServiceTableCell : UITableViewCell 13 | 14 | - (void) update:(CBService*)service; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/ServiceTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceTableCell.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/17/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import "ServiceTableCell.h" 10 | 11 | @interface ServiceTableCell () 12 | 13 | @property (strong, nonatomic) IBOutlet UILabel *uuidLabel; 14 | @property (strong, nonatomic) IBOutlet UILabel *isPrimaryLabel; 15 | @property (strong, nonatomic) IBOutlet UILabel *includedServicesCountLabel; 16 | @property (strong, nonatomic) IBOutlet UILabel *characteristicCountLabel; 17 | 18 | @end 19 | 20 | @implementation ServiceTableCell 21 | 22 | - (void)awakeFromNib { 23 | [super awakeFromNib]; 24 | // Initialization code 25 | } 26 | 27 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 28 | [super setSelected:selected animated:animated]; 29 | 30 | // Configure the view for the selected state 31 | } 32 | 33 | - (void) update:(CBService*)service 34 | { 35 | self.uuidLabel.text = [service.UUID UUIDString]; 36 | self.isPrimaryLabel.text = service.isPrimary ? @"Y" : @"N"; 37 | self.includedServicesCountLabel.text = [NSString stringWithFormat:@"%@", @(service.includedServices.count)]; 38 | self.characteristicCountLabel.text = [NSString stringWithFormat:@"%@", @(service.characteristics.count)]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Sample/UUCoreBluetooth/UUCoreBluetooth/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // UUCoreBluetooth 4 | // 5 | // Created by Ryan DeVore on 11/9/16. 6 | // Copyright © 2016 UUToolbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/Images.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" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Sample/UUInstagramatic/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUAppDelegate.h 3 | // UUInstagramatic 4 | // 5 | // Created by Jonathan Hays on 1/17/14. 6 | // Copyright (c) 2014 Threejacks Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UUAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUAppDelegate.m 3 | // UUInstagramatic 4 | // 5 | // Created by Jonathan Hays on 1/17/14. 6 | // Copyright (c) 2014 Threejacks Software. All rights reserved. 7 | // 8 | 9 | #import "UUAppDelegate.h" 10 | #import "UUInstagramaticViewController.h" 11 | 12 | @implementation UUAppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 17 | // Override point for customization after application launch. 18 | self.window.backgroundColor = [UIColor whiteColor]; 19 | 20 | UUInstagramaticViewController* viewController = [[UUInstagramaticViewController alloc] initWithNibName:@"UUInstagramaticViewController" bundle:nil]; 21 | [self.window setRootViewController:viewController]; 22 | 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application 28 | { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application 34 | { 35 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application 40 | { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application 45 | { 46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 47 | } 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application 50 | { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUInstagramatic-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | threejacks.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | CFBundleURLTypes 38 | 39 | 40 | CFBundleURLName 41 | UUDemoApp 42 | CFBundleURLSchemes 43 | 44 | UUDemoApp 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUInstagramatic-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUInstagramaticTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUInstagramaticViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUInstagramaticViewController.h 3 | // UUInstagramatic 4 | // 5 | // Created by Jonathan Hays on 1/17/14. 6 | // Copyright (c) 2014 Threejacks Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UUInstagramaticTableViewCell : UITableViewCell 12 | @property (nonatomic, strong) IBOutlet UIImageView* imageView; 13 | @end 14 | 15 | @interface UUInstagramaticViewController : UIViewController 16 | @property (nonatomic, strong) IBOutlet UITableView* tableView; 17 | 18 | - (IBAction) onLogin:(id)sender; 19 | @end 20 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUInstagramaticViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUInstagramaticViewController.m 3 | // UUInstagramatic 4 | // 5 | // Created by Jonathan Hays on 1/17/14. 6 | // Copyright (c) 2014 Threejacks Software. All rights reserved. 7 | // 8 | 9 | #import "UUInstagramaticViewController.h" 10 | #import "UUInstagram.h" 11 | #import "UUImageView.h" 12 | 13 | #define kUUInstagramClientID @"b547fd59351944fd9c2e572a01493a24" 14 | #define kUUInstagramClientSecret @"1e15383b36bf4f5484c1557d922f0e04" 15 | 16 | #define kUUInstagramaticTableViewCellIdentifier @"UUInstagramaticTableViewCell" 17 | 18 | //Stubbed out implementation here... 19 | @implementation UUInstagramaticTableViewCell 20 | @end 21 | 22 | @interface UUInstagramaticViewController () 23 | @property (nonatomic, strong) NSMutableArray* imageURLArray; 24 | @end 25 | 26 | @implementation UUInstagramaticViewController 27 | 28 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 29 | { 30 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 31 | if (self) { 32 | // Custom initialization 33 | } 34 | return self; 35 | } 36 | 37 | - (void) viewDidLoad 38 | { 39 | [self.tableView registerNib:[UINib nibWithNibName:@"UUInstagramaticTableViewCell" bundle:nil] forCellReuseIdentifier:kUUInstagramaticTableViewCellIdentifier]; 40 | } 41 | 42 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 43 | { 44 | return 160.0; 45 | } 46 | 47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 48 | { 49 | return self.imageURLArray.count; 50 | } 51 | 52 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 53 | { 54 | NSString* imageURL = [self.imageURLArray objectAtIndex:indexPath.row]; 55 | UUInstagramaticTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:kUUInstagramaticTableViewCellIdentifier forIndexPath:indexPath]; 56 | [cell.imageView uuLoadImageFromURL:[NSURL URLWithString:imageURL] defaultImage:nil loadCompleteHandler:^(UIImageView *imageView) 57 | { 58 | 59 | }]; 60 | return cell; 61 | } 62 | 63 | - (IBAction) onLogin:(id)sender 64 | { 65 | [UUInstagram authenticate:self completionHandler:^(BOOL success, NSString *userKey) 66 | { 67 | NSLog(@"Got here!"); 68 | [UUInstagram getPopularMedia:^(BOOL success, NSDictionary *userMedia) 69 | { 70 | [self buildMediaList:userMedia]; 71 | }]; 72 | }]; 73 | } 74 | 75 | - (void) buildMediaList:(NSDictionary*)dictionary 76 | { 77 | self.imageURLArray = [NSMutableArray array]; 78 | 79 | NSArray* array = [dictionary objectForKey:@"data"]; 80 | for (NSDictionary* entryDictionary in array) 81 | { 82 | NSDictionary* images = [entryDictionary objectForKey:@"images"]; 83 | NSDictionary* standardResolutionInfo = [images objectForKey:@"standard_resolution"]; 84 | NSString* url = [standardResolutionInfo objectForKey:@"url"]; 85 | if (url) 86 | { 87 | [self.imageURLArray addObject:url]; 88 | } 89 | } 90 | 91 | [self.tableView reloadData]; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/UUInstagramaticViewController.xib: -------------------------------------------------------------------------------- 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 | 35 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Sample/UUInstagramatic/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // UUInstagramatic 4 | // 5 | // Created by Jonathan Hays on 1/17/14. 6 | // Copyright (c) 2014 Threejacks Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "UUAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([UUAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import CoreData 12 | import UUToolbox 13 | 14 | @UIApplicationMain 15 | class AppDelegate: UIResponder, UIApplicationDelegate 16 | { 17 | var window: UIWindow? 18 | 19 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 20 | { 21 | // Override point for customization after application launch. 22 | setupCoreData() 23 | return true 24 | } 25 | 26 | private func setupCoreData() 27 | { 28 | let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Library").appendingPathComponent("UUSwift.db") 29 | UUCoreData.configure(url: url) 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/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 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/HomeController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeController.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import UUToolbox 12 | 13 | class HomeTableRow : NSObject 14 | { 15 | var label : String = "" 16 | 17 | var action: () -> Void = { } 18 | 19 | required init(_ label : String, _ action: @escaping () -> Void) 20 | { 21 | super.init() 22 | self.label = label 23 | self.action = action 24 | } 25 | } 26 | 27 | class HomeController: UIViewController, UITableViewDelegate, UITableViewDataSource 28 | { 29 | @IBOutlet var tableView: UITableView! 30 | 31 | private var tableData: [HomeTableRow] = [] 32 | 33 | override func viewDidLoad() 34 | { 35 | super.viewDidLoad() 36 | 37 | tableData.append(HomeTableRow("UUWeather", loadWeather)) 38 | tableData.append(HomeTableRow("Ron Swanson Quotes", loadRSQuotes)) 39 | tableData.append(HomeTableRow("Image Gallery", loadImageGallery)) 40 | tableData.append(HomeTableRow("UUBeacon", loadBeaconView)) 41 | 42 | tableView.tableFooterView = UIView() 43 | } 44 | 45 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 46 | { 47 | return tableData.count 48 | } 49 | 50 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 51 | { 52 | let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTableCell", for: indexPath) as! HomeTableCell 53 | let cellData = tableData[indexPath.row] 54 | cell.update(cellData) 55 | return cell 56 | } 57 | 58 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 59 | { 60 | let cellData = tableData[indexPath.row] 61 | cellData.action() 62 | } 63 | 64 | private func loadWeather() 65 | { 66 | performSegue(withIdentifier: "showWeatherController", sender: nil) 67 | } 68 | 69 | private func loadRSQuotes() 70 | { 71 | performSegue(withIdentifier: "showRSQuotes", sender: nil) 72 | } 73 | 74 | private func loadImageGallery() 75 | { 76 | performSegue(withIdentifier: "showImageGallery", sender: nil) 77 | } 78 | 79 | private func loadBeaconView() 80 | { 81 | performSegue(withIdentifier: "showBeaconView", sender: nil) 82 | } 83 | } 84 | 85 | class HomeTableCell : UITableViewCell 86 | { 87 | @IBOutlet var label: UILabel! 88 | 89 | func update(_ cellData: HomeTableRow) 90 | { 91 | label.text = cellData.label 92 | } 93 | } 94 | 95 | 96 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | NSLocationAlwaysAndWhenInUseUsageDescription 29 | UUSwift uses location in the background to test location coding. 30 | NSLocationAlwaysUsageDescription 31 | UUSwift uses location in the background to test location coding. 32 | NSLocationWhenInUseUsageDescription 33 | UUSwift uses location in the background to test location coding. 34 | UIBackgroundModes 35 | 36 | bluetooth-central 37 | fetch 38 | location 39 | remote-notification 40 | 41 | UILaunchStoryboardName 42 | LaunchScreen 43 | UIMainStoryboardFile 44 | Main 45 | UIRequiredDeviceCapabilities 46 | 47 | armv7 48 | 49 | UISupportedInterfaceOrientations 50 | 51 | UIInterfaceOrientationPortrait 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/RSQuote+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RSQuote+Ext.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import CoreData 12 | import UUToolbox 13 | 14 | extension RSQuote : UUObjectFactory 15 | { 16 | public static func uuObjectFromDictionary(dictionary : [AnyHashable:Any], context: Any?) -> Self? 17 | { 18 | return uuObjectFromDictionaryInternal(dictionary: dictionary, context: context) 19 | } 20 | 21 | private static func uuObjectFromDictionaryInternal(dictionary : [AnyHashable:Any], context: Any?) -> T? 22 | { 23 | var obj : T? = nil 24 | 25 | if (context != nil && context is NSManagedObjectContext) 26 | { 27 | let moc = context as! NSManagedObjectContext 28 | moc.performAndWait 29 | { 30 | let predicate = primaryKeyPredicate(dictionary: dictionary) 31 | if (predicate != nil) 32 | { 33 | let o = uuFetchOrCreate(predicate: predicate!, context: moc) 34 | o.fillFromDictionary(dictionary) 35 | obj = o as? T 36 | } 37 | } 38 | } 39 | 40 | return obj 41 | } 42 | 43 | private static func primaryKeyPredicate(dictionary: [AnyHashable:Any]) -> NSPredicate? 44 | { 45 | let primaryKeyValue = dictionary["identifier"] as? Int 46 | if (primaryKeyValue != nil) 47 | { 48 | return NSPredicate(format: "identifier = %@", NSNumber(value: primaryKeyValue!)) 49 | } 50 | else 51 | { 52 | return nil 53 | } 54 | } 55 | 56 | private func fillFromDictionary(_ dictionary: [AnyHashable:Any]) 57 | { 58 | let df = DateFormatter.uuCachedFormatter(UUDate.Formats.rfc3339) 59 | 60 | quote = dictionary["quote"] as? String 61 | identifier = Int64(dictionary["identifier"] as! Int) 62 | downloadedAt = df.date(from: dictionary["downloadedAt"] as! String)! as Date 63 | 64 | print("parsed: \(self)") 65 | } 66 | 67 | override public var description: String 68 | { 69 | return "\(toDictionary().uuToJsonString())" 70 | } 71 | 72 | public func toDictionary() -> [String:Any] 73 | { 74 | var json : [String:Any] = [:] 75 | 76 | json["id"] = identifier 77 | json["quote"] = quote 78 | json["downloadedAt"] = (downloadedAt as Date?)?.uuRfc3339String() 79 | json["displayedAt"] = (displayedAt as Date?)?.uuRfc3339String() 80 | json["displayCount"] = displayCount 81 | 82 | return json 83 | } 84 | 85 | static func randomQuote(_ context: NSManagedObjectContext) -> Self? 86 | { 87 | return randomQuoteInternal(context) 88 | } 89 | 90 | private static func randomQuoteInternal(_ context: NSManagedObjectContext) -> T? 91 | { 92 | let predicate = NSPredicate(format: "displayCount = 0") 93 | 94 | let count = uuCountObjects(predicate: predicate, context: context) 95 | let index = arc4random_uniform(UInt32(count)) 96 | 97 | let results = uuFetchObjects(predicate: predicate, offset: Int(index), limit: 1, context: context) 98 | if (results.count > 0) 99 | { 100 | return results[0] as? T 101 | } 102 | else 103 | { 104 | return nil 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/RSQuoteController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RSQuoteController.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import UUToolbox 12 | 13 | class RSQuoteController: UIViewController 14 | { 15 | @IBOutlet var quoteLabel: UILabel! 16 | @IBOutlet var progressSpinner: UIActivityIndicatorView! 17 | 18 | override func viewDidLoad() 19 | { 20 | super.viewDidLoad() 21 | 22 | title = "Ron Swanson Quotes" 23 | quoteLabel.text = "" 24 | } 25 | 26 | override func viewWillAppear(_ animated: Bool) 27 | { 28 | super.viewWillAppear(animated) 29 | showNextQuote() 30 | } 31 | 32 | private func showNextQuote(_ clearBeforeDownload : Bool = false) 33 | { 34 | let context = UUCoreData.mainThreadContext! 35 | context.perform 36 | { 37 | let quote = RSQuote.randomQuote(context) 38 | if (quote != nil) 39 | { 40 | self.quoteLabel.text = quote?.quote 41 | 42 | quote!.displayCount = quote!.displayCount + 1 43 | quote!.displayedAt = Date() 44 | _ = context.uuSubmitChanges() 45 | } 46 | else 47 | { 48 | if (clearBeforeDownload) 49 | { 50 | RSQuote.uuDeleteObjects(context: context) 51 | _ = context.uuSubmitChanges() 52 | } 53 | 54 | self.downloadQuotes 55 | { 56 | self.showNextQuote(true) 57 | } 58 | } 59 | } 60 | } 61 | 62 | private func downloadQuotes(_ completion: @escaping ()->Void) 63 | { 64 | progressSpinner.startAnimating() 65 | 66 | RSQuoteService.shared.fetchQuotes(count: 10) 67 | { (error: Error?) in 68 | 69 | DispatchQueue.main.async 70 | { 71 | self.progressSpinner.stopAnimating() 72 | completion() 73 | } 74 | } 75 | } 76 | 77 | @IBAction func onShowAnotherQuote(_ sender: Any) 78 | { 79 | showNextQuote() 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/RSQuoteService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RSQuoteService.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import UUToolbox 12 | 13 | // 14 | // Credit for this API: 15 | // https://github.com/jamesseanwright/ron-swanson-quotes#ron-swanson-quotes-api 16 | // 17 | class RSQuoteService: NSObject 18 | { 19 | public static let shared = RSQuoteService() 20 | 21 | private var baseUrl : String = "http://ron-swanson-quotes.herokuapp.com/v2/quotes" 22 | 23 | public func fetchQuotes(count: Int = 1, completion: @escaping (Error?) -> Void) 24 | { 25 | let endpoint = "\(baseUrl)/\(count)" 26 | 27 | UUHttpSession.get(endpoint, [:]) 28 | { (response: UUHttpResponse) in 29 | 30 | if (response.httpError != nil) 31 | { 32 | completion(response.httpError) 33 | } 34 | else 35 | { 36 | let context = UUCoreData.workerThreadContext()! 37 | context.perform 38 | { 39 | let list = response.parsedResponse as? [String] 40 | 41 | if (list != nil) 42 | { 43 | for quote in list! 44 | { 45 | // Hack a dictionary together for parsing examples 46 | 47 | var d : [String:Any] = [:] 48 | d["quote"] = quote 49 | d["downloadedAt"] = (NSDate() as Date).uuRfc3339String() 50 | d["identifier"] = quote.hashValue 51 | 52 | _ = RSQuote.uuObjectFromDictionary(dictionary: d, context: context) 53 | } 54 | } 55 | 56 | _ = context.uuSubmitChanges() 57 | 58 | completion(nil) 59 | } 60 | } 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/UUSwift.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | UUSwift.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/UUSwift.xcdatamodeld/UUSwift.xcdatamodel/contents: -------------------------------------------------------------------------------- 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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/WeatherController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeatherController.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import UUToolbox 12 | 13 | class WeatherTableRow : NSObject 14 | { 15 | // Tuesday, July 3rd 2017 16 | 17 | static let kDateFormat : String = 18 | "\(UUDate.Formats.longDayOfWeek), \(UUDate.Formats.longMonthOfYear) \(UUDate.Formats.dayOfMonth) \(UUDate.Formats.fourDigitYear)" 19 | 20 | var date : Date = Date() 21 | var lowTemp : Double = 0 22 | var highTemp : Double = 0 23 | 24 | func formatDate() -> String 25 | { 26 | return date.uuFormat(WeatherTableRow.kDateFormat) 27 | } 28 | 29 | func formatTemp() -> String 30 | { 31 | return "High \(highTempAsFahrenheit) / Low \(lowTempAsFahrenheit)" 32 | } 33 | 34 | var lowTempAsFahrenheit : Double 35 | { 36 | return celsiusToFahrenheit(lowTemp) 37 | } 38 | 39 | var highTempAsFahrenheit : Double 40 | { 41 | return celsiusToFahrenheit(highTemp) 42 | } 43 | 44 | func celsiusToFahrenheit(_ celsius: Double) -> Double 45 | { 46 | return ((celsius * (9 / 5)) + 32) 47 | } 48 | } 49 | 50 | class WeatherController: UIViewController, UITableViewDelegate, UITableViewDataSource 51 | { 52 | @IBOutlet var tableView: UITableView! 53 | 54 | private var tableData: [WeatherTableRow] = [] 55 | 56 | override func viewDidLoad() 57 | { 58 | super.viewDidLoad() 59 | 60 | tableView.rowHeight = UITableViewAutomaticDimension 61 | tableView.estimatedRowHeight = 44 62 | tableView.tableFooterView = UIView() 63 | } 64 | 65 | override func viewWillAppear(_ animated: Bool) 66 | { 67 | super.viewWillAppear(animated) 68 | 69 | WeatherService.shared.fetchWeather(city: "Wilsonville", country: "United States") 70 | { (err: Error?) in 71 | 72 | print ("Weather fetch done") 73 | 74 | let context = UUCoreData.mainThreadContext! 75 | context.perform 76 | { 77 | let results = WeatherRecord.uuFetchObjects(context: context) 78 | 79 | for obj in results 80 | { 81 | let realObj = obj as? WeatherRecord 82 | if (realObj != nil) 83 | { 84 | let row = WeatherTableRow() 85 | row.lowTemp = realObj!.minTemperature 86 | row.highTemp = realObj!.maxTemperature 87 | row.date = realObj!.timestamp! as Date 88 | 89 | self.tableData.append(row) 90 | self.tableView.reloadData() 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 98 | { 99 | return tableData.count 100 | } 101 | 102 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 103 | { 104 | let cell = tableView.dequeueReusableCell(withIdentifier: "WeatherTableCell", for: indexPath) as! WeatherTableCell 105 | let cellData = tableData[indexPath.row] 106 | cell.update(cellData) 107 | return cell 108 | } 109 | } 110 | 111 | class WeatherTableCell : UITableViewCell 112 | { 113 | @IBOutlet var dateLabel: UILabel! 114 | @IBOutlet var tempLabel: UILabel! 115 | 116 | func update(_ cellData: WeatherTableRow) 117 | { 118 | dateLabel.text = cellData.formatDate() 119 | tempLabel.text = cellData.formatTemp() 120 | } 121 | 122 | } 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwift/WeatherService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeatherService.swift 3 | // UUSwift 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import UUToolbox 12 | 13 | class WeatherService: NSObject 14 | { 15 | public static let shared = WeatherService() 16 | 17 | private var apiKey : String = "6a747114c9cf80cf4d2908053cb4f8c2" 18 | private var baseUrl : String = "http://api.openweathermap.org/data/2.5" 19 | 20 | public func fetchWeather(city: String, country: String, completion: @escaping (Error?) -> Void) 21 | { 22 | var queryArgs : [String:String] = [:] 23 | queryArgs["q"] = "\(city),\(country)" 24 | queryArgs["APPID"] = apiKey 25 | 26 | let endpoint = "\(baseUrl)/weather" 27 | 28 | UUHttpSession.get(endpoint, queryArgs) 29 | { (response: UUHttpResponse) in 30 | 31 | let context = UUCoreData.workerThreadContext()! 32 | context.perform 33 | { 34 | let parsed = WeatherRecord.uuObjectFromDictionary( 35 | dictionary: (response.parsedResponse as? [AnyHashable:Any])!, context: context) 36 | 37 | print("Parsed object: \(String(describing: parsed))") 38 | 39 | _ = context.uuSubmitChanges() 40 | 41 | completion(nil) 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwiftTests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwiftTests/UUCoreDataUnitTests.xcdatamodeld/UUCoreDataUnitTests.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwiftTests/UURemoteDataTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UURemoteDataTests.swift 3 | // UURemoteDataTests 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import XCTest 11 | @testable import UUSwift 12 | 13 | class UURemoteDataTests: XCTestCase 14 | { 15 | static var isFirstTest : Bool = true 16 | 17 | private static let testUrl : String = "http://publicdomainarchive.com/?ddownload=47473" 18 | 19 | override func setUp() 20 | { 21 | super.setUp() 22 | 23 | if (UURemoteDataTests.isFirstTest) 24 | { 25 | UUDataCache.shared.clearCache() 26 | UURemoteDataTests.isFirstTest = false 27 | UUDataCache.shared.contentExpirationLength = 30 * 24 * 60 * 60 28 | } 29 | } 30 | 31 | override func tearDown() 32 | { 33 | super.tearDown() 34 | } 35 | 36 | func test_0000_FetchNoLocal() 37 | { 38 | let key = UURemoteDataTests.testUrl 39 | 40 | expectation(forNotification: NSNotification.Name(rawValue: UURemoteData.Notifications.DataDownloaded.rawValue), object: nil) 41 | { (notification: Notification) -> Bool in 42 | 43 | let md = UURemoteData.shared.metaData(for: key) 44 | XCTAssertNotNil(md) 45 | 46 | let data = UURemoteData.shared.data(for: key) 47 | XCTAssertNotNil(data) 48 | 49 | let nKey = notification.uuRemoteDataPath 50 | XCTAssertNotNil(nKey) 51 | 52 | let nErr = notification.uuRemoteDataError 53 | XCTAssertNil(nErr) 54 | 55 | return true 56 | } 57 | 58 | var data = UURemoteData.shared.data(for: key) 59 | XCTAssertNil(data) 60 | 61 | waitForExpectations(timeout: .infinity) 62 | { (err : Error?) in 63 | 64 | if (err != nil) 65 | { 66 | XCTFail("failed waiting for expectations, error: \(err!)") 67 | } 68 | } 69 | 70 | 71 | let md = UURemoteData.shared.metaData(for: key) 72 | data = UURemoteData.shared.data(for: key) 73 | XCTAssertNotNil(data) 74 | XCTAssertNotNil(md) 75 | } 76 | 77 | func test_0001_FetchFromBadUrl() 78 | { 79 | expectation(forNotification: NSNotification.Name(rawValue: UURemoteData.Notifications.DataDownloadFailed.rawValue), object: nil) 80 | 81 | let key = "http://this.is.a.fake.url/non_existent.jpg" 82 | 83 | let data = UURemoteData.shared.data(for: key) 84 | XCTAssertNil(data) 85 | 86 | waitForExpectations(timeout: .infinity) 87 | { (err : Error?) in 88 | 89 | if (err != nil) 90 | { 91 | XCTFail("failed waiting for expectations, error: \(err!)") 92 | } 93 | } 94 | } 95 | 96 | func test_0002_FetchExisting() 97 | { 98 | let key = UURemoteDataTests.testUrl 99 | 100 | let data = UURemoteData.shared.data(for: key) 101 | XCTAssertNotNil(data) 102 | } 103 | 104 | 105 | } 106 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwiftUITests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sample/UUSwift/UUSwiftUITests/UUSwiftUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUSwiftUITests.swift 3 | // UUSwiftUITests 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import XCTest 11 | 12 | class UUSwiftUITests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | 19 | // In UI tests it is usually best to stop immediately when a failure occurs. 20 | continueAfterFailure = false 21 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 22 | XCUIApplication().launch() 23 | 24 | // 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. 25 | } 26 | 27 | override func tearDown() { 28 | // Put teardown code here. This method is called after the invocation of each test method in the class. 29 | super.tearDown() 30 | } 31 | 32 | func testExample() { 33 | // Use recording to get started writing UI tests. 34 | // Use XCTAssert and related functions to verify your tests produce the correct results. 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolbox/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | uu.toolbox.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolbox/UUToolbox.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUToolbox.h 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for UUToolbox. 12 | FOUNDATION_EXPORT double UUToolboxVersionNumber; 13 | 14 | //! Project version string for UUToolbox. 15 | FOUNDATION_EXPORT const unsigned char UUToolboxVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/Helpers/XCTestCase+UUTestExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestCase+UUTestExtensions.h 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "UURandom.h" 12 | 13 | #define UUBeginAsyncTest() __block BOOL asyncTestDone = NO 14 | #define UUEndAsyncTest() asyncTestDone = YES 15 | #define UUWaitForAsyncTest() \ 16 | while (!asyncTestDone) \ 17 | { \ 18 | [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; \ 19 | } \ 20 | 21 | @interface XCTestCase (UUTestExtensions) 22 | 23 | @end 24 | 25 | @interface UURandom (ToolboxUnitTestHelpers) 26 | 27 | + (NSString*) uuRandomAsciiString:(NSUInteger)maxLength; 28 | + (NSNumber*) uuRandomNumber; 29 | + (NSNumber*) uuRandomDouble; 30 | + (id) uuRandomJsonSafeObject; 31 | 32 | + (NSMutableDictionary*) uuMakeRandomDictionary:(NSUInteger)maxChildCount; 33 | + (NSMutableArray*) uuMakeRandomArray:(NSUInteger)maxChildCount; 34 | 35 | + (NSString*) uuMakeRandomJsonString:(NSInteger)maxDepth childMax:(NSUInteger)childMax; 36 | + (NSMutableDictionary*) uuMakeRandomDictionary:(NSInteger)maxDepth childMax:(NSUInteger)childMax; 37 | 38 | + (NSMutableArray*) uuMakeRandomFakeObjectList:(NSUInteger)objectChildCount length:(NSUInteger)length; 39 | 40 | @end 41 | 42 | @interface NSData (ToolboxUnitTestHelpers) 43 | 44 | - (NSData*) uuRemoveTrailingZeros; 45 | 46 | @end 47 | 48 | @interface NSDictionary (ToolboxUnitTestHelpers) 49 | 50 | - (NSString*) toJsonString; // Defaults to zero and NSUTF8StringEncoding 51 | - (NSString*) toJsonString:(NSJSONWritingOptions)options encoding:(NSStringEncoding)encoding; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | uu.toolbox.$(PRODUCT_NAME:rfc1034identifier) 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 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUColorTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUColorTests.m 3 | // UUFrameworkTest 4 | // 5 | // Created by Ryan DeVore on 5/6/14. 6 | // 7 | // 8 | 9 | #import 10 | #import "UUColor.h" 11 | 12 | @interface UUColorTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation UUColorTests 17 | 18 | - (void)setUp 19 | { 20 | [super setUp]; 21 | // Put setup code here. This method is called before the invocation of each test method in the class. 22 | } 23 | 24 | - (void)tearDown 25 | { 26 | // Put teardown code here. This method is called after the invocation of each test method in the class. 27 | [super tearDown]; 28 | } 29 | 30 | - (void)testHexColor 31 | { 32 | //BG #a7a9ac 33 | //Text #d8d8d8 34 | 35 | // 167, 169, 172 36 | 37 | UIColor* fromHex = [UIColor uuColorFromHex:@"A7A9AC"]; 38 | 39 | CGFloat r = 0; 40 | CGFloat g = 0; 41 | CGFloat b = 0; 42 | CGFloat a = 0; 43 | [fromHex getRed:&r green:&g blue:&b alpha:&a]; 44 | 45 | UIColor* fromRGB = [UIColor uuColorWithRed:167 Green:169 Blue:172]; 46 | 47 | CGFloat r2 = 0; 48 | CGFloat g2 = 0; 49 | CGFloat b2 = 0; 50 | CGFloat a2 = 0; 51 | [fromRGB getRed:&r2 green:&g2 blue:&b2 alpha:&a2]; 52 | 53 | //XCTAssertEqual(r, r2, @"Red not equal"); 54 | //XCTAssertEqual(g, g2, @"Green not equal"); 55 | //XCTAssertEqual(b, b2, @"Blue not equal"); 56 | //XCTAssertEqual(a, a2, @"Alpha not equal"); 57 | 58 | 59 | 60 | 61 | // XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUCoreData/ModelExtensions/UUPlayer+Extensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUPlayer+Extensions.h 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import "UUPlayer.h" 10 | 11 | @interface UUPlayer (Extensions) 12 | 13 | + (void) addPlayer:(NSString*)first last:(NSString*)last team:(NSString*)team position:(NSString*)position number:(NSNumber*)number context:(NSManagedObjectContext*)context; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUCoreData/ModelExtensions/UUPlayer+Extensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUPlayer+Extensions.m 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import "UUPlayer+Extensions.h" 10 | #import "UUCoreData.h" 11 | 12 | @implementation UUPlayer (Extensions) 13 | 14 | + (void) addPlayer:(NSString*)first last:(NSString*)last team:(NSString*)team position:(NSString*)position number:(NSNumber*)number context:(NSManagedObjectContext*)context 15 | { 16 | UUPlayer* p = [NSEntityDescription insertNewObjectForEntityForName:[self uuEntityName] inManagedObjectContext:context]; 17 | p.firstName = first; 18 | p.lastName = last; 19 | p.team = team; 20 | p.position = position; 21 | p.number = number; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUCoreData/Models/UUPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUPlayer.h 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface UUPlayer : NSManagedObject 14 | 15 | @property (nonatomic, retain) NSString * firstName; 16 | @property (nonatomic, retain) NSString * lastName; 17 | @property (nonatomic, retain) NSString * position; 18 | @property (nonatomic, retain) NSNumber * number; 19 | @property (nonatomic, retain) NSString * team; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUCoreData/Models/UUPlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUPlayer.m 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import "UUPlayer.h" 10 | 11 | 12 | @implementation UUPlayer 13 | 14 | @dynamic firstName; 15 | @dynamic lastName; 16 | @dynamic position; 17 | @dynamic number; 18 | @dynamic team; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUCoreData/UUCoreDataTestModels.xcdatamodeld/UUCoreDataTestModels.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUCoreData/UUCoreDataTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUCoreDataTests.m 3 | // UUToolbox 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "UUCoreData.h" 12 | #import "UUPlayer.h" 13 | #import "UUPlayer+Extensions.h" 14 | #import "XCTestCase+UUTestExtensions.h" 15 | 16 | @interface UUCoreDataTests : XCTestCase 17 | 18 | @end 19 | 20 | @implementation UUCoreDataTests 21 | 22 | - (NSString*) databasePath 23 | { 24 | NSString* path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Library"] stringByAppendingPathComponent:@"UUCoreDataTests.db"]; 25 | return path; 26 | } 27 | 28 | - (void) deleteDatabase 29 | { 30 | NSFileManager* fm = [NSFileManager defaultManager]; 31 | NSString* path = [self databasePath]; 32 | NSError* err = nil; 33 | [fm removeItemAtPath:path error:&err]; 34 | if (err) 35 | { 36 | NSLog(@"Error deleting test database! Err: %@", err); 37 | } 38 | } 39 | 40 | - (void) setupDatabase 41 | { 42 | NSBundle* modelBundle = [NSBundle bundleForClass:[self class]]; 43 | NSString* path = [self databasePath]; 44 | NSURL* storeURL = [NSURL fileURLWithPath:path]; 45 | [UUCoreData configureWithStoreUrl:storeURL modelDefinitionBundle:modelBundle]; 46 | 47 | NSManagedObjectContext* context = [UUCoreData mainThreadContext]; 48 | [UUPlayer addPlayer:@"Troy" last:@"Aikman" team:@"Dallas Cowboys" position:@"QB" number:@(8) context:context]; 49 | [UUPlayer addPlayer:@"Emmitt" last:@"Smith" team:@"Dallas Cowboys" position:@"RB" number:@(22) context:context]; 50 | [UUPlayer addPlayer:@"Michael" last:@"Irvin" team:@"Dallas Cowboys" position:@"WR" number:@(88) context:context]; 51 | [context uuSubmitChanges]; 52 | } 53 | 54 | - (void)setUp 55 | { 56 | [super setUp]; 57 | 58 | [self deleteDatabase]; 59 | [self setupDatabase]; 60 | } 61 | 62 | - (void)tearDown 63 | { 64 | [self deleteDatabase]; 65 | 66 | [super tearDown]; 67 | } 68 | 69 | - (void) testFetchFromMainThread 70 | { 71 | BOOL isMainThread = [NSThread isMainThread]; 72 | NSManagedObjectContext* context = [UUCoreData workerThreadContext]; 73 | NSArray* results = [UUPlayer uuFetchObjectsWithPredicate:nil context:context]; 74 | XCTAssertEqual(results.count, 3, "Expect 3 objects in players table"); 75 | } 76 | 77 | - (void) testFetchFromWorkerThread 78 | { 79 | UUBeginAsyncTest(); 80 | 81 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ 82 | { 83 | BOOL isMainThread = [NSThread isMainThread]; 84 | NSManagedObjectContext* context = [UUCoreData workerThreadContext]; 85 | NSArray* results = [UUPlayer uuFetchObjectsWithPredicate:nil context:context]; 86 | XCTAssertEqual(results.count, 3, "Expect 3 objects in players table"); 87 | 88 | UUEndAsyncTest(); 89 | }); 90 | 91 | UUWaitForAsyncTest(); 92 | } 93 | 94 | - (void) testCrossThreadInsert 95 | { 96 | NSManagedObjectContext* context = [UUCoreData mainThreadContext]; 97 | [UUPlayer addPlayer:@"Tony" last:@"Romo" team:@"Dallas Cowboys" position:@"QB" number:@(9) context:context]; 98 | 99 | UUBeginAsyncTest(); 100 | 101 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ 102 | //dispatch_async(dispatch_get_main_queue(), ^ 103 | { 104 | [context uuSubmitChanges]; 105 | 106 | UUEndAsyncTest(); 107 | }); 108 | 109 | UUWaitForAsyncTest(); 110 | 111 | NSArray* results = [UUPlayer uuFetchObjectsWithPredicate:nil context:context]; 112 | XCTAssertEqual(results.count, 4, "Expect 4 objects in players table"); 113 | 114 | } 115 | 116 | /* 117 | - (void)testExample { 118 | // This is an example of a functional test case. 119 | XCTAssert(YES, @"Pass"); 120 | } 121 | 122 | - (void)testPerformanceExample { 123 | // This is an example of a performance test case. 124 | [self measureBlock:^{ 125 | // Put the code you want to measure the time of here. 126 | }]; 127 | }*/ 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUDateTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUDateTests.m 3 | // UUFrameworkTest 4 | // 5 | // Created by Ryan DeVore on 7/1/14. 6 | // 7 | // 8 | 9 | #import 10 | #import "UUDate.h" 11 | 12 | @interface UUDateTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation UUDateTests 17 | 18 | - (void)setUp 19 | { 20 | [super setUp]; 21 | // Put setup code here. This method is called before the invocation of each test method in the class. 22 | } 23 | 24 | - (void)tearDown 25 | { 26 | // Put teardown code here. This method is called after the invocation of each test method in the class. 27 | [super tearDown]; 28 | } 29 | 30 | - (void)testDateChecks 31 | { 32 | NSDate* d = [NSDate date]; 33 | BOOL result = [d uuIsToday]; 34 | XCTAssertTrue(result, @"Expect current date to be today"); 35 | 36 | result = [d uuIsYesterday]; 37 | XCTAssertFalse(result, @"Today is not yesterday"); 38 | 39 | result = [d uuIsTomorrow]; 40 | XCTAssertFalse(result, @"Today is not tomorrow"); 41 | 42 | d = [d uuAddDays:2]; 43 | result = [d uuIsTomorrow]; 44 | XCTAssertFalse(result, @"Two days from now is not tomorrow"); 45 | 46 | d = [[NSDate date] uuAddDays:-2]; 47 | result = [d uuIsTomorrow]; 48 | XCTAssertFalse(result, @"Two days ago is not yesterday"); 49 | 50 | 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UURandomTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UURandomTests.m 3 | // UUFrameworkTest 4 | // 5 | // Created by Ryan DeVore on 6/20/14. 6 | // 7 | // 8 | 9 | #import 10 | #import "UURandom.h" 11 | 12 | @interface UURandomTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation UURandomTests 17 | 18 | - (void)setUp 19 | { 20 | [super setUp]; 21 | // Put setup code here. This method is called before the invocation of each test method in the class. 22 | } 23 | 24 | - (void)tearDown 25 | { 26 | // Put teardown code here. This method is called after the invocation of each test method in the class. 27 | [super tearDown]; 28 | } 29 | 30 | - (void) testRandomSingle 31 | { 32 | int runs = 1000; 33 | 34 | for (int i = 0; i < runs; i++) 35 | { 36 | u_int32_t r = [UURandom uuRandomUInt32]; 37 | //NSLog(@"%u", r); 38 | 39 | BOOL b = [UURandom uuRandomBool]; 40 | //NSLog(@"%@", b ? @"YES" : @"NO"); 41 | 42 | NSData* buff = [UURandom uuRandomBytes:[UURandom uuRandomUInt32BetweenLow:0 high:500]]; 43 | //NSLog(@"%@", buff); 44 | 45 | #pragma unused(r) 46 | #pragma unused(b) 47 | #pragma unused(buff) 48 | } 49 | } 50 | 51 | - (void) testRandomRange 52 | { 53 | int runs = 1000; 54 | 55 | for (int i = 0; i < runs; i++) 56 | { 57 | u_int32_t min = [UURandom uuRandomUInt32]; 58 | u_int32_t max = [UURandom uuRandomUInt32]; 59 | 60 | u_int32_t r = [UURandom uuRandomUInt32BetweenLow:min high:max]; 61 | XCTAssertTrue(r >= MIN(min,max), @"Expect val to be greater than min"); 62 | XCTAssertTrue(r <= MAX(min,max), @"Expect val to be less than max"); 63 | 64 | u_int32_t not = [UURandom uuRandomUInt32]; 65 | r = [UURandom uuRandomUInt32BetweenLow:min high:max not:not]; 66 | XCTAssertTrue(r >= MIN(min,max), @"Expect val to be greater than min"); 67 | XCTAssertTrue(r <= MAX(min,max), @"Expect val to be less than max"); 68 | XCTAssertTrue(r != not, @"Expect val not to be the not value"); 69 | 70 | min = 0; 71 | max = 100; 72 | u_int32_t dist = 10; 73 | u_int32_t marker = 50; 74 | r = [UURandom uuRandomUInt32BetweenLow:min high:max atLeast:dist from:marker]; 75 | XCTAssertTrue(r >= MIN(min,max), @"Expect val to be greater than min"); 76 | XCTAssertTrue(r <= MAX(min,max), @"Expect val to be less than max"); 77 | XCTAssertTrue(r != not, @"Expect val not to be the not value"); 78 | 79 | int64_t diff = llabs((int64_t)marker - (int64_t)r); 80 | XCTAssertTrue(diff >= dist, @"Expect result to be at least %lld away from marker %u", diff, marker); 81 | } 82 | } 83 | 84 | - (void) testRandomArray 85 | { 86 | NSMutableArray* array = nil; 87 | NSUInteger index = [array uuRandomIndex]; 88 | XCTAssertEqual(0, index, @"Expect random index from nil array to be zero"); 89 | 90 | id obj = [array uuRandomElement]; 91 | XCTAssertNil(obj, @"Expect random object from nil array to be nil"); 92 | 93 | int size = 100; 94 | array = [NSMutableArray array]; 95 | for (int i = 0; i < size; i++) 96 | { 97 | [array addObject:@(i)]; 98 | } 99 | 100 | int runs = 1000; 101 | 102 | for (int i = 0; i < runs; i++) 103 | { 104 | NSUInteger index = [array uuRandomIndex]; 105 | XCTAssertTrue(index < array.count, @"Expect random index to be in valid range"); 106 | 107 | obj = [array uuRandomElement]; 108 | XCTAssertNotNil(obj, @"Expect random object from array to be non-nil"); 109 | } 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUStringTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUStringTests.m 3 | // UUFrameworkTest 4 | // 5 | // Created by Ryan DeVore on 4/18/14. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface UUStringTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation UUStringTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | //XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Test/UUToolbox/UUToolboxTests/UUToolboxTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUToolboxTests.m 3 | // UUToolboxTests 4 | // 5 | // Created by Ryan DeVore on 2/22/15. 6 | // Copyright (c) 2015 Silver Pine. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface UUToolboxTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation UUToolboxTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /UUAccessorySession.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUAccessorySession.h 3 | // Useful Utilities - Simple client for communicating with an external accessory 4 | // 5 | // Created by Ryan on 02/01/16 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | 11 | #import 12 | #import 13 | 14 | typedef void (^UUAccessoryConnectCallback)(NSError* error); 15 | typedef void (^UUAccessoryWriteDataCallback)(NSError* error); 16 | typedef void (^UUAccessoryReadDataCallback)(NSError* error, NSData* data); 17 | typedef void (^UUAccessoryPushedDataCallback)(NSData* data); 18 | 19 | @interface UUAccessorySession : NSObject 20 | 21 | - (id) initWithProtocol:(NSString*)protocol; 22 | 23 | - (BOOL) isConnected; 24 | - (void) connect:(UUAccessoryConnectCallback)completion; 25 | - (void) writeData:(NSData*)data completion:(UUAccessoryWriteDataCallback)completion; 26 | - (void) readData:(NSUInteger)count timeout:(NSTimeInterval)timeout completion:(UUAccessoryReadDataCallback)completion; 27 | 28 | // Some accessories will just push data to the phone. This provides a raw data pipe 29 | // where the accessory data will be passed along. 30 | // 31 | // NOTE: This callback will only be invoked if there is no current call to readData that 32 | // is waiting for data to come in. 33 | - (void) registerPushedDataCallback:(UUAccessoryPushedDataCallback)callback; 34 | 35 | @end 36 | 37 | 38 | 39 | 40 | extern NSString * const kUUAccessorySessionErrorDomain; 41 | 42 | typedef NS_ENUM(NSInteger, UUAccessorySessionErrorCode) 43 | { 44 | UUAccessorySessionErrorCodeBluetoothPickerError = 1000, 45 | UUAccessorySessionErrorCodeUnableToCreateAccessory, 46 | UUAccessorySessionErrorCodeUnableToAcquireInputStream, 47 | UUAccessorySessionErrorCodeUnableToOpenInputStream, 48 | UUAccessorySessionErrorCodeUnableToAcquireOutputStream, 49 | UUAccessorySessionErrorCodeUnableToOpenOutputStream, 50 | UUAccessorySessionErrorCodeNoDeviceFound, 51 | UUAccessorySessionErrorCodeNoDeviceFoundReadDataTimeout 52 | }; 53 | 54 | @interface NSError (UUAccessorySession) 55 | 56 | + (instancetype) uuAccessorySessionError:(UUAccessorySessionErrorCode)code; 57 | + (instancetype) uuAccessorySessionError:(UUAccessorySessionErrorCode)code inner:(NSError*)inner; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /UUActionSheet.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUActionSheet.h 3 | // Useful Utilities - UIActionSheet extensions 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | 10 | 11 | #import 12 | 13 | @class UUActionSheet; 14 | 15 | typedef void (^UUActionSheetDelegateBlock)(UUActionSheet* sheet, NSInteger buttonIndex); 16 | 17 | @interface UUActionSheet : NSObject 18 | 19 | // Variable list custructor for an N button Action Sheet 20 | - (instancetype) initWithTitle:(NSString*)title 21 | completion:(UUActionSheetDelegateBlock)completion 22 | cancelButton:(NSString*)cancelButton 23 | destructiveButton:(NSString*)destructiveButton 24 | otherButtons:(NSString*)button, ...; 25 | 26 | // Convenience method 27 | + (instancetype) uuTwoButtonSheet:(NSString*)title 28 | cancelButton:(NSString*)cancelButton 29 | destructiveButton:(NSString*)destructiveButton 30 | completion:(UUActionSheetDelegateBlock)completion; 31 | 32 | 33 | - (void) show; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /UUAlert.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUAlert.h 3 | // Useful Utilities - UIAlertView extensions 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@silverpine.com 9 | 10 | #import 11 | 12 | @interface UUAlertViewController : NSObject 13 | 14 | //Show a simple one button alert 15 | + (void) uuShowAlertWithTitle:(NSString*)alertTitle 16 | message:(NSString*)alertMessage 17 | buttonTitle:(NSString*)buttonTitle 18 | completionHandler:(void (^)(NSInteger buttonIndex))completionHandler; 19 | 20 | + (void) uuShowOKCancelAlert:(NSString *)title message:(NSString *)message completionHandler:(void (^)(NSInteger buttonIndex))completionHandler; 21 | + (void) uuShowOneButtonAlert:(NSString *)title message:(NSString *)message button:(NSString*)button completionHandler:(void (^)(NSInteger buttonIndex))completionHandler; 22 | + (void) uuShowTwoButtonAlert:(NSString *)title message:(NSString *)message buttonOne:(NSString*)buttonOne buttonTwo:(NSString*)buttonTwo completionHandler:(void (^)(NSInteger buttonIndex))completionHandler; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /UUAwsS3Client.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUAwsS3Client.h 3 | // Useful Utilities - Lightweight Wrapper for Amazon S3 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // This file requires the AWSS3 and AWSRuntime frameworks 9 | 10 | #import 11 | #import 12 | 13 | typedef void (^UUAwsS3UploadCompletionHandler)(NSString* resourceUrl, NSError* error); 14 | typedef void (^UUAwsS3UploadProgressHandler)(float percent); 15 | 16 | @interface UUAwsS3Client : NSObject 17 | 18 | // Should be called prior to any usage. 19 | + (void) init:(NSString*)accessId key:(NSString*)key bucket:(NSString*)bucket; 20 | 21 | // Uploads a single file to Amazon S3. File access is set to public read 22 | // so the returned URL can be used. 23 | + (UUAwsS3Client*) uploadFile:(NSData*)data 24 | fileName:(NSString*)fileName 25 | contentType:(NSString*)contentType 26 | progress:(UUAwsS3UploadProgressHandler)progress 27 | completion:(UUAwsS3UploadCompletionHandler)completion; 28 | 29 | @end -------------------------------------------------------------------------------- /UUCameraView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUCameraView.h 3 | // Useful Utilities - UUCameraView custom camera drop in view 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | 10 | #import 11 | 12 | #import 13 | #import 14 | 15 | #define kUUFlashOff 0 16 | #define kUUFlashOn 1 17 | #define kUUFlashAuto 2 18 | 19 | @protocol UUCameraDelegate 20 | @optional 21 | - (void) photoReady:(NSDate*)imageData; 22 | @end 23 | 24 | @interface UUCameraView : UIView 25 | 26 | - (void) startSession; 27 | - (void) stopSession; 28 | 29 | - (void) setFocusPoint:(CGPoint)focalPoint; 30 | 31 | - (void) setZoomValue:(CGFloat)zoom; 32 | 33 | - (void) setToBackFacingCamera; 34 | - (void) setToFrontFacingCamera; 35 | 36 | - (void) takePicture; 37 | 38 | - (void) setCameraFrame:(CGRect)frame; 39 | - (void) setCameraOrientation:(UIInterfaceOrientation)orientation; 40 | 41 | @property (assign) bool torchOn; 42 | @property (assign) int flashMode; 43 | 44 | @property (nonatomic, assign) NSObject* delegate; 45 | 46 | @end -------------------------------------------------------------------------------- /UUColor.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUColor.h 3 | // Useful Utilities - Extensions for conveniently creating colors 4 | // 5 | // Created by Jonathan on 7/29/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import 13 | 14 | @interface UIColor (UUColorCreation) 15 | 16 | + (UIColor*) uuColorFromHex:(NSString*)color; 17 | + (UIColor*) uuColorWithRed:(int)red Green:(int)green Blue:(int)blue; 18 | 19 | @end -------------------------------------------------------------------------------- /UUColor.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUColor.m 3 | // Useful Utilities - Extensions for conveniently creating colors 4 | // 5 | // Created by Jonathan on 7/29/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import "UUColor.h" 13 | 14 | @implementation UIColor (UUColorCreation) 15 | 16 | + (UIColor*) uuColorFromHex:(NSString*)color 17 | { 18 | CGFloat rgba[4] = {0, 0, 0, 1}; 19 | 20 | if (color && (color.length == 6 || color.length == 8)) 21 | { 22 | for (int i = 0; i < color.length; i += 2) 23 | { 24 | NSScanner* sc = [NSScanner scannerWithString:(NSString*)[color substringWithRange:NSMakeRange(i, 2)]]; 25 | unsigned int hex = 0; 26 | [sc scanHexInt:&hex]; 27 | rgba[i/2] = (hex / 255.0f); 28 | } 29 | } 30 | 31 | UIColor* c = [UIColor colorWithRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]; 32 | return c; 33 | } 34 | 35 | + (UIColor*) uuColorWithRed:(int)red Green:(int)green Blue:(int)blue 36 | { 37 | return [UIColor colorWithRed:(float)red / 255.0 green:(float)green / 255.0 blue:(float)blue / 255.0 alpha:1.0]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /UUCompression.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUCompression.h 3 | // Useful Utilities - Compression extensions 4 | // 5 | // Smile License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, UUCompressionAlgorithm) 12 | { 13 | UUCompressionAlgorithmRaw, 14 | UUCompressionAlgorithmZlib, 15 | UUCompressionAlgorithmGZip, 16 | }; 17 | 18 | typedef NS_ENUM(NSUInteger, UUCompressionLevel) 19 | { 20 | UUCompressionLevelNone = 0, 21 | UUCompressionLevelFastest = 1, 22 | UUCompressionLevelBest = 9, 23 | }; 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | // Data Compression 27 | @interface NSData (UUDataCompression) 28 | 29 | // Performs an in-memory compression of the data using the algorithm specified. 30 | - (NSData*) uuCompress:(UUCompressionAlgorithm)algorithm level:(UUCompressionLevel)level; 31 | 32 | // Performs an automatic decompression of the data using automatic algorithm detection. 33 | - (NSData*) uuDecompress; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /UUData.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUData.h 3 | // Useful Utilities - extensions for NSData and NSMutableData 4 | // 5 | // Created by Ryan on 02/01/16 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | 11 | #import 12 | 13 | @interface NSData (UUToolbox) 14 | 15 | - (UInt8) uuUInt8AtIndex:(NSUInteger)index; 16 | - (UInt16) uuUInt16AtIndex:(NSUInteger)index; 17 | - (UInt32) uuUInt32AtIndex:(NSUInteger)index; 18 | - (UInt64) uuUInt64AtIndex:(NSUInteger)index; 19 | 20 | - (SInt8) uuSInt8AtIndex:(NSUInteger)index; 21 | - (SInt16) uuSInt16AtIndex:(NSUInteger)index; 22 | - (SInt32) uuSInt32AtIndex:(NSUInteger)index; 23 | - (SInt64) uuSInt64AtIndex:(NSUInteger)index; 24 | 25 | - (NSData*) uuDataAtIndex:(NSUInteger)index count:(NSUInteger)count; 26 | 27 | - (NSString*) uuStringAtIndex:(NSUInteger)index count:(NSUInteger)count encoding:(NSStringEncoding)encoding; 28 | 29 | - (NSString*) uuToHexString; 30 | 31 | @end 32 | 33 | @interface NSMutableData (UUToolbox) 34 | 35 | - (void) uuAppendUInt8:(UInt8)data; 36 | - (void) uuAppendUInt16:(UInt16)data; 37 | - (void) uuAppendUInt32:(UInt32)data; 38 | - (void) uuAppendUInt64:(UInt64)data; 39 | 40 | - (void) uuAppendSInt8:(SInt8)data; 41 | - (void) uuAppendSInt16:(SInt16)data; 42 | - (void) uuAppendSInt32:(SInt32)data; 43 | - (void) uuAppendSInt64:(SInt64)data; 44 | 45 | - (void) uuAppendString:(NSString*)data encoding:(NSStringEncoding)encoding; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /UUData.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUData.m 3 | // Useful Utilities - extensions for NSData and NSMutableData 4 | // 5 | // Created by Ryan on 02/01/16 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | 11 | #import "UUData.h" 12 | 13 | @implementation NSData (UUToolbox) 14 | 15 | - (UInt8) uuUInt8AtIndex:(NSUInteger)index 16 | { 17 | UInt8 data = 0; 18 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 19 | return data; 20 | } 21 | 22 | - (UInt16) uuUInt16AtIndex:(NSUInteger)index 23 | { 24 | UInt16 data = 0; 25 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 26 | return data; 27 | } 28 | 29 | - (UInt32) uuUInt32AtIndex:(NSUInteger)index 30 | { 31 | UInt32 data = 0; 32 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 33 | return data; 34 | } 35 | 36 | - (UInt64) uuUInt64AtIndex:(NSUInteger)index 37 | { 38 | UInt64 data = 0; 39 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 40 | return data; 41 | } 42 | 43 | - (SInt8) uuSInt8AtIndex:(NSUInteger)index 44 | { 45 | SInt8 data = 0; 46 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 47 | return data; 48 | } 49 | 50 | - (SInt16) uuSInt16AtIndex:(NSUInteger)index 51 | { 52 | SInt16 data = 0; 53 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 54 | return data; 55 | } 56 | 57 | - (SInt32) uuSInt32AtIndex:(NSUInteger)index 58 | { 59 | SInt32 data = 0; 60 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 61 | return data; 62 | } 63 | 64 | - (SInt64) uuSInt64AtIndex:(NSUInteger)index 65 | { 66 | SInt64 data = 0; 67 | [[self subdataWithRange:NSMakeRange(index, sizeof(data))] getBytes:&data length:sizeof(data)]; 68 | return data; 69 | } 70 | 71 | - (NSData*) uuDataAtIndex:(NSUInteger)index count:(NSUInteger)count 72 | { 73 | return [self subdataWithRange:NSMakeRange(index, count)]; 74 | } 75 | 76 | - (NSString*) uuStringAtIndex:(NSUInteger)index count:(NSUInteger)count encoding:(NSStringEncoding)encoding 77 | { 78 | NSData* subData = [self uuDataAtIndex:index count:count]; 79 | return [[NSString alloc] initWithData:subData encoding:encoding]; 80 | } 81 | 82 | - (NSString*) uuToHexString 83 | { 84 | NSMutableString* sb = [NSMutableString string]; 85 | 86 | const char* rawData = [self bytes]; 87 | int count = (int)self.length; 88 | for (int i = 0; i < count; i++) 89 | { 90 | [sb appendFormat:@"%02X", (UInt8)rawData[i]]; 91 | } 92 | 93 | return sb; 94 | } 95 | 96 | @end 97 | 98 | 99 | @implementation NSMutableData (UUToolbox) 100 | 101 | - (void) uuAppendUInt8:(UInt8)data 102 | { 103 | [self appendBytes:&data length:sizeof(data)]; 104 | } 105 | 106 | - (void) uuAppendUInt16:(UInt16)data 107 | { 108 | [self appendBytes:&data length:sizeof(data)]; 109 | } 110 | 111 | - (void) uuAppendUInt32:(UInt32)data 112 | { 113 | [self appendBytes:&data length:sizeof(data)]; 114 | } 115 | 116 | - (void) uuAppendUInt64:(UInt64)data 117 | { 118 | [self appendBytes:&data length:sizeof(data)]; 119 | } 120 | 121 | - (void) uuAppendSInt8:(SInt8)data 122 | { 123 | [self appendBytes:&data length:sizeof(data)]; 124 | } 125 | 126 | - (void) uuAppendSInt16:(SInt16)data 127 | { 128 | [self appendBytes:&data length:sizeof(data)]; 129 | } 130 | 131 | - (void) uuAppendSInt32:(SInt32)data 132 | { 133 | [self appendBytes:&data length:sizeof(data)]; 134 | } 135 | 136 | - (void) uuAppendSInt64:(SInt64)data 137 | { 138 | [self appendBytes:&data length:sizeof(data)]; 139 | } 140 | 141 | - (void) uuAppendString:(NSString*)data encoding:(NSStringEncoding)encoding 142 | { 143 | if (data != nil) 144 | { 145 | [self appendData:[data dataUsingEncoding:encoding]]; 146 | } 147 | } 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /UUDataCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUDataCache.h 3 | // Useful Utilities - UUDataCache for commonly fetched data from URL's 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | 10 | #import 11 | 12 | @interface UUDataCache : NSObject 13 | 14 | + (NSData*) uuDataForURL:(NSURL*)url; 15 | + (void) uuCacheData:(NSData*)data forURL:(NSURL*)url; 16 | + (void) uuClearCacheForURL:(NSURL*)url; 17 | + (void) uuSetCacheExpirationLength:(NSTimeInterval)seconds; 18 | + (void) uuClearCacheContents; 19 | + (void) uuPurgeExpiredContent; 20 | + (void) uuPurgeContentAboveSize:(unsigned long long)purgeFileSize; 21 | + (BOOL) uuDoesCachedFileExistForURL:(NSURL*)url; 22 | 23 | + (UUDataCache*) sharedCache; 24 | 25 | // If you want to use UUDataCache as an NSCache or NSMutableDictionary replacement 26 | - (id) objectForKey:(id)key; 27 | - (void) setObject:(id)object forKey:(id)key; 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /UUDebug.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUDebug.h 3 | // Useful Utilities - UUDebug for displaying logging output to an external screen either via AirPlay or a cable 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Usage: 9 | // 1. To begin monitoring for attached secondary screens, make sure to first call [UUDebug uuEnableSecondScreenLogging]; 10 | // All subsequent calls in UUDebug will not display until the second screen has been enabled. 11 | // 2. To continually display all NSLog calls to the second screen, use [UUDebug uuStartContinuousLogging]; 12 | // 3. To display one time, the most recent calls to NSLog, call [UUDebug uuDisplayLogStatements]; 13 | // 4. To display your own custom text output, call [UUDebug uuSetSecondScreenText:@"My output"]; 14 | // 5. If you use uuDisplayLogStatement or uuSetSecondScreenText, make sure that you did not start the continuous debug logging 15 | // because they will end up getting overwritten by the continuous log monitoring 16 | // 17 | // Questions/comments/complaints: 18 | // contact: @cheesemaker or jon@threejacks.com 19 | 20 | #import 21 | 22 | @interface UUDebug : NSObject 23 | + (void) uuEnableSecondScreenLogging; 24 | + (void) uuDisableSecondScreenLogging; 25 | 26 | 27 | + (void) uuDisplayLogStatements; 28 | 29 | + (void) uuStartContinuousDebugLogging; 30 | + (void) uuStopContinuousDebugLogging; 31 | 32 | + (void) uuSetSecondScreenText:(NSString*)output; 33 | @end 34 | -------------------------------------------------------------------------------- /UUDevice.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUDevice.h 3 | // Apple has announced it will stop accepting Apps that use the old UIDevice uniqueIdentifier aka UDID. This is a drop in replacement. 4 | // On iOS 6.0.1 and greater, it will use the new identifierForVendor but for previous OS versions it will create a unique identifier 5 | // and persist it using user defaults and the Pasteboard which will allow it to survive App deletions, reboots and OS upgrades. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Questions/comments/complaints: 11 | // contact: @cheesemaker or jon@threejacks.com 12 | 13 | #import 14 | 15 | @interface UIDevice(UUDevice) 16 | - (NSString*) uuUniqueIdentifier; 17 | @end 18 | -------------------------------------------------------------------------------- /UUDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUDictionary.h 3 | // Useful Utilities - Extensions for NSDictionary 4 | // 5 | // Created by Ryan DeVore on 4/18/14. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | // 12 | 13 | #import 14 | 15 | @interface NSDictionary (UUDictionary) 16 | 17 | // Safely get the object at the specified key. If the object is NSNull, then 18 | // nil will be returned. 19 | - (id) uuSafeGet:(NSString*)key; 20 | 21 | // Safely gets an object and verifies it is of the expected class type. If 22 | // the value is NSNull or not of the expecting type, nil will be returned 23 | - (id) uuSafeGet:(NSString*)key forClass:(Class)forClass; 24 | 25 | // Safely gets an object and verifies it is of the expected class type. If the 26 | // value is NSNull or not of the expected type, the passed in default will be 27 | // returned. 28 | - (id) uuSafeGet:(NSString*)key forClass:(Class)forClass defaultValue:(id)defaultValue; 29 | 30 | // Safely gets an NSNumber. If the value is an NSString, this method will 31 | // attempt to convert it to a number object using NSNumberFormatter 32 | - (NSNumber*) uuSafeGetNumber:(NSString*)key; 33 | - (NSNumber*) uuSafeGetNumber:(NSString*)key defaultValue:(NSNumber*)defaultValue; 34 | 35 | // Safely gets an NSString 36 | - (NSString*) uuSafeGetString:(NSString*)key; 37 | - (NSString*) uuSafeGetString:(NSString*)key defaultValue:(NSString*)defaultValue; 38 | 39 | // Safely gets a string object and formats is as an NSDate using the 40 | // specified NSDateFormatter 41 | - (NSDate*) uuSafeGetDate:(NSString*)key formatter:(NSDateFormatter*)formatter; 42 | 43 | // Convenience wrappers 44 | - (NSDictionary*) uuSafeGetDictionary:(NSString*)key; 45 | - (NSArray*) uuSafeGetArray:(NSString*)key; 46 | - (NSData*) uuSafeGetData:(NSString*)key; 47 | - (NSData*) uuSafeGetData:(NSString*)key defaultValue:(NSData*)defaultValue; 48 | 49 | - (NSData*) uuSafeGetDataFromBase64String:(NSString*)key; 50 | 51 | @end 52 | 53 | 54 | @interface NSDictionary (UUHttpDictionary) 55 | 56 | // Builds a formatted query string from the dictionary arguments. Only handles 57 | // value objects that are NSNumber or NSString. 58 | - (NSString*) uuBuildQueryString; 59 | 60 | - (NSString*) uuToJsonString; 61 | 62 | - (NSData*) uuToJson; 63 | 64 | @end 65 | 66 | @interface NSMutableDictionary (UUMutableDictionary) 67 | 68 | - (void) uuSafeSetValue:(id)value forKey:(NSString*)key; 69 | 70 | - (void) uuSafeRemove:(id)key; 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /UUDoubleSliderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUDoubleSliderView.h 3 | // Useful Utilities - A replacement for the UISliderView that can have both ends adjusted 4 | // 5 | // Created by Jonathan Hays on 6/02/15. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | // 12 | 13 | #import 14 | 15 | @class UUDoubleSliderView; 16 | 17 | @protocol UUDoubleSliderViewDelegate 18 | @optional 19 | - (void) minSliderValuesChanged:(UUDoubleSliderView*)slider value:(float)value; 20 | - (void) maxSliderValuesChanged:(UUDoubleSliderView*)slider value:(float)value; 21 | @end 22 | 23 | IB_DESIGNABLE 24 | // UUDoubleSliderView supports layout and preview in Interface Builder. You can create it by hand with 25 | // initWithFrame, but it's much easier to do it in IB. 26 | // The only thing not supported directly in IB is setting the delegate which currently isn't supported 27 | // by Xcode. Perhaps in the future that will, but for now, make sure you set the delegate. 28 | @interface UUDoubleSliderView : UIView 29 | 30 | - (id) initWithFrame:(CGRect)frame sliderColor:(UIColor*)sliderColor 31 | backgroundColor:(UIColor*)backgroundColor 32 | leftSlider:(UIImage*)leftSlider 33 | rightSlider:(UIImage*)rightSlider; 34 | 35 | // Default values are 0.0 and 100.0 36 | @property (nonatomic, assign) IBInspectable float minimumValue; 37 | @property (nonatomic, assign) IBInspectable float maximumValue; 38 | @property (nonatomic, assign) IBInspectable float minimumSliderValue; 39 | @property (nonatomic, assign) IBInspectable float maximumSliderValue; 40 | 41 | //Customization of the slider bar 42 | @property (nonatomic, assign) IBInspectable float sliderHeight; 43 | @property (nonatomic, assign) IBInspectable UIColor* sliderColor; 44 | @property (nonatomic, assign) IBInspectable UIColor* sliderBackgroundColor; 45 | @property (nonatomic, assign) IBInspectable UIImage* leftSliderImage; 46 | @property (nonatomic, assign) IBInspectable UIImage* rightSliderImage; 47 | 48 | 49 | // Delegate for slider notifications 50 | @property (nonatomic, assign) IBOutlet NSObject* delegate; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /UUDropbox.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUDropbox.h 3 | // Photos+ 4 | // 5 | // Created by Jonathan Hays on 2/3/14. 6 | // Copyright (c) 2014 Second Gear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DBMetadata; 12 | 13 | extern NSString *const kUUDropBoxDestFileKey; 14 | extern NSString *const kUUDropBoxDownloadProgressKey; 15 | extern NSString *const kUUDropBoxFileDownloadProgressNotification; 16 | extern NSString *const kUUDropBoxFileDownloadFinishedNotification; 17 | 18 | @interface UUDropBox : NSObject 19 | 20 | //Account setup 21 | - (void) initialize:(NSString*)appKey withSecret:(NSString*)appSecret; 22 | - (NSString*) userName; 23 | - (long long) bytesUsed; 24 | - (long long) bytesAvailable; 25 | - (BOOL) isLinked; 26 | - (void) link:(UIViewController*)parent completion:(void (^)(BOOL authorized))completionHandler; 27 | - (void) unlink; 28 | 29 | //Load the full, raw DBMetadata for a folder 30 | - (void) loadMetaDataForFolder:(NSString*)path 31 | completionHandler:(void (^)(BOOL success, DBMetadata* subfolders))completionHandler; 32 | 33 | //Given a path, enumerate the folders - NOT recursive 34 | - (void) enumerateFolders:(NSString*)path 35 | completionHandler:(void (^)(BOOL success, NSArray* subfolders))completionHandler; 36 | 37 | //Given a path, enumerate the images - NOT recursive 38 | - (void) enumerateImagesInFolder:(NSString*)path 39 | completionHandler:(void (^)(BOOL success, NSArray* imagePaths))completionHandler; 40 | 41 | 42 | //The destination path needs to exist, and the variable passed in needs to include the file name 43 | - (void) loadThumbnail:(NSString*)dropBoxPath 44 | to:(NSString*)destinationPathAndFileName 45 | completion:(void (^)(BOOL success, NSString* destinationPath, NSDate* lastModified))completionHandler; 46 | 47 | 48 | //The destination path needs to exist, and the variable passed in needs to include the file name 49 | - (void) loadFile:(NSString*)dropBoxPath 50 | to:(NSString*)destination 51 | completion:(void (^)(BOOL success, NSString* destinationPath, NSDate* lastModified))completionHandler; 52 | 53 | 54 | //URL Callback support. Make sure to call appropriately for your AppDelegate 55 | - (BOOL) handleURL:(NSURL*)url; 56 | 57 | - (NSDate*) dateOfRemoteFile:(NSString*)dropBoxPath; 58 | 59 | - (void) cancelAllRequests; 60 | 61 | + (UUDropBox*) sharedInstance; 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /UUFlickr.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUFlickr 3 | // Useful Utilities - Useful functions to interact with Flickr 4 | // (c) Copyright Jonathan Hays, all rights reserved 5 | // 6 | // License: 7 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 8 | // 9 | // Contact: @cheesemaker or jon@threejacks.com 10 | 11 | #import 12 | 13 | @interface UUFlickr : NSObject 14 | 15 | + (void) initializeKey:(NSString*)key secret:(NSString*)secret callbackURL:(NSString*)callbackURL; 16 | + (void) authenticate:(UIViewController*)parent completionHandler:(void (^)(BOOL success, NSError* error))completionBlock; 17 | + (NSString*) userName; 18 | + (void) logout; 19 | 20 | + (void) getUserMedia:(void (^)(BOOL success, NSArray* userMedia))completionBlock; 21 | + (void) getPhotoSetMedia:(NSString*)photoSetId completionBlock:(void (^)(BOOL success, NSArray* userMedia))completionBlock; 22 | + (void) getUserPhotoSets:(void (^)(BOOL success, NSArray* photoSets))completionBlock; 23 | + (void) getUserPhotoCount:(void (^)(BOOL success, NSInteger count))completionBlock; 24 | 25 | // Call this from your App Delegate 26 | + (BOOL) handleURLCallback:(NSURL*)url; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /UUGradientView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUGradientView.h 3 | // Useful Utilities - Handy helpers for a custom gradient view 4 | // 5 | // Created by Ryan DeVore on 12/31/15. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | 11 | #import 12 | 13 | IB_DESIGNABLE @interface UUGradientView : UIView 14 | 15 | @property (nonatomic, strong) IBInspectable UIColor* leftColor; 16 | @property (nonatomic, strong) IBInspectable UIColor* rightColor; 17 | @property (nonatomic, assign) IBInspectable CGFloat midPoint; 18 | 19 | @end -------------------------------------------------------------------------------- /UUGradientView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUGradientView.m 3 | // Useful Utilities - Handy helpers for a custom gradient view 4 | // 5 | // Created by Ryan DeVore on 12/31/15. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | 11 | #import "UUGradientView.h" 12 | 13 | @interface UUGradientView () 14 | 15 | @end 16 | 17 | @implementation UUGradientView 18 | 19 | - (id)initWithFrame:(CGRect)frame 20 | { 21 | self = [super initWithFrame:frame]; 22 | if (self) 23 | { 24 | // Initialization code 25 | self.leftColor = [UIColor clearColor]; 26 | self.rightColor = [UIColor clearColor]; 27 | self.midPoint = 0.5f; 28 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 29 | self.opaque = NO; 30 | } 31 | return self; 32 | } 33 | 34 | - (void) setLeftColor:(UIColor *)leftColor 35 | { 36 | _leftColor = leftColor; 37 | [self setNeedsDisplay]; 38 | } 39 | 40 | - (void) setRightColor:(UIColor *)rightColor 41 | { 42 | _rightColor = rightColor; 43 | [self setNeedsDisplay]; 44 | } 45 | 46 | - (void) setMidPoint:(CGFloat)midPoint 47 | { 48 | _midPoint = midPoint; 49 | [self setNeedsDisplay]; 50 | } 51 | 52 | - (void)drawRect:(CGRect)rect 53 | { 54 | CGContextRef context = UIGraphicsGetCurrentContext(); 55 | 56 | CGFloat leftColors[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 57 | [self.leftColor getRed:&leftColors[0] green:&leftColors[1] blue:&leftColors[2] alpha:&leftColors[3]]; 58 | 59 | CGFloat rightColors[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 60 | [self.rightColor getRed:&rightColors[0] green:&rightColors[1] blue:&rightColors[2] alpha:&rightColors[3]]; 61 | 62 | CGFloat midRed = (leftColors[0] + rightColors[0]) / 2.0f; 63 | CGFloat midGreen = (leftColors[1] + rightColors[1]) / 2.0f; 64 | CGFloat midBlue = (leftColors[2] + rightColors[2]) / 2.0f; 65 | CGFloat midAlpha = (leftColors[3] + rightColors[3]) / 2.0f; 66 | 67 | UIColor* midColor = [UIColor colorWithRed:midRed green:midGreen blue:midBlue alpha:midAlpha]; 68 | 69 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 70 | CGFloat locations[] = { 0.0, self.midPoint, 1.0 }; 71 | 72 | NSArray *colors = @[(__bridge id) self.leftColor.CGColor, (__bridge id) midColor.CGColor, (__bridge id) self.rightColor.CGColor]; 73 | 74 | CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations); 75 | 76 | CGPoint startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMidY(rect)); 77 | CGPoint endPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMidY(rect)); 78 | 79 | CGContextSaveGState(context); 80 | CGContextAddRect(context, rect); 81 | CGContextClip(context); 82 | CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); 83 | CGContextRestoreGState(context); 84 | 85 | CGGradientRelease(gradient); 86 | CGColorSpaceRelease(colorSpace); 87 | } 88 | 89 | @end -------------------------------------------------------------------------------- /UUHttpResponseHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUHttpResponseHandler.h 3 | // Useful Utilities - HTTP response de-serialization protocol 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | // 10 | 11 | #import 12 | 13 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | // Currently supported HTTP verbs 15 | typedef enum 16 | { 17 | UUHttpMethodGet, 18 | UUHttpMethodPut, 19 | UUHttpMethodPost, 20 | UUHttpMethodDelete, 21 | UUHttpMethodHead, 22 | UUHttpMethodPatch, 23 | } UUHttpMethod; 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | // Common HTTP response Codes 27 | typedef enum 28 | { 29 | UUHttpResponseCodeOK = 200, 30 | UUHttpResponseCodeCreated = 201, 31 | 32 | } UUHttpResponseCode; 33 | 34 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | // HTTP String Constants 36 | 37 | extern NSString * const kUUContentTypeApplicationJson; 38 | extern NSString * const kUUContentTypeTextJson; 39 | extern NSString * const kUUContentTypeTextHtml; 40 | extern NSString * const kUUContentTypeTextPlain; 41 | extern NSString * const kUUContentTypeBinary; 42 | extern NSString * const kUUContentTypeImagePng; 43 | extern NSString * const kUUContentTypeImageJpeg; 44 | 45 | extern NSString * const kUUContentLengthHeader; 46 | extern NSString * const kUUContentTypeHeader; 47 | extern NSString * const kUUAcceptHeader; 48 | extern NSString * const kUUHttpMethodGet; 49 | extern NSString * const kUUHttpMethodPut; 50 | extern NSString * const kUUHttpMethodPost; 51 | extern NSString * const kUUHttpMethodDelete; 52 | extern NSString * const kUUHttpMethodHead; 53 | extern NSString * const kUUHttpMethodPatch; 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | // Register response handlers to construct objects from mime types 57 | @protocol UUHttpResponseHandler 58 | @required 59 | - (NSArray*) supportedMimeTypes; 60 | - (id) parseResponse:(NSData*)rxBuffer response:(NSHTTPURLResponse*)response forRequest:(NSURLRequest*)request; 61 | @end 62 | 63 | 64 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65 | // Built-in response handlers 66 | @interface UUTextResponseHandler : NSObject 67 | @end 68 | 69 | @interface UUBinaryResponseHandler : NSObject 70 | @end 71 | 72 | @interface UUJsonResponseHandler : NSObject 73 | @end 74 | 75 | @interface UUImageResponseHandler : NSObject 76 | @end 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /UUImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUImage.h 3 | // Useful Utilities - UIImage extensions 4 | // 5 | // Created by Jonathan on 3/11/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import 13 | 14 | @interface UIImage (UUFramework) 15 | 16 | - (UIImage*) uuRemoveOrientation; 17 | - (UIImage*) uuScaleToSize:(CGSize)targetSize; 18 | - (UIImage*) uuScaleAndCropToSize:(CGSize)targetSize; 19 | - (UIImage*) uuCropToSize:(CGSize)targetSize; 20 | - (UIImage*) uuBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; 21 | 22 | + (UIImage*) uuViewToImage:(UIView*)view; 23 | 24 | - (UIImage*) uuScaleToWidth:(CGFloat)width; 25 | - (UIImage*) uuScaleToHeight:(CGFloat)height; 26 | 27 | // Picks the smaller of height or width and scales the image 28 | - (UIImage*) uuScaleSmallestDimensionToSize:(CGFloat)size; 29 | 30 | - (CGSize) uuCalculateScaleToWidthDestSize:(CGFloat)width; 31 | - (CGSize) uuCalculateScaleToHeightDestSize:(CGFloat)height; 32 | - (CGSize) uuCalculateScaleToFitDestSize:(CGFloat)size; 33 | 34 | // Pure math functions handy to use in layout methods 35 | + (CGSize) uuCalculateScaleToWidthDestSize:(CGFloat)width fromSize:(CGSize)srcSize; 36 | + (CGSize) uuCalculateScaleToHeightDestSize:(CGFloat)height fromSize:(CGSize)srcSize; 37 | 38 | + (UIImage*) uuMakeStretchableImage:(NSString*)imageName insets:(UIEdgeInsets)insets; 39 | 40 | + (UIImage*) uuSolidColorImage:(UIColor*)color; 41 | + (UIImage*) uuSolidColorImage:(UIColor*)color cornerRadius:(CGFloat)cornerRadius borderColor:(UIColor*)borderColor borderWidth:(CGFloat)borderWidth; 42 | 43 | + (UIImage*) uuSolidColorImage:(UIColor*)color 44 | cornerRadius:(CGFloat)cornerRadius 45 | borderColor:(UIColor*)borderColor 46 | borderWidth:(CGFloat)borderWidth 47 | roundedCorners:(UIRectCorner)roundedCorners; 48 | 49 | @end 50 | 51 | 52 | @interface UIImage (UUAnimatedGIF) 53 | 54 | + (UIImage*) uuImageWithGIFData:(NSData*)data; 55 | 56 | @end -------------------------------------------------------------------------------- /UUImageCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUImageCache.h 3 | // Useful Utilities - An easy to use UIImage cache 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | // 10 | // UUImageCache is an extension of UURemoteData that saves a UIImage 11 | // and CGSize in the UURemoteData meta data cache. 12 | 13 | @import UIKit; 14 | 15 | @interface UUImageCache : NSObject 16 | 17 | + (instancetype) sharedInstance; 18 | 19 | // Controls whether UURemoteData will fetch the image from its remote location or 20 | // just look locally in UUDataCache. Defaults to YES 21 | @property (assign) BOOL remoteFetchEnabled; 22 | 23 | - (NSValue*) imageSizeForPath:(NSString*)path; 24 | - (UIImage*) imageForPath:(NSString*)path; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /UUImageCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUImageCache.m 3 | // Useful Utilities - An easy to use UIImage cache 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | // 10 | 11 | #import "UUImageCache.h" 12 | #import "UUDataCache.h" 13 | #import "UUDictionary.h" 14 | #import "UURemoteData.h" 15 | 16 | NSString * const kUUImageCacheMetaDataSizeKey = @"UUImageCacheMetaDataSize"; 17 | NSString * const kUUImageCacheMetaDataImageKey = @"UUImageCacheMetaDataImage"; 18 | 19 | @interface UUImageCache () 20 | 21 | @end 22 | 23 | @implementation UUImageCache 24 | 25 | + (instancetype) sharedInstance 26 | { 27 | static id theSharedObject = nil; 28 | static dispatch_once_t onceToken; 29 | 30 | dispatch_once (&onceToken, ^ 31 | { 32 | theSharedObject = [[[self class] alloc] init]; 33 | }); 34 | 35 | return theSharedObject; 36 | } 37 | 38 | - (id) init 39 | { 40 | self = [super init]; 41 | 42 | if (self) 43 | { 44 | self.remoteFetchEnabled = YES; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (NSValue*) imageSizeForPath:(NSString*)path 51 | { 52 | NSValue* imageSize = nil; 53 | 54 | NSDictionary* metaData = [[UURemoteData sharedInstance] metaDataForPath:path]; 55 | if (metaData) 56 | { 57 | imageSize = [metaData uuSafeGet:path forClass:[NSValue class]]; 58 | } 59 | 60 | if (!imageSize) 61 | { 62 | // imageForPath will update the image size cache if needed 63 | UIImage* img = [self imageForPath:path remoteDownloadIfNeeded:NO]; 64 | if (img) 65 | { 66 | imageSize = [NSValue valueWithCGSize:img.size]; 67 | } 68 | } 69 | 70 | return imageSize; 71 | } 72 | 73 | - (UIImage*) cachedImageForPath:(NSString*)path 74 | { 75 | UIImage* image = nil; 76 | 77 | NSDictionary* metaData = [[UURemoteData sharedInstance] metaDataForPath:path]; 78 | if (metaData) 79 | { 80 | image = [metaData uuSafeGet:kUUImageCacheMetaDataImageKey forClass:[UIImage class]]; 81 | } 82 | 83 | return image; 84 | } 85 | 86 | - (void) updateCache:(UIImage*)image forPath:(NSString*)path 87 | { 88 | NSMutableDictionary* md = nil; 89 | 90 | NSDictionary* metaData = [[UURemoteData sharedInstance] metaDataForPath:path]; 91 | if (metaData) 92 | { 93 | md = [NSMutableDictionary dictionaryWithDictionary:metaData]; 94 | } 95 | else 96 | { 97 | md = [NSMutableDictionary dictionary]; 98 | } 99 | 100 | NSValue* imageSize = [NSValue valueWithCGSize:image.size]; 101 | [md setValue:imageSize forKey:kUUImageCacheMetaDataSizeKey]; 102 | [md setValue:image forKey:kUUImageCacheMetaDataImageKey]; 103 | [[UURemoteData sharedInstance] updateMetaData:md.copy forPath:path]; 104 | } 105 | 106 | - (UIImage*) imageForPath:(NSString*)path 107 | { 108 | return [self imageForPath:path remoteDownloadIfNeeded:self.remoteFetchEnabled]; 109 | } 110 | 111 | - (UIImage*) imageForPath:(NSString*)path remoteDownloadIfNeeded:(BOOL)remoteDownloadIfNeeded 112 | { 113 | if (!path || path.length <= 0) 114 | { 115 | return nil; 116 | } 117 | 118 | id obj = [self cachedImageForPath:path]; 119 | if (obj) 120 | { 121 | return obj; 122 | } 123 | 124 | NSData* data = nil; 125 | 126 | if (remoteDownloadIfNeeded) 127 | { 128 | data = [[UURemoteData sharedInstance] dataForPath:path]; 129 | } 130 | else 131 | { 132 | data = [[UUDataCache sharedCache] objectForKey:path]; 133 | } 134 | 135 | if (data) 136 | { 137 | UIImage* img = [[UIImage alloc] initWithData:data]; 138 | if (img) 139 | { 140 | [self updateCache:img forPath:path]; 141 | } 142 | 143 | return img; 144 | } 145 | 146 | return nil; 147 | } 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /UUImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUImageView.h 3 | // Useful Utilities - UIImageView extensions 4 | // 5 | // (c) 2013, Jonathan Hays. All Rights Reserved. 6 | // 7 | // Smile License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import 13 | 14 | @protocol UUImageCache 15 | @required 16 | - (id)objectForKey:(id)key; 17 | - (void) setObject:(id)object forKey:(id)key; 18 | @end 19 | 20 | @interface UIImageView (UURemoteLoading) 21 | 22 | - (void) uuLoadImageFromURL:(NSURL*)url defaultImage:(UIImage*)defaultImage loadCompleteHandler:(void (^)(UIImageView* imageView))loadCompleteHandler; 23 | 24 | + (void) uuSetImageCache:(NSObject*)cache; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /UUInstagram.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUInstagram 3 | // Useful Utilities - Useful functions to interact with Instagram 4 | // (c) Copyright Jonathan Hays, all rights reserved 5 | // 6 | // License: 7 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 8 | // 9 | // Contact: @cheesemaker or jon@threejacks.com 10 | 11 | #import 12 | 13 | @interface UUInstagram : NSObject 14 | + (void) initialize:(NSString*)clientId secret:(NSString*)clientSecret redirect:(NSString*)redirectURL; 15 | + (void) authenticate:(UIViewController*)parent completionHandler:(void (^)(BOOL success, NSError* error))completionBlock; 16 | 17 | + (NSString*) userName; 18 | + (void) logout; 19 | 20 | + (void) getUserMedia:(void (^)(BOOL success, NSDictionary* userMedia))completionBlock; 21 | + (void) getUserFeed:(void (^)(BOOL success, NSDictionary* userMedia))completionBlock; 22 | + (void) getPopularMedia:(void (^)(BOOL success, NSDictionary* userMedia))completionBlock; 23 | 24 | //Helper functions to build the URLs for thumbnails and standard resolution URL's for images 25 | + (NSArray*) listOfUserThumbnailURLs:(NSDictionary*)userMedia; 26 | + (NSArray*) listOfUserImageURLs:(NSDictionary*)userMedia; 27 | 28 | + (NSString*) accessToken; 29 | @end 30 | 31 | -------------------------------------------------------------------------------- /UULocation.h: -------------------------------------------------------------------------------- 1 | // 2 | // UULocation.h 3 | // Useful Utilities - CLLocationManager wrapper 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@silverpinesoftware.com 9 | 10 | 11 | #import 12 | #import 13 | 14 | @interface UULocation : NSObject 15 | //The last reported location. If no location reported, this will be nil 16 | + (UULocation*) lastReportedLocation; 17 | 18 | //Query location information. If the location name hasn't resolved, then the names will be nil 19 | @property (nonatomic, readonly) CLLocation* clLocation; 20 | @property (nonatomic, readonly) NSString* currentLocationName; 21 | @property (nonatomic, readonly) NSString* currentCityName; 22 | @property (nonatomic, readonly) NSString* currentStateName; 23 | - (BOOL) isValid; 24 | @end 25 | 26 | 27 | @protocol UULocationMonitoringDelegate 28 | @optional 29 | - (void) uuLocationChanged:(UULocation*)newLocation; 30 | - (void) uuLocationResolved:(UULocation*)resolvedLocation; 31 | - (void) uuLocationUpdateFailed:(NSError*)error; 32 | @end 33 | 34 | 35 | @interface UULocationMonitoring : NSObject 36 | + (void) addDelegate:(NSObject*)delegate; 37 | + (void) removeDelegate:(NSObject*)delegate; 38 | @end 39 | 40 | 41 | @interface UULocationMonitoringConfiguration : NSObject 42 | 43 | //Global settings interface. 44 | + (BOOL) isAuthorizedToTrack; 45 | + (BOOL) isTrackingDenied; 46 | 47 | + (void) requestStartTracking:(BOOL)trackOnlyWhenInUse completionBlock:(void(^)(BOOL authorized))callback; 48 | + (void) requestStopTracking; 49 | + (void) startTrackingSignificantLocationChanges; 50 | + (void) stopTrackingSignficantLocationChanges; 51 | 52 | + (CLLocationDistance) distanceThreshold; 53 | + (void) setDistanceThreshold:(CLLocationDistance) distanceThreshold; 54 | 55 | + (NSTimeInterval) minimumTimeThreshold; 56 | + (void) setMinimumTimeThreshold:(NSTimeInterval)timeThreshold; 57 | 58 | + (BOOL) locationNameReportingEnabled; 59 | + (void) setLocationNameReportingEnabled:(BOOL)enabled; 60 | 61 | + (BOOL) delayLocationUpdates; 62 | + (void) setDelayLocationUpdates:(BOOL)delayUpdates; 63 | 64 | + (NSTimeInterval) locationUpdateDelay; 65 | + (void) setLocationUpdateDelay:(NSTimeInterval)updateDelay; 66 | 67 | @end -------------------------------------------------------------------------------- /UULocationManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // UULocationManager.h 3 | // Useful Utilities - CLLocationManager wrapper 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | 10 | 11 | #import 12 | #import 13 | 14 | extern NSString * const UULocationChangedNotification; 15 | extern NSString * const UULocationNameChangedNotification; 16 | extern NSString * const UULocationAuthChangedNotification; 17 | extern NSString * const UULocationErrorNotification; 18 | 19 | @interface UULocationManager : NSObject 20 | 21 | 22 | //Call startTracking to begin location services. If you do not explicitly call startTracking, 23 | //the first time you access the sharedInstance, it will be called internally. 24 | + (void) startTracking; 25 | + (UULocationManager*) sharedInstance; 26 | 27 | 28 | // Cached results 29 | - (CLLocation*) currentLocation; 30 | - (NSString*) currentLocationName; 31 | - (NSString*) currentCityName; 32 | - (NSString*) currentStateName; 33 | 34 | - (bool) hasValidLocation; 35 | 36 | - (void) startTracking; 37 | - (void) stopTracking; 38 | - (void) startTrackingSignificantLocationChanges; 39 | - (void) stopTrackingSignificantLocationChanges; 40 | 41 | // Configuration Properties 42 | @property (assign, setter = setDistsanceThreshold:) CLLocationDistance distanceThreshold; // Defaults to 10 meters 43 | @property (assign) NSTimeInterval timeThreshold; // Defaults to 30 minutes (time is in seconds) 44 | @property (assign) bool monitorLocationName; // Defaults to NO 45 | @property (assign) bool delayLocationUpdates; // Defaults to NO 46 | @property (assign) NSTimeInterval locationUpdateDelay; // Defaults to 1 second 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /UUMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUMacros 3 | // Useful Utilities - Handy macros 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only 7 | // requirement is that you smile everytime you use it. 8 | // 9 | 10 | #ifndef UUMacros_h 11 | #define UUMacros_h 12 | 13 | #define UUGCDMainQueue dispatch_get_main_queue() 14 | #define UUGCDBackgroundQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 15 | 16 | #define UUDispatchTimeInSeconds(seconds) dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC) 17 | 18 | #define UUDispatchThread(block) \ 19 | dispatch_async(UUGCDBackgroundQueue, block) 20 | 21 | #define UUDispatchMain(block) \ 22 | dispatch_async(UUGCDMainQueue, block) 23 | 24 | #define UUDispatchSecondsMain(seconds, block) \ 25 | dispatch_after(UUDispatchTimeInSeconds(seconds), UUGCDMainQueue, block) 26 | 27 | #define UUDispatchSecondsThread(seconds, block) \ 28 | dispatch_after(UUDispatchTimeInSeconds(seconds), UUGCDBackgroundQueue, block) 29 | 30 | #define UUCurrentFile [[NSString stringWithUTF8String:__FILE__] lastPathComponent] 31 | 32 | #ifndef UULog 33 | #define UULog(fmt, ...) NSLog((@"%s [%@:%d] - " fmt), __PRETTY_FUNCTION__, UUCurrentFile, __LINE__, ##__VA_ARGS__); 34 | #endif 35 | 36 | #ifndef UUDebugLog 37 | #ifdef DEBUG 38 | #define UUDebugLog(fmt, ...) UULog(fmt, ##__VA_ARGS__); 39 | #else 40 | #define UUDebugLog(fmt, ...) //don't log anything if this is not running in debug mode 41 | #endif // DEBUG 42 | #endif // UUDebugLog 43 | 44 | #endif /* UUMacros_h */ 45 | -------------------------------------------------------------------------------- /UUMapView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUMapView.h 3 | // Useful Utilities - MKMapView extensions 4 | // 5 | // Created by Jonathan on 3/4/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import 13 | 14 | @interface MKMapView (UUFramework) 15 | - (void) uuZoomToAnnotations:(bool)animated; 16 | @end 17 | -------------------------------------------------------------------------------- /UUMapView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUMapView.m 3 | // Useful Utilities - MKMapView extensions 4 | // 5 | // Created by Jonathan on 3/4/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import "UUMapView.h" 13 | 14 | @implementation MKMapView (UUFramework) 15 | 16 | + (bool) uuFindBoundingBox:(NSArray*)annotations bounds:(MKCoordinateRegion*)boundingBox 17 | { 18 | CLLocationDegrees minLat = INT_MAX; 19 | CLLocationDegrees maxLat = INT_MIN; 20 | CLLocationDegrees minLng = INT_MAX; 21 | CLLocationDegrees maxLng = INT_MIN; 22 | 23 | bool foundMinLat = false; 24 | bool foundMinLng = false; 25 | bool foundMaxLat = false; 26 | bool foundMaxLng = false; 27 | 28 | for (NSObject* annotation in annotations) 29 | { 30 | CLLocationDegrees lat = annotation.coordinate.latitude; 31 | CLLocationDegrees lng = annotation.coordinate.longitude; 32 | if (lat != 0.0 || lng!= 0.0) 33 | { 34 | if (lat < minLat) 35 | { 36 | minLat = lat; 37 | foundMinLat = true; 38 | } 39 | 40 | if (lat > maxLat) 41 | { 42 | maxLat = lat; 43 | foundMaxLat = true; 44 | } 45 | 46 | if (lng < minLng) 47 | { 48 | minLng = lng; 49 | foundMinLng = true; 50 | } 51 | 52 | if (lng > maxLng) 53 | { 54 | maxLng = lng; 55 | foundMaxLng = true; 56 | } 57 | } 58 | } 59 | 60 | if (foundMinLat && foundMinLng && foundMaxLat && foundMaxLng) 61 | { 62 | (*boundingBox).center.latitude = minLat + ((maxLat - minLat) / 2.0f); 63 | (*boundingBox).center.longitude = minLng + ((maxLng - minLng) / 2.0f); 64 | (*boundingBox).span.latitudeDelta = fabs(maxLat - minLat); 65 | (*boundingBox).span.longitudeDelta = fabs(maxLng - minLng); 66 | return true; 67 | } 68 | else 69 | { 70 | return false; 71 | } 72 | } 73 | 74 | - (void) uuZoomToAnnotations:(bool)animated 75 | { 76 | MKCoordinateRegion region; 77 | if ([MKMapView uuFindBoundingBox:self.annotations bounds:®ion]) 78 | { 79 | region = [self regionThatFits:region]; 80 | [self setRegion:region animated:animated]; 81 | } 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /UUObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUObject.h 3 | // Useful Utilities - NSObject extensions for attaching arbitrary data to objects. Useful for when 4 | // you have painted yourself into a design corner. 5 | // 6 | // Created by Jonathan on 3/4/13. 7 | // 8 | // License: 9 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 10 | // 11 | // Contact: @cheesemaker or jon@threejacks.com 12 | 13 | #import 14 | 15 | @interface NSObject (UUFramework) 16 | 17 | - (void) attachUserInfo:(id)userInfo; //Uses kUUDefaultUserKey 18 | - (id) userInfo; 19 | 20 | - (void) attachUserInfo:(id)userInfo forKey:(const void*)key; 21 | - (id) userInfoForKey:(const void*)key; 22 | 23 | 24 | //Here for convenience... 25 | extern unsigned long const kUUDefaultUserKey; 26 | 27 | @end -------------------------------------------------------------------------------- /UUObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUObject.m 3 | // Useful Utilities - NSObject extensions 4 | // 5 | // Created by Jonathan on 3/4/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import "UUObject.h" 13 | #import 14 | 15 | const unsigned long kUUDefaultUserKey = 0x04261978; 16 | 17 | @implementation NSObject (UUFramework) 18 | 19 | - (void) attachUserInfo:(id)userInfo 20 | { 21 | objc_setAssociatedObject(self, (const void*)kUUDefaultUserKey, userInfo, OBJC_ASSOCIATION_RETAIN); 22 | } 23 | 24 | - (id) userInfo 25 | { 26 | return objc_getAssociatedObject(self, (const void*)kUUDefaultUserKey); 27 | } 28 | 29 | - (void) attachUserInfo:(id)userInfo forKey:(const void*)key 30 | { 31 | if (key != nil) 32 | { 33 | objc_setAssociatedObject(self, key, userInfo, OBJC_ASSOCIATION_RETAIN); 34 | } 35 | } 36 | 37 | - (id) userInfoForKey:(const void*)key 38 | { 39 | if (key != nil) 40 | { 41 | return objc_getAssociatedObject(self, key); 42 | } 43 | else 44 | { 45 | return nil; 46 | } 47 | } 48 | 49 | @end -------------------------------------------------------------------------------- /UUObjectFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUObjectFactory.h 3 | // Useful Utilities - Object parsing protocols and helpers 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | // 10 | // 11 | // These methods and protocols are meant to simplify a common problem when building 12 | // RESTful iOS applications. That of converting raw data into real objects. 13 | // Typically this will be the form of a JSON web service that the application 14 | // will turn into plain data objects, or Core Data managed objects 15 | 16 | @import Foundation; 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Object Factory 20 | @protocol UUObjectFactory 21 | 22 | + (id) uuObjectFromDictionary:(NSDictionary*)dictionary withContext:(id)context; 23 | 24 | @end 25 | 26 | @interface UUObjectFactory : NSObject 27 | 28 | + (id) process:(Class)objectFactoryClass object:(id)object context:(id)context; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /UUObjectFactory.m: -------------------------------------------------------------------------------- 1 | // 2 | // UUObjectFactory.m 3 | // Useful Utilities - Object parsing protocols and helpers 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | // 10 | // 11 | 12 | #import "UUObjectFactory.h" 13 | #import "UUHttpResponseHandler.h" 14 | 15 | @implementation UUObjectFactory 16 | 17 | + (id) process:(Class)objectFactoryClass object:(id)object context:(id)context 18 | { 19 | id processedResponse = object; 20 | 21 | if (objectFactoryClass && [objectFactoryClass conformsToProtocol:@protocol(UUObjectFactory)]) 22 | { 23 | if ([object isKindOfClass:[NSDictionary class]]) 24 | { 25 | id singleResponse = [objectFactoryClass uuObjectFromDictionary:object withContext:context]; 26 | processedResponse = singleResponse; 27 | } 28 | else if ([object isKindOfClass:[NSArray class]]) 29 | { 30 | NSMutableArray* list = [NSMutableArray array]; 31 | 32 | for (id node in object) 33 | { 34 | if ([node isKindOfClass:[NSDictionary class]]) 35 | { 36 | id nodeObj = [objectFactoryClass uuObjectFromDictionary:node withContext:context]; 37 | if (nodeObj) 38 | { 39 | [list addObject:nodeObj]; 40 | } 41 | } 42 | } 43 | 44 | processedResponse = list; 45 | } 46 | } 47 | 48 | return processedResponse; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /UUOpenALSoundManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUOpenALSoundManager.h 3 | // Useful Utilities - OpenAL wrapper 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | 10 | #import 11 | # 12 | @interface UUOpenALSoundClip : NSObject 13 | - (void) playSound:(float)volume; 14 | @end 15 | 16 | @interface UUOpenALSoundManager : NSObject 17 | 18 | // Static Interface 19 | + (UUOpenALSoundManager*) sharedSoundManager; 20 | 21 | // Instance Interface 22 | - (bool) isOtherMusicPlaying; 23 | - (void) disableOtherMusicPlaying; 24 | - (UUOpenALSoundClip*) soundClipFromResource:(NSString*)file Ext:(NSString*)ext; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /UUProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUProgressView.h 3 | // 4 | // Created by Jonathan on 3/19/13. 5 | // 6 | // License: 7 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 8 | // 9 | // Contact: @cheesemaker or jon@threejacks.com 10 | 11 | #import 12 | 13 | @interface UUProgressView : UIView 14 | 15 | - (void) show:(BOOL)animated; 16 | - (void) hide:(BOOL)animated; 17 | - (void) updateMessage:(NSString*)message; 18 | 19 | + (UUProgressView*) globalProgressView; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /UURandom.h: -------------------------------------------------------------------------------- 1 | // 2 | // UURandom.h 3 | // Useful Utilities - Handy helpers for generating random numbers and picking random elements 4 | // 5 | // Created by Ryan DeVore on 7/29/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import 13 | 14 | @interface UURandom : NSObject 15 | 16 | + (u_int32_t) uuRandomUInt32; 17 | + (u_int32_t) uuRandomUInt32BetweenLow:(u_int32_t)low high:(u_int32_t)high; 18 | + (u_int32_t) uuRandomUInt32BetweenLow:(u_int32_t)low high:(u_int32_t)high not:(u_int32_t)notIncluding; 19 | + (u_int32_t) uuRandomUInt32BetweenLow:(u_int32_t)low high:(u_int32_t)high atLeast:(u_int32_t)distance from:(u_int32_t)marker; 20 | 21 | + (BOOL) uuRandomBool; 22 | 23 | + (NSData*) uuRandomBytes:(NSUInteger)length; 24 | 25 | @end 26 | 27 | @interface NSArray (UURandom) 28 | 29 | - (NSUInteger) uuRandomIndex; 30 | - (id) uuRandomElement; 31 | 32 | @end 33 | 34 | @interface NSSet (UURandom) 35 | 36 | - (id) uuRandomElement; 37 | 38 | @end 39 | 40 | @interface NSMutableArray (UURandom) 41 | 42 | - (void) uuRandomize; 43 | 44 | @end -------------------------------------------------------------------------------- /UURandom.m: -------------------------------------------------------------------------------- 1 | // 2 | // UURandom.m 3 | // Useful Utilities - Handy helpers for generating random numbers and picking random elements 4 | // 5 | // Created by Ryan DeVore on 7/29/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import "UURandom.h" 13 | 14 | #pragma mark - UURandom 15 | 16 | @implementation UURandom 17 | 18 | + (u_int32_t) uuRandomUInt32 19 | { 20 | return arc4random(); 21 | } 22 | 23 | + (u_int32_t) uuRandomUInt32BetweenLow:(u_int32_t)low high:(u_int32_t)high 24 | { 25 | if (low > high) 26 | { 27 | u_int32_t temp = low; 28 | low = high; 29 | high = temp; 30 | } 31 | 32 | u_int32_t range = high - low + 1; 33 | u_int32_t rand = arc4random_uniform(range); 34 | return (low + rand); 35 | } 36 | 37 | + (u_int32_t) uuRandomUInt32BetweenLow:(u_int32_t)low high:(u_int32_t)high not:(u_int32_t)notIncluding 38 | { 39 | u_int32_t randomResult = [self uuRandomUInt32BetweenLow:low high:high]; 40 | 41 | while (randomResult == notIncluding) 42 | { 43 | randomResult = [self uuRandomUInt32BetweenLow:low high:high]; 44 | } 45 | 46 | return randomResult; 47 | } 48 | 49 | + (u_int32_t) uuRandomUInt32BetweenLow:(u_int32_t)low high:(u_int32_t)high atLeast:(u_int32_t)distance from:(u_int32_t)marker 50 | { 51 | u_int32_t randomResult = [self uuRandomUInt32BetweenLow:low high:high]; 52 | 53 | while ( (randomResult >= (marker - distance)) && (randomResult <= (marker + distance)) ) 54 | { 55 | randomResult = [self uuRandomUInt32BetweenLow:low high:high]; 56 | } 57 | 58 | return randomResult; 59 | } 60 | 61 | + (BOOL) uuRandomBool 62 | { 63 | return (([self uuRandomUInt32] % 2) == 0); 64 | } 65 | 66 | + (NSData*) uuRandomBytes:(NSUInteger)length 67 | { 68 | NSMutableData* data = [NSMutableData dataWithLength:length]; 69 | SecRandomCopyBytes(kSecRandomDefault, length, [data mutableBytes]); 70 | return [data copy]; 71 | } 72 | 73 | @end 74 | 75 | #pragma mark - NSArray+UURandom 76 | 77 | @implementation NSArray (UURandom) 78 | 79 | - (NSUInteger) uuRandomIndex 80 | { 81 | return [UURandom uuRandomUInt32BetweenLow:0 high:(u_int32_t)(self.count - 1)]; 82 | } 83 | 84 | - (id) uuRandomElement 85 | { 86 | if (self.count <= 0) 87 | { 88 | return nil; 89 | } 90 | 91 | return [self objectAtIndex:[self uuRandomIndex]]; 92 | } 93 | 94 | @end 95 | 96 | #pragma mark - NSSet+UURandom 97 | 98 | @implementation NSSet (UURandom) 99 | 100 | - (id) uuRandomElement 101 | { 102 | return [[self allObjects] uuRandomElement]; 103 | } 104 | 105 | @end 106 | 107 | #pragma mark - NSMutableArray+UURandom 108 | 109 | @implementation NSMutableArray (UURandom) 110 | 111 | #define UU_RANDOMIZE_ARRAY_FACTOR 100 112 | 113 | - (void) uuRandomize 114 | { 115 | if (self.count > 1) 116 | { 117 | for (int i = 0; i < (self.count * UU_RANDOMIZE_ARRAY_FACTOR); i++) 118 | { 119 | NSUInteger a = [self uuRandomIndex]; 120 | NSUInteger b = [UURandom uuRandomUInt32BetweenLow:0 high:(u_int32_t)(self.count - 1) not:(u_int32_t)a]; 121 | 122 | [self exchangeObjectAtIndex:a withObjectAtIndex:b]; 123 | } 124 | } 125 | } 126 | 127 | @end -------------------------------------------------------------------------------- /UUReachability.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUReachability.h 3 | // Useful Utilities - Simple block based reachibilty wrapper 4 | // 5 | // Created by Ryan DeVore on 7/1/14. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | // 12 | // This class was adapted from the Apple sample on Reachability 13 | 14 | #import 15 | #import 16 | 17 | extern NSString * const kUUReachabilityChangedNotification; 18 | 19 | @interface UUReachabilityResult : NSObject 20 | 21 | // Raw reachability flags 22 | @property (assign) SCNetworkReachabilityFlags reachabilityFlags; 23 | 24 | // Convenience methods to check reachability bit flags 25 | @property (assign) BOOL isReachableWithWiFi; 26 | @property (assign) BOOL isReachableWithCell; 27 | @property (assign) BOOL isReachable; // Cell or WiFi 28 | 29 | // For inspection of bit values 30 | - (NSDictionary*) reachabilityFlagsAsDictionary; 31 | 32 | @end 33 | 34 | @interface UUReachability : NSObject 35 | 36 | + (instancetype) sharedInstance; // uses www.apple.com 37 | + (instancetype) reachabilityForHostName:(NSString*)hostName; 38 | 39 | // Cached reachability value. If nil it means the current reachability 40 | // has not been determined yet. 41 | @property (nonatomic, strong) UUReachabilityResult* currentReachability; 42 | 43 | // Convenience helper to check if the host is currently reachable. This 44 | // will return YES if currentReachability is nil, so as to avoid false posivites 45 | // when the reachability status is still being determined. 46 | - (BOOL) isReachable; 47 | 48 | // Delay (in seconds) before firing a kUUReachabilityChangedNotification. Default is 1.0 49 | // This delay is to buffer against rapid changes in reachability 50 | @property (assign) NSTimeInterval reachabilityChangedDelay; 51 | 52 | // Asyncrhonously checks the current reachability 53 | // NOTE: the very first time this is called it sometimes returns a flags value 54 | // of 0, for this reason it is recommended to respond to kUUReachabilityChangedNotification 55 | // instead. 56 | - (void) checkReachability:(void (^)(UUReachabilityResult* result))completion; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /UURemoteData.h: -------------------------------------------------------------------------------- 1 | // 2 | // UURemoteData.h 3 | // Useful Utilities - An extension to Useful Utilities UUDataCache that fetches 4 | // data from a remote source 5 | // 6 | // License: 7 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 8 | // 9 | // 10 | // UURemoteData provides a centralized place where application components can request 11 | // data that may come from a remote source. It utilizes existing UUDataCache functionality 12 | // to locally store files for later fetching. It will intelligently handle multiple requests for the 13 | // same image so that extraneous network requests are not needed. 14 | // 15 | // 16 | // NOTE: This class depends on the following toolbox classes: 17 | // 18 | // UUHttpClient 19 | // UUDataCache 20 | // 21 | // 22 | // NOTE NOTE: This class is currently under development, so the interface and functionality 23 | // may be subject to change. 24 | // 25 | 26 | #import 27 | 28 | // Notification userInfo has two values: 29 | // 30 | // kUUDataRemotePathKey - NSString of the remote path 31 | // kUUDataKey - UIImage 32 | // kUUErrorKey - NSError (may be nil) 33 | // 34 | extern NSString * const kUUDataDownloadedNotification; 35 | extern NSString * const kUUDataDownloadFailedNotification; 36 | extern NSString * const kUUDataRemotePathKey; 37 | extern NSString * const kUUDataKey; 38 | extern NSString * const kUUErrorKey; 39 | 40 | // Meta Data keys 41 | extern NSString * const kUUMetaDataMimeTypeKey; 42 | extern NSString * const kUUMetaDataDownloadTimestampKey; 43 | 44 | @interface UURemoteData : NSObject 45 | 46 | + (instancetype) sharedInstance; 47 | 48 | // Attempts to fetch remote data. If the data exists locally in UUDataCache, it will return 49 | // immediately. If nil is returned, there is no local copy of the resource, and it indicates 50 | // a remote request has either been started or is already in progress. 51 | - (NSData*) dataForPath:(NSString*)path; 52 | 53 | // Returns true if there is an active or queue'd download request for the remote resource 54 | - (BOOL) hasPendingDownloadForPath:(NSString*)path; 55 | 56 | // UURemoteData maintains an NSCache of NSDictionary's per remote object. 57 | // UURemoteData will store the MIME type and download time of the object. 58 | - (NSDictionary*) metaDataForPath:(NSString*)path; 59 | - (void) updateMetaData:(NSDictionary*)metaData forPath:(NSString*)path; 60 | 61 | // Fetches multiple remote data objects and calls the completion block only when all 62 | // have completed. The completion block is an NSDictionary of NSString->NSError objects. If 63 | // empty it means all completed successfully. 64 | - (void) fetchMultiple:(NSArray*)remotePaths completion:(void(^)(NSDictionary* results))completion; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /UURemoteImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UURemoteImage.h 3 | // Useful Utilities - An extension to UURemoteData that provides an NSCache of UIImage objects 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // 9 | // UURemoteData provides a centralized place where application components can request 10 | // data that may come from a remote source. It utilizes existing UUDataCache functionality 11 | // to locally store files for later fetching. It will intelligently handle multiple requests for the 12 | // same image so that extraneous network requests are not needed. 13 | // 14 | // 15 | // NOTE: This class depends on the following toolbox classes: 16 | // 17 | // UURemoteData 18 | // UUDictionary 19 | // 20 | // NOTE NOTE: This class is currently under development, so the interface and functionality 21 | // may be subject to change. 22 | // 23 | 24 | #import 25 | #import "UURemoteData.h" 26 | 27 | extern NSString * const kUUMetaDataImageSizeKey; 28 | 29 | @interface UURemoteImage : UURemoteData 30 | 31 | // Loads an image first from the NSCache, then from UURemoteData 32 | - (UIImage*) imageForPath:(NSString*)path; 33 | 34 | // Loads an image first from an NSCache of UIImage's, then from UUDataCache, 35 | // and optionally from its remote source. 36 | - (UIImage*) imageForPath:(NSString*)path skipDownload:(BOOL)skipDownload; 37 | 38 | // Returns the cached image size, or nil if the image is not present in the local cache 39 | - (NSValue*) imageSizeForPath:(NSString*)path; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /UURemoteImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // UURemoteImage.h 3 | // Useful Utilities - An extension to UURemoteData that provides an NSCache of UIImage objects 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // 9 | // UURemoteData provides a centralized place where application components can request 10 | // data that may come from a remote source. It utilizes existing UUDataCache functionality 11 | // to locally store files for later fetching. It will intelligently handle multiple requests for the 12 | // same image so that extraneous network requests are not needed. 13 | // 14 | // 15 | // NOTE: This class depends on the following toolbox classes: 16 | // 17 | // UURemoteData 18 | // UUDictionary 19 | // 20 | // NOTE NOTE: This class is currently under development, so the interface and functionality 21 | // may be subject to change. 22 | // 23 | 24 | #import "UURemoteImage.h" 25 | #import "UUDataCache.h" 26 | #import "UUDictionary.h" 27 | 28 | //If you want to provide your own logging mechanism, define UUDebugLog in your .pch 29 | #ifndef UUDebugLog 30 | #ifdef DEBUG 31 | #define UUDebugLog(fmt, ...) NSLog(fmt, ##__VA_ARGS__) 32 | #else 33 | #define UUDebugLog(fmt, ...) 34 | #endif 35 | #endif 36 | 37 | NSString * const kUUMetaDataImageSizeKey = @"UUMetaDataImageSize"; 38 | 39 | @interface UURemoteImage () 40 | 41 | @property (nonatomic, strong) NSCache* imageCache; 42 | 43 | @end 44 | 45 | @implementation UURemoteImage 46 | 47 | + (instancetype) sharedInstance 48 | { 49 | static id theSharedObject = nil; 50 | static dispatch_once_t onceToken; 51 | 52 | dispatch_once (&onceToken, ^ 53 | { 54 | theSharedObject = [[[self class] alloc] init]; 55 | }); 56 | 57 | return theSharedObject; 58 | } 59 | 60 | - (id) init 61 | { 62 | self = [super init]; 63 | 64 | if (self) 65 | { 66 | self.imageCache = [[NSCache alloc] init]; 67 | self.imageCache.name = [NSString stringWithFormat:@"%@Cache", NSStringFromClass([self class])]; 68 | } 69 | 70 | return self; 71 | } 72 | 73 | - (UIImage*) imageForPath:(NSString*)path 74 | { 75 | return [self imageForPath:path skipDownload:NO]; 76 | } 77 | 78 | - (UIImage*) imageForPath:(NSString*)path skipDownload:(BOOL)skipDownload 79 | { 80 | if (!path || path.length <= 0) 81 | { 82 | return nil; 83 | } 84 | 85 | id obj = [self.imageCache objectForKey:path]; 86 | if (obj) 87 | { 88 | //NSLog(@"Returning NSCache'd image for %@", path); 89 | return obj; 90 | } 91 | 92 | NSData* data = nil; 93 | 94 | if (skipDownload) 95 | { 96 | data = [[UUDataCache sharedCache] objectForKey:path]; 97 | } 98 | else 99 | { 100 | data = [[UURemoteData sharedInstance] dataForPath:path]; 101 | } 102 | 103 | if (data) 104 | { 105 | UIImage* img = [[UIImage alloc] initWithData:data]; 106 | if (img) 107 | { 108 | [self.imageCache setObject:img forKey:path]; 109 | 110 | NSMutableDictionary* metaData = [[self metaDataForPath:path] mutableCopy]; 111 | if (!metaData) 112 | { 113 | metaData = [NSMutableDictionary dictionary]; 114 | } 115 | 116 | [metaData setValue:[NSValue valueWithCGSize:img.size] forKey:kUUMetaDataImageSizeKey]; 117 | [self updateMetaData:[metaData copy] forPath:path]; 118 | //UUDebugLog(@"Image at path %@ has size %f, %f, byteSize: %@", path, img.size.width, img.size.height, @(data.length)); 119 | } 120 | return img; 121 | } 122 | 123 | return nil; 124 | } 125 | 126 | - (NSValue*) imageSizeForPath:(NSString*)path 127 | { 128 | NSDictionary* metaData = [self metaDataForPath:path]; 129 | NSValue* val = [metaData uuSafeGet:kUUMetaDataImageSizeKey forClass:[NSValue class]]; 130 | return val; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /UUString.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUString.h 3 | // Useful Utilities - Extensions for NSStrings 4 | // 5 | // Created by Jonathan on 7/29/13. 6 | // 7 | // License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@threejacks.com 11 | 12 | #import 13 | 14 | 15 | @interface NSString (UUString) 16 | 17 | // Formats a sequence of numbers as a list of range or discrete values 18 | // 1,2,3,4,5,6,7,8 ==> "1-8" 19 | // 1,3,5,7,8 ==> "1,3,5,7,8" 20 | // 1,2,3,6,7,8 ==> "1-3,6-8" 21 | // 1,2,3,4,6,8,9,10 ==> "1-4,6,8-10" 22 | + (NSString*) uuFormatSortedNumbers:(NSArray*)numbers; 23 | 24 | + (NSString*) uuFormatCurrency:(NSDecimalNumber*)value withLocale:(NSLocale*)locale; 25 | 26 | - (NSString*) uuTrimWhitespace; 27 | - (NSString*) uuToProperString; 28 | 29 | - (bool) uuContainsString:(NSString*)subString; 30 | - (bool) uuStartsWithSubstring:(NSString *)inSubstring; 31 | - (bool) uuEndsWithSubstring:(NSString *)inSubstring; 32 | - (NSString *) uuReverse; 33 | 34 | + (NSString*) uuGenerateUUIDString; 35 | 36 | - (NSData*) uuToHexData; 37 | + (NSData*) uuToHexData:(NSString*)string; 38 | + (NSString*) uuHexStringFromData:(NSData*)data; 39 | 40 | - (bool) uuCsvContainsString:(NSString*)token; 41 | 42 | // Validates a string against RFC 2822 43 | - (BOOL) uuValidEmailAddress; 44 | 45 | @end 46 | 47 | 48 | @interface NSString (UUHttpString) 49 | 50 | // Extracts the part after the '=' in a typical HTTP query string. 51 | // NSString* url = http://www.threejacks.com?someArg=foobar&anotherArg=blarfo 52 | // NSString* arg = [url parseQueryStringArg:@"someArg"]; 53 | // arg is 'foobar' 54 | - (NSDictionary*) uuDictionaryFromQueryString; 55 | - (NSString*) uuFindQueryStringArg:(NSString*)argName; 56 | - (NSString *) uuUrlEncoded; 57 | - (NSString *) uuUrlDecoded; 58 | 59 | @end 60 | 61 | @interface NSString (UUStringEncryption) 62 | 63 | - (bool) uuIsValidMD5Hash:(NSData*)buffer; 64 | - (NSString*) uuHMACSHA1:(NSString*)key; 65 | + (NSData*) uuAESEncryptString:(NSString*)string with:(NSString*)key; 66 | + (NSString*) uuAESDecryptData:(NSData*)data with:(NSString*)key; 67 | 68 | @end 69 | 70 | -------------------------------------------------------------------------------- /UUTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField.h 3 | // Useful Utilities - UITextField and UITextView extensions 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | // Contact: @cheesemaker or jon@threejacks.com 9 | 10 | #import 11 | 12 | @interface UITextField (UUFramework) 13 | 14 | //Enable one finger swipe to move the text caret forward/backward one character and 15 | // two finger swipe to move the text caret forward/backward an entire word 16 | - (void) uuAddGestureNavigation; 17 | 18 | @end 19 | 20 | 21 | @interface UITextView (UUFramework) 22 | 23 | //Enable one finger swipe to move the text caret forward/backward one character and 24 | // two finger swipe to move the text caret forward/backward an entire word 25 | - (void) uuAddGestureNavigation; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /UUTimer.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUTimer.h 3 | // Useful Utilities - GCD based timer 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only 7 | // requirement is that you smile everytime you use it. 8 | // 9 | 10 | #import 11 | 12 | @class UUTimer; 13 | 14 | typedef void (^UUTimerBlock)(UUTimer* _Nonnull timer); 15 | 16 | @interface UUTimer : NSObject 17 | 18 | @property (nonnull, nonatomic, copy, readonly) NSString* timerId; 19 | @property (nullable, nonatomic, strong, readonly) id userInfo; 20 | 21 | - (nonnull id) initWithInterval:(NSTimeInterval)interval 22 | userInfo:(nullable id)userInfo 23 | repeat:(BOOL)repeat 24 | queue:(nonnull dispatch_queue_t)queue 25 | block:(nonnull UUTimerBlock)block; 26 | 27 | - (nonnull id) initWithId:(nonnull NSString*)timerId 28 | interval:(NSTimeInterval)interval 29 | userInfo:(nullable id)userInfo 30 | repeat:(BOOL)repeat 31 | queue:(nonnull dispatch_queue_t)queue 32 | block:(nonnull UUTimerBlock)block; 33 | 34 | - (void) start; 35 | - (void) cancel; 36 | 37 | // Returns a shared serial queue for executing timers on a background thread 38 | + (nonnull dispatch_queue_t) backgroundTimerQueue; 39 | 40 | // Alias for dispatch_get_main_queue() 41 | + (nonnull dispatch_queue_t) mainThreadTimerQueue; 42 | 43 | // Find an active timer by its ID 44 | + (nullable instancetype) findActiveTimer:(nonnull NSString*)timerId; 45 | 46 | // Lists all active timers 47 | + (nonnull NSArray*) listActiveTimers; 48 | 49 | @end 50 | 51 | 52 | @interface UUTimer (WatchdogTimers) 53 | 54 | // Cancels any existing timer with this ID, and kicks off a new timer 55 | // on the background timer queue. If the timeout value is negative, the 56 | // new timer will not be started. 57 | + (void) startWatchdogTimer:(nonnull NSString*)timerId 58 | timeout:(NSTimeInterval)timeout 59 | userInfo:(nullable id)userInfo 60 | block:(nonnull void (^)(id _Nullable userInfo))block; 61 | 62 | + (void) cancelWatchdogTimer:(nonnull NSString*)timerId; 63 | 64 | @end 65 | 66 | 67 | -------------------------------------------------------------------------------- /UUVerticalSliderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UUVerticalSliderView.h 3 | // Useful Utilities - Vertical slider view drop in replacement for OS horizontal slider 4 | // 5 | // (c) 2014, Jonathan Hays. All Rights Reserved. 6 | // 7 | // Smile License: 8 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 9 | // 10 | // Contact: @cheesemaker or jon@silverpinesoftware.com 11 | 12 | #import 13 | 14 | @interface UUVerticalSliderView : UIControl 15 | 16 | - (instancetype) initWithFrame:(CGRect)frame; 17 | - (instancetype) initWithBackground:(UIImage*)background andSlider:(UIImage*)slider; //Uses the background image as the frame 18 | 19 | @property (nonatomic, assign) float value; // default 0.0. this value will be pinned to min/max 20 | @property (nonatomic, assign) float minimumValue; 21 | @property (nonatomic, assign) float maximumValue; 22 | 23 | @property (nonatomic, assign) BOOL snapToIntegerValues; 24 | 25 | - (void) setThumbImage:(UIImage *)image forState:(UIControlState)state; 26 | - (void) setTrackImage:(UIImage *)image forState:(UIControlState)state; 27 | 28 | @end 29 | 30 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUCircularImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUCircularImageView 3 | // Useful Utilities - UIImageView subclass that maintains circular clipping 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | public class UUCircularImageView: UIImageView 13 | { 14 | public override func layoutSubviews() 15 | { 16 | super.layoutSubviews() 17 | layer.cornerRadius = bounds.size.width / 2 18 | layer.masksToBounds = true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUCircularView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUCircularView 3 | // Useful Utilities - UIView subclass that maintains circular clipping 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | public class UUCircularView: UIView 13 | { 14 | public override func layoutSubviews() 15 | { 16 | super.layoutSubviews() 17 | layer.cornerRadius = bounds.size.width / 2 18 | layer.masksToBounds = true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUColor.swift 3 | // Useful Utilities - Extensions for UIColor 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | public extension UIColor 13 | { 14 | // Creates a UIColor object from a hex string in the form of 15 | // 16 | // RRGGBB or RRGGBBAA 17 | // 18 | public static func uuColorFromHex(_ color: String) -> UIColor 19 | { 20 | var rgba : [CGFloat] = [0, 0, 0, 1] 21 | 22 | let len = color.lengthOfBytes(using: .utf8) 23 | if (len == 6 || len == 8) 24 | { 25 | var i = 0 26 | while (i < len) 27 | { 28 | let subStr = color.uuSubString(i, 2) 29 | 30 | let scanner = Scanner(string: subStr) 31 | 32 | var hex : UInt32 = 0 33 | if (scanner.scanHexInt32(&hex)) 34 | { 35 | rgba[i/2] = (CGFloat(hex) / 255.0) 36 | } 37 | 38 | i = i + 2 39 | } 40 | } 41 | 42 | let c = UIColor(red: rgba[0], green: rgba[1], blue: rgba[2], alpha: rgba[3]) 43 | return c 44 | } 45 | 46 | // Calculates the midpoint value of each color component between two colors 47 | public static func uuCalculateMidColor(startColor: UIColor, endColor: UIColor) -> UIColor 48 | { 49 | var r : CGFloat = 0 50 | var g : CGFloat = 0 51 | var b : CGFloat = 0 52 | var a : CGFloat = 0 53 | startColor.getRed(&r, green: &g, blue: &b, alpha: &a) 54 | 55 | var startColors : [CGFloat] = [r, g, b, a] 56 | 57 | endColor.getRed(&r, green: &g, blue: &b, alpha: &a) 58 | var endColors : [CGFloat] = [r, g, b, a] 59 | 60 | var midColors : [CGFloat] = [0, 0, 0, 0] 61 | 62 | var i = 0 63 | while (i < midColors.count) 64 | { 65 | midColors[i] = (startColors[i] + endColors[i]) / 2.0 66 | i = i + 1 67 | } 68 | 69 | let midColor = UIColor.init(red: midColors[0], green: midColors[1], blue: midColors[2], alpha: midColors[3]) 70 | return midColor 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUData.swift 3 | // Useful Utilities - Extensions for Data 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import Foundation 11 | 12 | public extension Data 13 | { 14 | // Return hex string representation of data 15 | // 16 | public func uuToHexString() -> String 17 | { 18 | let sb : NSMutableString = NSMutableString() 19 | 20 | if (self.count > 0) 21 | { 22 | for index in 0...(self.count - 1) 23 | { 24 | sb.appendFormat("%02X", self[index]) 25 | } 26 | } 27 | 28 | return sb as String 29 | } 30 | 31 | // Return JSON object of the data 32 | // 33 | public func uuToJson() -> Any? 34 | { 35 | do 36 | { 37 | return try JSONSerialization.jsonObject(with: self, options: []) 38 | } 39 | catch (let err) 40 | { 41 | UUDebugLog("Error deserializing JSON: %@", String(describing: err)) 42 | } 43 | 44 | return nil 45 | } 46 | 47 | // Returns JSON string representation of the data 48 | // 49 | public func uuToJsonString() -> String 50 | { 51 | let json = uuToJson() 52 | return String(format: "%@", (json as? CVarArg) ?? "") 53 | } 54 | 55 | public func uuReversed() -> Data 56 | { 57 | return Data.init(bytes: self.reversed()) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUDebugLog.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUDebugLog.swift 3 | // Useful Utilities - NSLog wrapper that only prints in debug mode 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import Foundation 11 | 12 | // 13 | // UUDebugLog appends file, method, and line information to your custom logging 14 | // message and prints to NSLog only when the preprocessor symbol DEBUG is defined 15 | // 16 | // In Swift projects, you can define a symbol in the 'Other Swift Flags' as 17 | // "-D DEBUG" (without the quotes) 18 | // 19 | // Usage is identical to traditional Objective-C NSLog, 20 | // 21 | // UUDebugLog("Some interesting log statement") 22 | // 23 | // or with paramaters: 24 | // 25 | // UUDebugLog("Another interesting log statement, foo: %@, bar: %@", "Foo", "Bar") 26 | // 27 | public func UUDebugLog(function : NSString = #function, file : NSString = #file, line : Int = #line, _ format : String, _ args: CVarArg...) 28 | { 29 | #if DEBUG 30 | withVaList(args, 31 | { (p : CVaListPointer) -> Void in 32 | 33 | let now = Date().uuRfc3339WithMillisString() 34 | let fileNameOnly : String = file.lastPathComponent 35 | let s = NSString.init(format: "\(now) \(fileNameOnly) [\(function):\(line)] - \(format)", arguments: p) as String 36 | print(s) 37 | }) 38 | #endif 39 | } 40 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUGradientView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUGradientView.swift 3 | // Useful Utilities - Simple UIView subclass to draw a gradient background color 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | public enum UUGradientDirection : Int 13 | { 14 | case horizontal 15 | case vertical 16 | } 17 | 18 | // This class is a simple UIView subclass that draws a gradient background using 19 | // two colors. 20 | // 21 | // 22 | @IBDesignable public class UUGradientView : UIView 23 | { 24 | @IBInspectable public var startColor : UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1) 25 | { 26 | didSet 27 | { 28 | self.setNeedsDisplay() 29 | } 30 | } 31 | 32 | @IBInspectable public var endColor : UIColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1) 33 | { 34 | didSet 35 | { 36 | self.setNeedsDisplay() 37 | } 38 | } 39 | 40 | @IBInspectable public var midPoint : Float = 0.5 41 | { 42 | didSet 43 | { 44 | self.setNeedsDisplay() 45 | } 46 | } 47 | 48 | public var direction : UUGradientDirection = .horizontal 49 | { 50 | didSet 51 | { 52 | self.setNeedsDisplay() 53 | } 54 | } 55 | 56 | public var transparentClipRect : CGRect = CGRect.zero 57 | { 58 | didSet 59 | { 60 | self.isOpaque = false 61 | self.setNeedsDisplay() 62 | } 63 | } 64 | 65 | @IBInspectable public var directionAdapter : Int 66 | { 67 | get 68 | { 69 | return self.direction.rawValue 70 | } 71 | 72 | set( val) 73 | { 74 | self.direction = UUGradientDirection(rawValue: val) ?? .horizontal 75 | } 76 | } 77 | 78 | override required public init(frame: CGRect) 79 | { 80 | super.init(frame: frame) 81 | } 82 | 83 | required public init?(coder aDecoder: NSCoder) 84 | { 85 | super.init(coder: aDecoder) 86 | } 87 | 88 | override public func draw(_ rect: CGRect) 89 | { 90 | let context = UIGraphicsGetCurrentContext()! 91 | let colorSpace = CGColorSpaceCreateDeviceRGB() 92 | 93 | let midColor = UIColor.uuCalculateMidColor(startColor: self.startColor, endColor: self.endColor) 94 | 95 | let colors : [CGColor] = [ self.startColor.cgColor, midColor.cgColor, self.endColor.cgColor ] 96 | let locations : [CGFloat] = [ 0.0, CGFloat(self.midPoint), 1.0 ] 97 | 98 | let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations)! 99 | 100 | var startPoint = CGPoint(x: rect.minX, y: rect.midY) 101 | var endPoint = CGPoint(x: rect.maxX, y: rect.midY) 102 | 103 | if (self.direction == .vertical) 104 | { 105 | startPoint = CGPoint(x: rect.midX, y: rect.minY) 106 | endPoint = CGPoint(x: rect.midX, y: rect.maxY) 107 | } 108 | 109 | context.saveGState() 110 | context.addRect(rect) 111 | context.clip() 112 | context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: CGGradientDrawingOptions(rawValue: 0)) 113 | 114 | context.restoreGState() 115 | 116 | context.clear(transparentClipRect) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUJson.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUJson.swift 3 | // Useful Utilities - JSON Extensions for a variety of objects 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import Foundation 11 | 12 | public extension NSObject 13 | { 14 | public func uuToJsonString(_ prettyPrinted: Bool = false) -> String 15 | { 16 | let jsonData : Data? = uuToJson(prettyPrinted) 17 | var jsonStr : String? = nil 18 | 19 | if (jsonData != nil) 20 | { 21 | jsonStr = String.init(data: jsonData!, encoding: .utf8) 22 | } 23 | 24 | if (jsonStr == nil) 25 | { 26 | jsonStr = "" 27 | } 28 | 29 | return jsonStr! 30 | } 31 | 32 | public func uuToJson(_ prettyPrinted: Bool = false) -> Data? 33 | { 34 | var data : Data? = nil 35 | 36 | do 37 | { 38 | let writingOptions: JSONSerialization.WritingOptions = prettyPrinted ? [ JSONSerialization.WritingOptions.prettyPrinted ] : [] 39 | 40 | data = try JSONSerialization.data(withJSONObject: self, options: writingOptions) 41 | } 42 | catch 43 | { 44 | data = nil 45 | } 46 | 47 | 48 | return data 49 | } 50 | } 51 | 52 | public extension Dictionary 53 | { 54 | public func uuToJsonString(_ prettyPrinted: Bool = false) -> String 55 | { 56 | return (self as NSObject).uuToJsonString(prettyPrinted) 57 | } 58 | 59 | public func uuToJson(_ prettyPrinted: Bool = false) -> Data? 60 | { 61 | return (self as NSObject).uuToJson(prettyPrinted) 62 | } 63 | } 64 | 65 | public extension Array 66 | { 67 | public func uuToJsonString(_ prettyPrinted: Bool = false) -> String 68 | { 69 | return (self as NSObject).uuToJsonString(prettyPrinted) 70 | } 71 | 72 | public func uuToJson(_ prettyPrinted: Bool = false) -> Data? 73 | { 74 | return (self as NSObject).uuToJson(prettyPrinted) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUMapView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUMapView.swift 3 | // Useful Utilities - Helpful methods for MKMapView 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | import MapKit 12 | 13 | public extension MKMapView 14 | { 15 | public static func uuFindBoundingBox(annotations: [MKAnnotation]) -> MKCoordinateRegion? 16 | { 17 | var minLat : CLLocationDegrees = CLLocationDegrees(Int.max) 18 | var maxLat : CLLocationDegrees = CLLocationDegrees(Int.min) 19 | var minLng : CLLocationDegrees = CLLocationDegrees(Int.max) 20 | var maxLng : CLLocationDegrees = CLLocationDegrees(Int.min) 21 | 22 | var foundMinLat : Bool = false 23 | var foundMinLng : Bool = false 24 | var foundMaxLat : Bool = false 25 | var foundMaxLng : Bool = false 26 | 27 | for annotation in annotations 28 | { 29 | if (annotation.isKind(of: MKUserLocation.classForCoder())) 30 | { 31 | continue 32 | } 33 | 34 | let lat = annotation.coordinate.latitude 35 | let lng = annotation.coordinate.longitude 36 | 37 | if (lat != 0.0 || lng != 0.0) 38 | { 39 | if (lat < minLat) 40 | { 41 | minLat = lat 42 | foundMinLat = true 43 | } 44 | 45 | if (lat > maxLat) 46 | { 47 | maxLat = lat 48 | foundMaxLat = true 49 | } 50 | 51 | if (lng < minLng) 52 | { 53 | minLng = lng 54 | foundMinLng = true 55 | } 56 | 57 | if (lng > maxLng) 58 | { 59 | maxLng = lng 60 | foundMaxLng = true 61 | } 62 | } 63 | } 64 | 65 | if (foundMinLat && foundMinLng && foundMaxLat && foundMaxLng) 66 | { 67 | var boundingBox : MKCoordinateRegion = MKCoordinateRegion() 68 | boundingBox.center.latitude = minLat + ((maxLat - minLat) / 2.0) 69 | boundingBox.center.longitude = minLng + ((maxLng - minLng) / 2.0) 70 | boundingBox.span.latitudeDelta = fabs(maxLat - minLat) 71 | boundingBox.span.longitudeDelta = fabs(maxLng - minLng) 72 | return boundingBox 73 | } 74 | else 75 | { 76 | return nil 77 | } 78 | } 79 | 80 | public func uuZoomToAnnotations(animated: Bool, center: CLLocationCoordinate2D? = nil) 81 | { 82 | var region = MKMapView.uuFindBoundingBox(annotations: annotations) 83 | if (region != nil) 84 | { 85 | if (center != nil && CLLocationCoordinate2DIsValid(center!)) 86 | { 87 | region!.center.latitude = center!.latitude 88 | region!.center.longitude = center!.longitude 89 | } 90 | 91 | let adjustedRegion = regionThatFits(region!) 92 | setRegion(adjustedRegion, animated: animated) 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUObjectFactory.swift: -------------------------------------------------------------------------------- 1 | // UUObjectFactory 2 | // Useful Utilities - Helpful methods for Converting Objects 3 | // to and from dictionaries 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | public protocol UUObjectFactory 13 | { 14 | static func uuObjectFromDictionary(dictionary : [AnyHashable:Any], context: Any?) -> Self? 15 | } 16 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UURandom.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UURandom.swift 3 | // Useful Utilities - Handy helpers for generating random numbers and picking 4 | // random elements 5 | // 6 | // License: 7 | // You are free to use this code for whatever purposes you desire. 8 | // The only requirement is that you smile everytime you use it. 9 | // 10 | 11 | import Foundation 12 | 13 | public class UURandom 14 | { 15 | public static func randomUInt32() -> UInt32 16 | { 17 | return arc4random() 18 | } 19 | 20 | public static func randomUInt32(low: UInt32, high: UInt32) -> UInt32 21 | { 22 | var l = low 23 | var h = high 24 | if (low > high) 25 | { 26 | let tmp = l 27 | l = h 28 | h = tmp 29 | } 30 | 31 | let range = h - l + 1 32 | let rand = arc4random_uniform(range) 33 | return (l + rand) 34 | } 35 | 36 | public static func randomBool() -> Bool 37 | { 38 | return randomUInt32() % 2 == 0 39 | } 40 | 41 | public static func randomBytes(length: Int) -> Data 42 | { 43 | guard let buffer = NSMutableData(length: length) else 44 | { 45 | return Data() 46 | } 47 | 48 | let result = SecRandomCopyBytes(kSecRandomDefault, length, buffer.mutableBytes) 49 | if (result != 0) 50 | { 51 | return Data() 52 | } 53 | 54 | return buffer as Data 55 | } 56 | 57 | public static func randomUInt8() -> UInt8 58 | { 59 | let bytes = randomBytes(length: 1) 60 | let byteArray = [UInt8](bytes) 61 | return byteArray[0] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UURemoteImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UURemoteImage.swift 3 | // Useful Utilities - An extension to Useful Utilities 4 | // UURemoteData that exposes the cached data as UIImage objects 5 | // 6 | // License: 7 | // You are free to use this code for whatever purposes you desire. 8 | // The only requirement is that you smile everytime you use it. 9 | // 10 | // NOTE: This class depends on the following toolbox classes: 11 | // 12 | // UUHttpSession 13 | // UUDataCache 14 | // UURemoteData 15 | // 16 | 17 | import UIKit 18 | 19 | public protocol UURemoteImageProtocol 20 | { 21 | func image(for key: String, skipDownload: Bool) -> UIImage? 22 | func isDownloadPending(for key: String) -> Bool 23 | 24 | func metaData(for key: String) -> [String:Any] 25 | func set(metaData: [String:Any], for key: String) 26 | 27 | func imageSize(for key: String) -> CGSize? 28 | } 29 | 30 | public class UURemoteImage: NSObject, UURemoteImageProtocol 31 | { 32 | public struct MetaData 33 | { 34 | public static let ImageSize = "ImageSize" 35 | } 36 | 37 | public static let shared = UURemoteImage() 38 | 39 | //////////////////////////////////////////////////////////////////////////// 40 | // UURemoteImageProtocol Implementation 41 | //////////////////////////////////////////////////////////////////////////// 42 | 43 | public func image(for key: String, skipDownload: Bool = false) -> UIImage? 44 | { 45 | let url = URL(string: key) 46 | if (url == nil) 47 | { 48 | return nil 49 | } 50 | 51 | let cached = UUDataCache.shared.data(for: key) 52 | if (cached != nil) 53 | { 54 | return UIImage(data: cached!) 55 | } 56 | 57 | var data : Data? = nil 58 | 59 | if (skipDownload) 60 | { 61 | data = UUDataCache.shared.data(for: key) 62 | } 63 | else 64 | { 65 | data = UURemoteData.shared.data(for: key) 66 | } 67 | 68 | if (data != nil) 69 | { 70 | let img = UIImage(data: data!) 71 | if (img != nil) 72 | { 73 | var md = metaData(for: key) 74 | md[MetaData.ImageSize] = img!.size 75 | set(metaData: md, for: key) 76 | 77 | return img 78 | } 79 | } 80 | 81 | return nil 82 | } 83 | 84 | public func isDownloadPending(for key: String) -> Bool 85 | { 86 | return UURemoteData.shared.isDownloadPending(for: key) 87 | } 88 | 89 | public func metaData(for key: String) -> [String:Any] 90 | { 91 | return UURemoteData.shared.metaData(for: key) 92 | } 93 | 94 | public func set(metaData: [String:Any], for key: String) 95 | { 96 | UURemoteData.shared.set(metaData: metaData, for: key) 97 | } 98 | 99 | public func imageSize(for key: String) -> CGSize? 100 | { 101 | let md = UURemoteData.shared.metaData(for: key) 102 | return md[MetaData.ImageSize] as? CGSize 103 | } 104 | 105 | //////////////////////////////////////////////////////////////////////////// 106 | // Private methods 107 | //////////////////////////////////////////////////////////////////////////// 108 | 109 | } 110 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUTextField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUTextField 3 | // Useful Utilities - Simple UITextField subclass to support a few IBDesignable additions 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | @IBDesignable class UUTextField: UITextField 13 | { 14 | @IBInspectable public var leftPadding : CGFloat = 0 15 | { 16 | didSet 17 | { 18 | self.setNeedsDisplay() 19 | } 20 | } 21 | 22 | @IBInspectable public var rightPadding : CGFloat = 0 23 | { 24 | didSet 25 | { 26 | self.setNeedsDisplay() 27 | } 28 | } 29 | 30 | @IBInspectable public var topPadding : CGFloat = 0 31 | { 32 | didSet 33 | { 34 | self.setNeedsDisplay() 35 | } 36 | } 37 | 38 | @IBInspectable public var bottomPadding : CGFloat = 0 39 | { 40 | didSet 41 | { 42 | self.setNeedsDisplay() 43 | } 44 | } 45 | 46 | private var paddingRect : UIEdgeInsets 47 | { 48 | return UIEdgeInsets(top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding) 49 | } 50 | 51 | override func textRect(forBounds bounds: CGRect) -> CGRect 52 | { 53 | return UIEdgeInsetsInsetRect(bounds, paddingRect) 54 | } 55 | 56 | override func placeholderRect(forBounds bounds: CGRect) -> CGRect 57 | { 58 | return UIEdgeInsetsInsetRect(bounds, paddingRect) 59 | } 60 | 61 | override func editingRect(forBounds bounds: CGRect) -> CGRect 62 | { 63 | return UIEdgeInsetsInsetRect(bounds, paddingRect) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUToolbox.h: -------------------------------------------------------------------------------- 1 | // 2 | // Useful Utilities 3 | // 4 | // License: 5 | // You are free to use this code for whatever purposes you desire. 6 | // The only requirement is that you smile everytime you use it. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for UUToolbox. 12 | FOUNDATION_EXPORT double UUToolboxVersionNumber; 13 | 14 | //! Project version string for UUToolbox. 15 | FOUNDATION_EXPORT const unsigned char UUToolboxVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUView.swift: -------------------------------------------------------------------------------- 1 | // UUView 2 | // Useful Utilities - Helpful methods for UIView 3 | // 4 | // License: 5 | // You are free to use this code for whatever purposes you desire. 6 | // The only requirement is that you smile everytime you use it. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView 12 | { 13 | static let blurEffectViewTag : Int = 90210 14 | 15 | public func uuAddBlurEffectView() 16 | { 17 | uuRemoveBlurEffectView() 18 | 19 | let effect = UIBlurEffect(style: .light) 20 | let effectView = UIVisualEffectView.init(effect: effect) 21 | 22 | effectView.frame = self.bounds 23 | effectView.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight] 24 | effectView.tag = UIView.blurEffectViewTag 25 | insertSubview(effectView, at: 0) 26 | } 27 | 28 | public func uuRemoveBlurEffectView() 29 | { 30 | self.superview?.viewWithTag(UIView.blurEffectViewTag)?.removeFromSuperview() 31 | } 32 | 33 | @IBInspectable public var uuCornerRadius: CGFloat 34 | { 35 | get 36 | { 37 | return layer.cornerRadius 38 | } 39 | 40 | set 41 | { 42 | layer.cornerRadius = newValue 43 | layer.masksToBounds = newValue > 0 44 | } 45 | } 46 | 47 | @IBInspectable public var uuBorderWidth: CGFloat 48 | { 49 | get 50 | { 51 | return layer.borderWidth 52 | } 53 | 54 | set 55 | { 56 | layer.borderWidth = newValue 57 | } 58 | } 59 | 60 | @IBInspectable public var uuBorderColor: UIColor? 61 | { 62 | get 63 | { 64 | let color = UIColor(cgColor: layer.borderColor!) 65 | return color 66 | } 67 | 68 | set 69 | { 70 | layer.borderColor = newValue?.cgColor 71 | } 72 | } 73 | 74 | @IBInspectable public var uuShadowRadius: CGFloat 75 | { 76 | get 77 | { 78 | return layer.shadowRadius 79 | } 80 | 81 | set 82 | { 83 | layer.shadowColor = UIColor.black.cgColor 84 | layer.shadowOffset = CGSize(width: 0, height: 2) 85 | layer.shadowOpacity = 0.35 86 | layer.shadowRadius = newValue 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolbox/UUViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUViewController.swift 3 | // Useful Utilities - Extensions for UIViewController 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. 7 | // The only requirement is that you smile everytime you use it. 8 | // 9 | 10 | import UIKit 11 | 12 | public extension UIViewController 13 | { 14 | public func uuFindControllerOfType(_ clazz : AnyClass) -> UIViewController? 15 | { 16 | var foundVc : UIViewController? = nil 17 | 18 | var navController : UINavigationController? = (self as? UINavigationController) 19 | if (navController == nil) 20 | { 21 | navController = self.navigationController 22 | } 23 | 24 | if (navController != nil) 25 | { 26 | for vc in navController!.viewControllers 27 | { 28 | if (object_getClass(vc) == clazz) 29 | { 30 | foundVc = vc 31 | break 32 | } 33 | } 34 | } 35 | 36 | return foundVc 37 | } 38 | 39 | public func uuPopToControllerOfType(_ clazz : AnyClass, animated : Bool = true) -> Bool 40 | { 41 | let vcToPopTo = uuFindControllerOfType(clazz) 42 | 43 | let didFindController = (vcToPopTo != nil) 44 | 45 | if (didFindController) 46 | { 47 | navigationController?.popToViewController(vcToPopTo!, animated: animated) 48 | } 49 | 50 | return didFindController 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolboxLib.modulemap: -------------------------------------------------------------------------------- 1 | module UUToolbox 2 | { 3 | export * 4 | } 5 | 6 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolboxLib.xcodeproj/xcshareddata/xcschemes/UUToolbox.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolboxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolboxTests/UUTestCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUTestCase.swift 3 | // Useful Utilities 4 | // 5 | // License: 6 | // You are free to use this code for whatever purposes you desire. The only requirement is that you smile everytime you use it. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | import UUToolbox 12 | 13 | public extension XCTestCase 14 | { 15 | public func UUExpectationForMethod( 16 | function : NSString = #function, 17 | tag : NSString = "") -> XCTestExpectation 18 | { 19 | return expectation(description: "_\(function)_\(tag)_") 20 | } 21 | 22 | public func UUWaitForExpectations(_ timeout: TimeInterval = 60) 23 | { 24 | waitForExpectations(timeout: timeout) 25 | { (err: Error?) in 26 | if (err != nil) 27 | { 28 | XCTFail("Failed waiting for expectation, error: \(err!)") 29 | } 30 | } 31 | } 32 | 33 | public func UULogBeginTest(function : NSString = #function) 34 | { 35 | UUDebugLog("\n\n******************** BEGIN TEST \(function) ********************\n\n") 36 | } 37 | 38 | public func UULogEndTest(function : NSString = #function) 39 | { 40 | UUDebugLog("\n\n******************** END TEST \(function) ********************\n\n") 41 | } 42 | 43 | func testXCTestCaseExtensionMethods() 44 | { 45 | UULogBeginTest() 46 | 47 | let exp = UUExpectationForMethod() 48 | 49 | DispatchQueue.main.async 50 | { 51 | exp.fulfill() 52 | } 53 | 54 | UUWaitForExpectations() 55 | UULogEndTest() 56 | } 57 | 58 | func testRandomWords() 59 | { 60 | let a = randomWord(20) 61 | XCTAssertNotNil(a) 62 | UUDebugLog("\(a)") 63 | 64 | let b = randomWords(5, 10) 65 | XCTAssertNotNil(b) 66 | UUDebugLog("\(b)") 67 | } 68 | 69 | func randomWord(_ length: Int) -> String 70 | { 71 | let sb = NSMutableString() 72 | 73 | while (sb.length < length) 74 | { 75 | let b = UURandom.randomUInt8() 76 | if (b >= 65 && b <= 90) || (b >= 97 && b <= 122) // A-Z or a-z 77 | { 78 | let u = UnicodeScalar(b) 79 | let c = Character(u) 80 | sb.append(String(c)) 81 | } 82 | } 83 | 84 | return sb as String 85 | } 86 | 87 | func randomWords(_ maxNumberOfWords: Int, _ maxWordLength: Int) -> String 88 | { 89 | let sb = NSMutableString() 90 | 91 | let words = UURandom.randomUInt32(low: 0, high: UInt32(maxNumberOfWords)) 92 | var i = 0 93 | while (i < words) 94 | { 95 | sb.append(randomWord(maxWordLength)) 96 | sb.append(" ") 97 | i = i + 1 98 | } 99 | 100 | return sb as String 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /swift/UUToolbox/UUToolboxTests/UUToolboxTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUToolboxTests.swift 3 | // UUToolboxTests 4 | // 5 | // Created by Ryan DeVore on 3/8/18. 6 | // Copyright © 2018 Useful Utilities. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import UUToolbox 11 | 12 | class UUToolboxTests: XCTestCase 13 | { 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | } 25 | --------------------------------------------------------------------------------