├── .gitignore ├── JenkinsCI.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── JenkinsCI.xcscheme ├── JenkinsCI.xcworkspace └── contents.xcworkspacedata ├── JenkinsCI ├── Classes │ ├── AppDelegate │ │ ├── AppDelegate.h │ │ └── AppDelegate.m │ ├── Controllers │ │ ├── ClubsViewController │ │ │ ├── ClubsViewController.h │ │ │ ├── ClubsViewController.m │ │ │ └── Datasource │ │ │ │ ├── ClubsViewController+UITableViewDatasource.h │ │ │ │ └── ClubsViewController+UITableViewDatasource.m │ │ ├── FetchedResultsTableViewController │ │ │ ├── FetchedResultsTableViewController.h │ │ │ └── FetchedResultsTableViewController.m │ │ ├── PlayerProfileViewController │ │ │ ├── PlayerProfileViewController.h │ │ │ └── PlayerProfileViewController.m │ │ ├── PlayersViewController │ │ │ ├── Datasource │ │ │ │ ├── PlayersViewController+UITableViewDatasource.h │ │ │ │ └── PlayersViewController+UITableViewDatasource.m │ │ │ ├── PlayersViewController.h │ │ │ └── PlayersViewController.m │ │ └── SquadViewController │ │ │ ├── Datasource │ │ │ ├── SquadViewController+TableViewDatasource.h │ │ │ └── SquadViewController+TableViewDatasource.m │ │ │ ├── SquadViewController.h │ │ │ └── SquadViewController.m │ ├── Managers │ │ ├── CoreDataClubManager │ │ │ ├── CoreDataClubManager.h │ │ │ └── CoreDataClubManager.m │ │ ├── CoreDataEntityManager │ │ │ ├── CoreDataEntityManager.h │ │ │ └── CoreDataEntityManager.m │ │ ├── CoreDataManager │ │ │ ├── CoreDataManager.h │ │ │ └── CoreDataManager.m │ │ ├── CoreDataPlayerManger │ │ │ ├── CoreDataPlayerManager.h │ │ │ └── CoreDataPlayerManager.m │ │ └── DataImporter │ │ │ ├── DataImporter.h │ │ │ └── DataImporter.m │ ├── Model │ │ ├── Club │ │ │ ├── Club.h │ │ │ └── Club.m │ │ └── Player │ │ │ ├── Player.h │ │ │ └── Player.m │ ├── Utils │ │ └── UIImageView+RoundCorners │ │ │ ├── UIImageView+RoundCorners.h │ │ │ └── UIImageView+RoundCorners.m │ └── View │ │ ├── ClubTableViewCell │ │ ├── ClubTableViewCell.h │ │ └── ClubTableViewCell.m │ │ ├── PlayerTableViewCell │ │ ├── PlayerTableViewCell.h │ │ └── PlayerTableViewCell.m │ │ └── SquadProfileTableViewCell │ │ ├── SquadProfileTableViewCell.h │ │ └── SquadProfileTableViewCell.m ├── CoreData │ └── Model.xcdatamodeld │ │ └── Model.xcdatamodel │ │ └── contents ├── Info.plist ├── PrefixHeader.pch ├── Resources │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x.png │ │ │ └── Icon-Small@3x.png │ │ ├── club-logos │ │ │ ├── Arsenal-FC-logo.imageset │ │ │ │ ├── Arsenal-FC-icon.png │ │ │ │ └── Contents.json │ │ │ ├── Chelsea-FC-logo.imageset │ │ │ │ ├── Chelsea-FC-icon.png │ │ │ │ └── Contents.json │ │ │ ├── Everton-FC-logo.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── Everton-FC-icon.png │ │ │ ├── Liverpool-FC-logo.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── Liverpool-FC-icon.png │ │ │ └── Manchester-United-logo.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── Manchester-United-icon.png │ │ ├── persons.imageset │ │ │ ├── Contents.json │ │ │ ├── persons@2x.png │ │ │ └── persons@3x.png │ │ ├── player-pictures │ │ │ ├── aaron_ramsey.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── aaron_ramsey.png │ │ │ ├── angel_di_maria.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── angel_di_maria.png │ │ │ ├── daniel_sturridge.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── daniel_sturridge.png │ │ │ ├── eden_hazard.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── eden_hazard.png │ │ │ ├── jordan_henderson.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── jordan_henderson.png │ │ │ ├── martin_skrtel.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── martin_skrtel.png │ │ │ ├── player_placeholder.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── player_placeholder.png │ │ │ ├── ross_barkley.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── ross_barkley.png │ │ │ ├── steven_gerrard.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── steven_gerrard.png │ │ │ └── wayne_rooney.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── wayne_rooney.png │ │ └── stadium.imageset │ │ │ ├── Contents.json │ │ │ ├── stadium@2x.png │ │ │ └── stadium@3x.png │ └── db.json └── main.m ├── JenkinsCITests ├── CoreDataTests │ └── CoreDataImportTest.m └── Info.plist ├── LICENSE ├── Podfile ├── Podfile.lock ├── Pods ├── CocoaLumberjack │ ├── Classes │ │ ├── CLI │ │ │ ├── CLIColor.h │ │ │ └── CLIColor.m │ │ ├── CocoaLumberjack.h │ │ ├── DDASLLogCapture.h │ │ ├── DDASLLogCapture.m │ │ ├── DDASLLogger.h │ │ ├── DDASLLogger.m │ │ ├── DDAbstractDatabaseLogger.h │ │ ├── DDAbstractDatabaseLogger.m │ │ ├── DDAssertMacros.h │ │ ├── DDFileLogger.h │ │ ├── DDFileLogger.m │ │ ├── DDLog+LOGV.h │ │ ├── DDLog.h │ │ ├── DDLog.m │ │ ├── DDLogMacros.h │ │ ├── DDTTYLogger.h │ │ ├── DDTTYLogger.m │ │ └── Extensions │ │ │ ├── DDContextFilterLogFormatter.h │ │ │ ├── DDContextFilterLogFormatter.m │ │ │ ├── DDDispatchQueueLogFormatter.h │ │ │ ├── DDDispatchQueueLogFormatter.m │ │ │ ├── DDMultiFormatter.h │ │ │ └── DDMultiFormatter.m │ ├── LICENSE.txt │ └── README.md ├── CrashlyticsFramework │ ├── Crashlytics.framework │ │ ├── Crashlytics │ │ ├── Headers │ │ ├── Modules │ │ │ └── module.modulemap │ │ ├── Resources │ │ ├── Versions │ │ │ ├── A │ │ │ │ ├── Crashlytics │ │ │ │ ├── Headers │ │ │ │ │ └── Crashlytics.h │ │ │ │ └── Resources │ │ │ │ │ └── Info.plist │ │ │ └── Current │ │ ├── run │ │ └── submit │ ├── LICENSE │ └── README.md ├── Headers │ └── Public │ │ ├── CocoaLumberjack │ │ ├── CLIColor.h │ │ ├── CocoaLumberjack.h │ │ ├── DDASLLogCapture.h │ │ ├── DDASLLogger.h │ │ ├── DDAbstractDatabaseLogger.h │ │ ├── DDAssertMacros.h │ │ ├── DDContextFilterLogFormatter.h │ │ ├── DDDispatchQueueLogFormatter.h │ │ ├── DDFileLogger.h │ │ ├── DDLog+LOGV.h │ │ ├── DDLog.h │ │ ├── DDLogMacros.h │ │ ├── DDMultiFormatter.h │ │ └── DDTTYLogger.h │ │ └── CrashlyticsFramework │ │ └── Crashlytics.h ├── Manifest.lock ├── Pods.xcodeproj │ └── project.pbxproj └── Target Support Files │ ├── Pods-CocoaLumberjack │ ├── Pods-CocoaLumberjack-Private.xcconfig │ ├── Pods-CocoaLumberjack-dummy.m │ ├── Pods-CocoaLumberjack-prefix.pch │ └── Pods-CocoaLumberjack.xcconfig │ ├── Pods-CrashlyticsFramework │ ├── Pods-CrashlyticsFramework-Private.xcconfig │ ├── Pods-CrashlyticsFramework-dummy.m │ ├── Pods-CrashlyticsFramework-prefix.pch │ └── Pods-CrashlyticsFramework.xcconfig │ └── Pods │ ├── Pods-acknowledgements.markdown │ ├── Pods-acknowledgements.plist │ ├── Pods-dummy.m │ ├── Pods-environment.h │ ├── Pods-resources.sh │ ├── Pods.debug.xcconfig │ └── Pods.release.xcconfig └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | -------------------------------------------------------------------------------- /JenkinsCI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JenkinsCI.xcodeproj/xcshareddata/xcschemes/JenkinsCI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 69 | 70 | 79 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 98 | 104 | 105 | 106 | 107 | 109 | 110 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /JenkinsCI.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/AppDelegate/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. 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 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/AppDelegate/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DataImporter.h" 11 | #import 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | // Override point for customization after application launch. 22 | 23 | // Checks if the import has been done and if not imports the data 24 | [self checkImport]; 25 | 26 | // Start Crashlytics 27 | [self startCrashlytics]; 28 | 29 | return YES; 30 | } 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application { 33 | // 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. 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidEnterBackground:(UIApplication *)application { 38 | // 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. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | - (void)applicationWillEnterForeground:(UIApplication *)application { 43 | // 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. 44 | } 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application { 47 | // 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. 48 | } 49 | 50 | - (void)applicationWillTerminate:(UIApplication *)application { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | #pragma mark - Import 55 | 56 | - (void)checkImport { 57 | DataImporter *importer = [[DataImporter alloc] init]; 58 | if (![importer didImportData]) { 59 | [importer importData]; 60 | } 61 | } 62 | 63 | 64 | 65 | #pragma mark - Crashlytics 66 | 67 | - (void)startCrashlytics { 68 | // [Crashlytics startWithAPIKey:<#(NSString *)#>]; 69 | //#ifdef DEBUG 70 | // [[Crashlytics sharedInstance] setDebugMode:YES]; 71 | //#else 72 | // [[Crashlytics sharedInstance] setDebugMode:NO]; 73 | //#endif 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/ClubsViewController/ClubsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ClubsViewController.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreDataManager.h" 11 | #import "FetchedResultsTableViewController.h" 12 | 13 | @interface ClubsViewController : FetchedResultsTableViewController 14 | 15 | @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/ClubsViewController/ClubsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ClubsViewController.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "ClubsViewController.h" 10 | #import "SquadViewController.h" 11 | #import "ClubsViewController+UITableViewDatasource.h" 12 | 13 | static NSString * const kClubFetchEntityName = @"Club"; 14 | static NSString * const kClubFetchSortingKey = @"clubName"; 15 | 16 | static NSString * const kPresentSquadSegueIdentifier = @"segue_clubsShowSquad"; 17 | 18 | @interface ClubsViewController () 19 | 20 | @end 21 | 22 | @implementation ClubsViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | 27 | // Uncomment the following line to preserve selection between presentations. 28 | // self.clearsSelectionOnViewWillAppear = NO; 29 | 30 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 31 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 32 | 33 | [self setupClubsFetchedResultsControler]; 34 | } 35 | 36 | - (void)didReceiveMemoryWarning { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | - (void)setupClubsFetchedResultsControler { 42 | CoreDataManager *manager = [CoreDataManager sharedInstance]; 43 | self.fetchedResultsController = [manager fetchedResultsControllerWithEntityName:kClubFetchEntityName 44 | predicate:nil 45 | sortingKeys:@[kClubFetchSortingKey] 46 | sectionNameKey:nil 47 | ascending:YES 48 | delegate:self]; 49 | 50 | self.cellConfigurer = self; 51 | 52 | NSError *error = nil; 53 | [self.fetchedResultsController performFetch:&error]; 54 | if (error) { 55 | DDLogError(@"Fetch Erorr: %@", error); 56 | } 57 | 58 | } 59 | 60 | 61 | #pragma mark - Navigation 62 | 63 | - (void)prepareForSegue:(UIStoryboardSegue *)segue 64 | sender:(id)sender 65 | { 66 | if ([segue.identifier isEqualToString:kPresentSquadSegueIdentifier]) { 67 | SquadViewController *squadViewController = (SquadViewController *)segue.destinationViewController; 68 | squadViewController.presentedClub = [self.fetchedResultsController objectAtIndexPath:self.tableView.indexPathForSelectedRow]; 69 | } 70 | } 71 | 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/ClubsViewController/Datasource/ClubsViewController+UITableViewDatasource.h: -------------------------------------------------------------------------------- 1 | // 2 | // ClubsViewController+UITableViewDatasource.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "ClubsViewController.h" 10 | 11 | @interface ClubsViewController (UITableViewDatasource) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/ClubsViewController/Datasource/ClubsViewController+UITableViewDatasource.m: -------------------------------------------------------------------------------- 1 | // 2 | // ClubsViewController+UITableViewDatasource.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "ClubsViewController+UITableViewDatasource.h" 10 | #import "ClubTableViewCell.h" 11 | #import "Club.h" 12 | 13 | static NSString * const kClubsCellIdentifier = @"_clubCell"; 14 | 15 | @implementation ClubsViewController (UITableViewDatasource) 16 | 17 | 18 | #pragma mark - UITableViewDataSource 19 | 20 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 21 | return 1; 22 | } 23 | 24 | - (NSInteger)tableView:(UITableView *)tableView 25 | numberOfRowsInSection:(NSInteger)section 26 | { 27 | return [[self.fetchedResultsController fetchedObjects] count]; 28 | } 29 | 30 | - (UITableViewCell *)tableView:(UITableView *)tableView 31 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 32 | { 33 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kClubsCellIdentifier 34 | forIndexPath:indexPath]; 35 | 36 | [self configureCell:cell forRowAtIndexPath:indexPath]; 37 | 38 | return cell; 39 | } 40 | 41 | - (void)configureCell:(UITableViewCell *)cell 42 | forRowAtIndexPath:(NSIndexPath *)indexPath 43 | { 44 | Club *club = [self.fetchedResultsController objectAtIndexPath:indexPath]; 45 | ClubTableViewCell *clubCell = (ClubTableViewCell *)cell; 46 | 47 | clubCell.clubNameLabel.text = club.clubName; 48 | clubCell.clubLogoView.image = [club logoImage]; 49 | clubCell.squadSizeLabel.text = [self squadSizeForClub:club]; 50 | 51 | } 52 | 53 | 54 | - (NSString *)squadSizeForClub:(Club *)club { 55 | NSInteger size = [club.squad count]; 56 | NSString *squadSize; 57 | switch (size) { 58 | case 0: 59 | squadSize = @"No players"; 60 | break; 61 | case 1: 62 | squadSize = @"One player"; 63 | break; 64 | default: 65 | squadSize = [NSString stringWithFormat:@"%li players", (long)size]; 66 | break; 67 | } 68 | 69 | return squadSize; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/FetchedResultsTableViewController/FetchedResultsTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FetchedResultsTableViewController.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 24/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | @import CoreData; 11 | 12 | @protocol UITableViewCellConfigurer 13 | 14 | - (void)configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; 15 | 16 | @end 17 | 18 | @interface FetchedResultsTableViewController : UITableViewController 19 | 20 | /** 21 | * Cell configurerDelegate object. 22 | */ 23 | @property (nonatomic, assign) id cellConfigurer; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/FetchedResultsTableViewController/FetchedResultsTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FetchedResultsTableViewController.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 24/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "FetchedResultsTableViewController.h" 10 | 11 | 12 | @implementation FetchedResultsTableViewController 13 | 14 | #pragma mark - NSFetchedResultsControllerDelegate 15 | 16 | - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 17 | [self.tableView beginUpdates]; 18 | } 19 | 20 | - (void)controller:(NSFetchedResultsController *)controller 21 | didChangeSection:(id )sectionInfo 22 | atIndex:(NSUInteger)sectionIndex 23 | forChangeType:(NSFetchedResultsChangeType)type 24 | { 25 | switch(type) { 26 | case NSFetchedResultsChangeInsert: 27 | [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic]; 28 | break; 29 | case NSFetchedResultsChangeDelete: 30 | [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic]; 31 | break; 32 | default: 33 | break; 34 | } 35 | } 36 | 37 | - (void)controller:(NSFetchedResultsController *)controller 38 | didChangeObject:(id)object 39 | atIndexPath:(NSIndexPath *)indexPath 40 | forChangeType:(NSFetchedResultsChangeType)type 41 | newIndexPath:(NSIndexPath *)newIndexPath 42 | { 43 | switch(type) { 44 | case NSFetchedResultsChangeInsert: 45 | [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 46 | break; 47 | case NSFetchedResultsChangeDelete: 48 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 49 | break; 50 | case NSFetchedResultsChangeUpdate: 51 | [self.cellConfigurer configureCell:[self.tableView cellForRowAtIndexPath:indexPath] forRowAtIndexPath:indexPath]; 52 | break; 53 | case NSFetchedResultsChangeMove: 54 | [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 55 | [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 56 | break; 57 | } 58 | } 59 | 60 | - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 61 | [self.tableView endUpdates]; 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/PlayerProfileViewController/PlayerProfileViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerProfileViewController.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class Player; 12 | 13 | @interface PlayerProfileViewController : UIViewController 14 | 15 | @property (nonatomic, strong) Player *presentedPlayer; 16 | 17 | // Interface outlets 18 | @property (weak, nonatomic) IBOutlet UILabel *playerNumberLabel; 19 | @property (weak, nonatomic) IBOutlet UIImageView *playerAvatarImageView; 20 | @property (weak, nonatomic) IBOutlet UILabel *playerFirstNameLabel; 21 | @property (weak, nonatomic) IBOutlet UILabel *playerLastNameLabel; 22 | @property (weak, nonatomic) IBOutlet UILabel *clubNameLabel; 23 | @property (weak, nonatomic) IBOutlet UIImageView *clubLogoImageView; 24 | @property (weak, nonatomic) IBOutlet UILabel *playerPositionLabel; 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/PlayerProfileViewController/PlayerProfileViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerProfileViewController.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "PlayerProfileViewController.h" 10 | #import "Player.h" 11 | #import "Club.h" 12 | 13 | @interface PlayerProfileViewController () 14 | 15 | @end 16 | 17 | @implementation PlayerProfileViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | } 23 | 24 | - (void)didReceiveMemoryWarning { 25 | [super didReceiveMemoryWarning]; 26 | // Dispose of any resources that can be recreated. 27 | } 28 | 29 | - (void)viewWillAppear:(BOOL)animated { 30 | [super viewWillAppear:animated]; 31 | self.title = [self.presentedPlayer playerFullName]; 32 | [self setupPlayerView]; 33 | } 34 | 35 | - (void)setupPlayerView { 36 | self.playerFirstNameLabel.text = self.presentedPlayer.firstName; 37 | self.playerLastNameLabel.text = self.presentedPlayer.lastName; 38 | self.playerAvatarImageView.image = [self.presentedPlayer playerImage]; 39 | self.playerPositionLabel.text = self.presentedPlayer.position; 40 | self.clubNameLabel.text = self.presentedPlayer.club.clubName; 41 | self.clubLogoImageView.image = [self.presentedPlayer.club logoImage]; 42 | self.playerNumberLabel.text = [NSString stringWithFormat:@"No. %@", self.presentedPlayer.shirtNumber]; 43 | } 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/PlayersViewController/Datasource/PlayersViewController+UITableViewDatasource.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayersViewController+UITableViewDatasource.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "PlayersViewController.h" 10 | 11 | @interface PlayersViewController (UITableViewDatasource) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/PlayersViewController/Datasource/PlayersViewController+UITableViewDatasource.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayersViewController+UITableViewDatasource.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "PlayersViewController+UITableViewDatasource.h" 10 | #import "PlayerTableViewCell.h" 11 | #import "Player.h" 12 | #import "Club.h" 13 | 14 | static NSString * const kPlayerCellIdentifier = @"_playerCell"; 15 | 16 | @implementation PlayersViewController (UITableViewDatasource) 17 | 18 | 19 | #pragma mark - UITableViewDataSource 20 | 21 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 22 | return 1; 23 | } 24 | 25 | - (NSInteger)tableView:(UITableView *)tableView 26 | numberOfRowsInSection:(NSInteger)section 27 | { 28 | return [[self.fetchedResultsController fetchedObjects] count]; 29 | } 30 | 31 | - (UITableViewCell *)tableView:(UITableView *)tableView 32 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 33 | { 34 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPlayerCellIdentifier 35 | forIndexPath:indexPath]; 36 | 37 | [self configureCell:cell forRowAtIndexPath:indexPath]; 38 | 39 | return cell; 40 | } 41 | 42 | - (void)configureCell:(UITableViewCell *)cell 43 | forRowAtIndexPath:(NSIndexPath *)indexPath 44 | { 45 | Player *player = [self.fetchedResultsController objectAtIndexPath:indexPath]; 46 | PlayerTableViewCell *playerCell = (PlayerTableViewCell *)cell; 47 | 48 | playerCell.playerFullNameLabel.text = [player playerFullName]; 49 | playerCell.playerImageView.image = [player playerImage]; 50 | playerCell.playerPositionLabel.text = player.position; 51 | playerCell.clubNameLabel.text = player.club.clubName; 52 | } 53 | 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/PlayersViewController/PlayersViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayersViewController.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreDataManager.h" 11 | #import "FetchedResultsTableViewController.h" 12 | 13 | @interface PlayersViewController : FetchedResultsTableViewController 14 | 15 | @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/PlayersViewController/PlayersViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayersViewController.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "PlayersViewController.h" 10 | #import "PlayerProfileViewController.h" 11 | #import "PlayersViewController+UITableViewDatasource.h" 12 | #import "Player.h" 13 | 14 | 15 | static NSString * const kPlayerFetchEntityName = @"Player"; 16 | static NSString * const kPlayerFetchSortingKeyLast = @"lastName"; 17 | static NSString * const kPlayerFetchSortingKeyFirst = @"firstName"; 18 | 19 | static NSString * const kPresentPlayerSegue = @"segue_playersShowPlayer"; 20 | 21 | @interface PlayersViewController () 22 | 23 | @end 24 | 25 | @implementation PlayersViewController 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | 30 | // Uncomment the following line to preserve selection between presentations. 31 | // self.clearsSelectionOnViewWillAppear = NO; 32 | 33 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 34 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 35 | 36 | [self setupPlayersFetchedResultsController]; 37 | } 38 | 39 | - (void)didReceiveMemoryWarning { 40 | [super didReceiveMemoryWarning]; 41 | // Dispose of any resources that can be recreated. 42 | } 43 | 44 | 45 | - (void)setupPlayersFetchedResultsController { 46 | CoreDataManager *manager = [CoreDataManager sharedInstance]; 47 | NSArray *sortingKeys = @[kPlayerFetchSortingKeyLast, kPlayerFetchSortingKeyFirst]; 48 | self.fetchedResultsController = [manager fetchedResultsControllerWithEntityName:kPlayerFetchEntityName 49 | predicate:nil 50 | sortingKeys:sortingKeys 51 | sectionNameKey:nil 52 | ascending:YES 53 | delegate:self]; 54 | 55 | self.cellConfigurer = self; 56 | 57 | NSError *error = nil; 58 | [self.fetchedResultsController performFetch:&error]; 59 | if (error) { 60 | DDLogError(@"Fetch Erorr: %@", error); 61 | } 62 | } 63 | 64 | 65 | #pragma mark - Navigation 66 | 67 | - (void)prepareForSegue:(UIStoryboardSegue *)segue 68 | sender:(id)sender 69 | { 70 | if ([[segue identifier] isEqualToString:kPresentPlayerSegue]) { 71 | PlayerProfileViewController *playerViewController = (PlayerProfileViewController *)segue.destinationViewController; 72 | Player *player = [self.fetchedResultsController objectAtIndexPath:self.tableView.indexPathForSelectedRow]; 73 | [playerViewController setPresentedPlayer:player]; 74 | } 75 | } 76 | 77 | 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/SquadViewController/Datasource/SquadViewController+TableViewDatasource.h: -------------------------------------------------------------------------------- 1 | // 2 | // SquadViewController+TableViewDatasource.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "SquadViewController.h" 10 | 11 | @interface SquadViewController (TableViewDatasource) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/SquadViewController/Datasource/SquadViewController+TableViewDatasource.m: -------------------------------------------------------------------------------- 1 | // 2 | // SquadViewController+TableViewDatasource.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "SquadViewController+TableViewDatasource.h" 10 | #import "SquadProfileTableViewCell.h" 11 | #import "Player.h" 12 | 13 | static NSString * const kSquadCellIdentifier = @"_squadProfileCell"; 14 | 15 | @implementation SquadViewController (TableViewDatasource) 16 | 17 | 18 | #pragma mark - UITableViewDataSource 19 | 20 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 21 | return 1; 22 | } 23 | 24 | - (NSInteger)tableView:(UITableView *)tableView 25 | numberOfRowsInSection:(NSInteger)section 26 | { 27 | return [[self.fetchedResultsController fetchedObjects] count]; 28 | } 29 | 30 | - (UITableViewCell *)tableView:(UITableView *)tableView 31 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 32 | { 33 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kSquadCellIdentifier 34 | forIndexPath:indexPath]; 35 | 36 | [self configureCell:cell forRowAtIndexPath:indexPath]; 37 | 38 | return cell; 39 | } 40 | 41 | - (void)configureCell:(UITableViewCell *)cell 42 | forRowAtIndexPath:(NSIndexPath *)indexPath 43 | { 44 | SquadProfileTableViewCell *playerCell = (SquadProfileTableViewCell *)cell; 45 | Player *player = [self.fetchedResultsController objectAtIndexPath:indexPath]; 46 | playerCell.playerFullNameLabel.text = [player playerFullName]; 47 | playerCell.playerNumberLabel.text = [player.shirtNumber stringValue]; 48 | playerCell.playerPictureView.image = [player playerImage]; 49 | playerCell.playerPositionLabel.text = player.position; 50 | } 51 | 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/SquadViewController/SquadViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SquadViewController.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreDataManager.h" 11 | #import "FetchedResultsTableViewController.h" 12 | @class Club; 13 | 14 | @interface SquadViewController : FetchedResultsTableViewController 15 | 16 | @property (nonatomic, strong) Club *presentedClub; 17 | @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Controllers/SquadViewController/SquadViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SquadViewController.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "SquadViewController.h" 10 | #import "PlayerProfileViewController.h" 11 | #import "SquadViewController+TableViewDatasource.h" 12 | #import "Club.h" 13 | 14 | static NSString * const kSquadPresentPlayerSegue = @"segue_squadShowPlayer"; 15 | 16 | @interface SquadViewController () 17 | 18 | @end 19 | 20 | @implementation SquadViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | // Uncomment the following line to preserve selection between presentations. 26 | // self.clearsSelectionOnViewWillAppear = NO; 27 | 28 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 29 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 30 | } 31 | 32 | - (void)didReceiveMemoryWarning { 33 | [super didReceiveMemoryWarning]; 34 | // Dispose of any resources that can be recreated. 35 | } 36 | 37 | - (void)viewWillAppear:(BOOL)animated { 38 | [super viewWillAppear:animated]; 39 | [self prepareFetchedResultsController]; 40 | 41 | self.title = self.presentedClub.clubName; 42 | } 43 | 44 | 45 | #pragma mark - NSFetchedResultsController 46 | 47 | - (void)prepareFetchedResultsController { 48 | CoreDataManager *manager = [CoreDataManager sharedInstance]; 49 | 50 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"club.clubId == %@", self.presentedClub.clubId]; 51 | NSArray *sortingKeys = @[@"position", @"lastName", @"firstName"]; 52 | 53 | self.fetchedResultsController = [manager fetchedResultsControllerWithEntityName:@"Player" 54 | predicate:predicate 55 | sortingKeys:sortingKeys 56 | sectionNameKey:nil 57 | ascending:YES 58 | delegate:self]; 59 | self.cellConfigurer = self; 60 | NSError *error = nil; 61 | [self.fetchedResultsController performFetch:&error]; 62 | if (error) { 63 | DDLogError(@"Fetch Erorr: %@", error); 64 | } 65 | 66 | } 67 | 68 | #pragma mark - Navigation 69 | 70 | - (void)prepareForSegue:(UIStoryboardSegue *)segue 71 | sender:(id)sender 72 | { 73 | if ([[segue identifier] isEqualToString:kSquadPresentPlayerSegue]) { 74 | PlayerProfileViewController *playerViewController = (PlayerProfileViewController *)segue.destinationViewController; 75 | Player *player = [self.fetchedResultsController objectAtIndexPath:self.tableView.indexPathForSelectedRow]; 76 | [playerViewController setPresentedPlayer:player]; 77 | } 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataClubManager/CoreDataClubManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataClubManager.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "CoreDataEntityManager.h" 10 | #import "Club.h" 11 | 12 | @interface CoreDataClubManager : CoreDataEntityManager 13 | 14 | /** 15 | * Method that creates a Club with a given name and stadium name. 16 | * 17 | * @param clubName The club name. 18 | * @param clubId The club id. 19 | * 20 | * @return Club instance. 21 | */ 22 | - (Club *)createClubWithName:(NSString *)clubName 23 | clubId:(NSNumber *)clubId; 24 | 25 | /** 26 | * Deletes a club from its managed object context. 27 | * 28 | * @param club Club object. 29 | */ 30 | - (void)deleteClub:(Club *)club; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataClubManager/CoreDataClubManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataClubManager.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "CoreDataClubManager.h" 10 | #import "CoreDataManager.h" 11 | 12 | @implementation CoreDataClubManager 13 | 14 | - (Club *)createClubWithName:(NSString *)clubName 15 | clubId:(NSNumber *)clubId 16 | { 17 | // Get the club class name 18 | NSString *clubClassName = NSStringFromClass([Club class]); 19 | // Get the main context 20 | NSManagedObjectContext *context = [[CoreDataManager sharedInstance] mainManagedObjectContext]; 21 | // Create the entity 22 | Club *clubObject = (Club *)[self createNSManagedObjectWithEntityName:clubClassName 23 | onContext:context]; 24 | // Set it's properties 25 | clubObject.clubName = clubName; 26 | clubObject.clubId = clubId; 27 | 28 | return clubObject; 29 | } 30 | 31 | - (void)deleteClub:(Club *)club { 32 | [self deleteObject:club]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataEntityManager/CoreDataEntityManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataEntityManager.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | @import CoreData; 11 | 12 | /** 13 | * Base class for CoreData manager classes. 14 | */ 15 | @interface CoreDataEntityManager : NSObject 16 | 17 | /** 18 | * The NSManagedObjectContext on which the CoreDataEntityManager instace will operate on. 19 | */ 20 | @property (nonatomic, strong, readonly) NSManagedObjectContext *managedObjectContext; 21 | 22 | /** 23 | * Designated initializer. 24 | * 25 | * @param context Instantiates a CoreDataEntityManager with a given context. 26 | * 27 | * @return CoreDataEntityManager instance. 28 | */ 29 | - (instancetype)initWithContext:(NSManagedObjectContext *)context; 30 | 31 | /** 32 | * Creates a NSManagedObject with a given entity name on the passed NSManagedObjectContext. 33 | * 34 | * @param entityName NSString representing a valid entity name. 35 | * @param context The NSManagedObjectContext on which the object will be created. 36 | * 37 | * @return NSManagedObject instance or nil. 38 | */ 39 | - (NSManagedObject *)createNSManagedObjectWithEntityName:(NSString *)entityName 40 | onContext:(NSManagedObjectContext *)context; 41 | 42 | /** 43 | * Deletes an object from its managed object context. 44 | * 45 | * @param object The NSManagedObject instance to be deleted; 46 | */ 47 | - (void)deleteObject:(NSManagedObject *)object; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataEntityManager/CoreDataEntityManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataEntityManager.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "CoreDataEntityManager.h" 10 | 11 | @implementation CoreDataEntityManager 12 | 13 | - (instancetype)initWithContext:(NSManagedObjectContext *)context { 14 | 15 | NSAssert((context != nil && [context isKindOfClass:[NSManagedObjectContext class]]), 16 | @"The NSManagedObjectContext must not be nil or of any other type."); 17 | 18 | if (self = [super init]) { 19 | // Set the managed object context 20 | _managedObjectContext = context; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | - (NSManagedObject *)createNSManagedObjectWithEntityName:(NSString *)entityName 27 | onContext:(NSManagedObjectContext *)context 28 | { 29 | return [NSEntityDescription insertNewObjectForEntityForName:entityName 30 | inManagedObjectContext:context]; 31 | } 32 | 33 | - (void)deleteObject:(NSManagedObject *)object { 34 | NSManagedObjectContext *context = object.managedObjectContext; 35 | [context deleteObject:object]; 36 | object = nil; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataManager/CoreDataManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataManager.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/07/14. 6 | // Copyright (c) 2014 Endava. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | /** 13 | * Singleton class that manages the CoreData stack. 14 | */ 15 | @interface CoreDataManager : NSObject 16 | 17 | /** 18 | * The main queue priority NSManagedObjectContext instance. 19 | */ 20 | @property (nonatomic, strong, readonly) NSManagedObjectContext *mainManagedObjectContext; 21 | 22 | /** 23 | * Returns a pointer to the singleton class instance. 24 | * 25 | * @return CoreDataManager instance. 26 | */ 27 | + (instancetype)sharedInstance; 28 | 29 | /** 30 | * Saves the main queue priority context. 31 | */ 32 | - (void)saveContext; 33 | 34 | /** 35 | * Performs a fetch request on the main queue managed object context with a set of 36 | * required parameters. 37 | * 38 | * @param entityName NSString instance representing a CoreData entity name. 39 | * @param predicate NSPredicate instance describing the fetch rule. 40 | * @param sortingKeys Array containing NSString instances representing the entity 41 | * property by which the sorting will be done. 42 | * @param ascending YES - Ascending. 43 | * 44 | * @return NSArray of NSManagedObject instances of that entityName type. 45 | */ 46 | - (NSArray *)fetchObjectsWithEntityName:(NSString *)entityName 47 | predicate:(NSPredicate *)predicate 48 | sortingKeys:(NSArray *)sortingKeys 49 | ascending:(BOOL)ascending; 50 | 51 | 52 | /** 53 | * Creates a NSFetchedResultsController with a set of parameters. 54 | * 55 | * @param entityName The entity name to fetch. 56 | * @param predicate The NSPredicate instance for the search. 57 | * @param sortingKeys The fetch sorting keys. 58 | * @param sectionNameKey The section name key. 59 | * @param ascending YES - ascending. 60 | * @param delegate The delegate for the search. 61 | * 62 | * @return NSFetchedResultsController instance. 63 | */ 64 | - (NSFetchedResultsController *)fetchedResultsControllerWithEntityName:(NSString *)entityName 65 | predicate:(NSPredicate *)predicate 66 | sortingKeys:(NSArray *)sortingKeys 67 | sectionNameKey:(NSString *)sectionKey 68 | ascending:(BOOL)ascending 69 | delegate:(id)delegate; 70 | 71 | /** 72 | * Returns a newly instantiated NSManagedObjectContext with a private queue priority. 73 | * 74 | * @return NSManagedObjectContext instance. 75 | */ 76 | @property (nonatomic, strong, readonly) NSManagedObjectContext *backgroundQueueManagedObjectContext; 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataManager/CoreDataManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataManager.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/07/14. 6 | // Copyright (c) 2014 Endava. All rights reserved. 7 | // 8 | 9 | #import "CoreDataManager.h" 10 | 11 | @interface CoreDataManager () 12 | 13 | @property (nonatomic, strong, readonly) NSManagedObjectModel *managedObjectModel; 14 | @property (nonatomic, strong, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator; 15 | 16 | - (NSURL *)applicationDocumentsDirectory; 17 | 18 | @end 19 | 20 | @implementation CoreDataManager 21 | 22 | @synthesize mainManagedObjectContext = _mainManagedObjectContext; 23 | @synthesize managedObjectModel = _managedObjectModel; 24 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 25 | 26 | #pragma mark - Initialization 27 | 28 | + (instancetype)sharedInstance { 29 | static dispatch_once_t onceToken; 30 | __strong static id _sharedObject = nil; 31 | dispatch_once(&onceToken, ^{ 32 | _sharedObject = [[self alloc] init]; 33 | }); 34 | 35 | return _sharedObject; 36 | } 37 | 38 | 39 | #pragma mark - CoreData Operations 40 | - (void)saveContext { 41 | NSError *error = nil; 42 | NSManagedObjectContext *managedObjectContext = self.mainManagedObjectContext; 43 | if (managedObjectContext != nil) { 44 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 45 | 46 | DDLogWarn(@"Unresolved error main context %@, %@", error, [error userInfo]); 47 | 48 | NSArray * conflictListArray = (NSArray*)[[error userInfo] objectForKey:@"conflictList"]; 49 | DDLogWarn(@"conflict array: %@",conflictListArray); 50 | NSError * conflictFixError = nil; 51 | 52 | if ([conflictListArray count] > 0) { 53 | 54 | NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSOverwriteMergePolicyType]; 55 | 56 | if (![mergePolicy resolveConflicts:conflictListArray error:&conflictFixError]) { 57 | DDLogError(@"Unresolved conflict error %@, %@", conflictFixError, [conflictFixError userInfo]); 58 | DDLogError(@"abort"); 59 | abort(); 60 | } 61 | } 62 | } 63 | } 64 | if (error) { 65 | DDLogError(@"Unresolved conflict error %@", [error userInfo]); 66 | } 67 | } 68 | 69 | - (NSArray *)fetchObjectsWithEntityName:(NSString *)entityName 70 | predicate:(NSPredicate *)predicate 71 | sortingKeys:(NSArray *)sortingKeys 72 | ascending:(BOOL)ascending 73 | { 74 | 75 | // Create a fetch request with a specific entity 76 | NSFetchRequest *fetchRequest = [self fetchRequestWithEntityName:entityName 77 | predicate:predicate 78 | sortingKeys:sortingKeys 79 | ascending:ascending]; 80 | NSError *error = nil; 81 | NSArray *fetchedObjects = [self.mainManagedObjectContext executeFetchRequest:fetchRequest error:&error]; 82 | if (error) { 83 | DDLogError(@"Fetch Error: %@", [error description]); 84 | } 85 | 86 | return fetchedObjects; 87 | } 88 | 89 | - (NSFetchedResultsController *)fetchedResultsControllerWithEntityName:(NSString *)entityName 90 | predicate:(NSPredicate *)predicate 91 | sortingKeys:(NSArray *)sortingKeys 92 | sectionNameKey:(NSString *)sectionKey 93 | ascending:(BOOL)ascending 94 | delegate:(id)delegate 95 | { 96 | 97 | NSFetchRequest *fetchRequest = [self fetchRequestWithEntityName:entityName 98 | predicate:predicate 99 | sortingKeys:sortingKeys 100 | ascending:ascending]; 101 | 102 | NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 103 | managedObjectContext:self.mainManagedObjectContext 104 | sectionNameKeyPath:sectionKey 105 | cacheName:nil]; 106 | fetchedResultsController.delegate = delegate; 107 | 108 | return fetchedResultsController; 109 | } 110 | 111 | /** 112 | * Creates a NSFetchRequest with a given entity name, predicate and sorting key. 113 | * 114 | * @param entityName The entity name of the fetched objects. 115 | * @param predicate The fetch predicate. 116 | * @param sortingKey The sorting key. 117 | * @param ascending YES - Ascending. 118 | * 119 | * @return NSFetchRequest instance. 120 | */ 121 | - (NSFetchRequest *)fetchRequestWithEntityName:(NSString *)entityName 122 | predicate:(NSPredicate *)predicate 123 | sortingKeys:(NSArray *)sortingKeys 124 | ascending:(BOOL)ascending 125 | { 126 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName]; 127 | fetchRequest.predicate = predicate; 128 | NSMutableArray *sortingDescriptors = [NSMutableArray arrayWithCapacity:[sortingKeys count]]; 129 | // Create the sort descriptors 130 | for (NSString *sortingKey in sortingKeys) { 131 | NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:sortingKey ascending:ascending]; 132 | [sortingDescriptors addObject:sortDescriptor]; 133 | } 134 | 135 | fetchRequest.sortDescriptors = sortingDescriptors; 136 | fetchRequest.returnsObjectsAsFaults = NO; 137 | 138 | return fetchRequest; 139 | } 140 | 141 | 142 | #pragma mark - CoreData stack 143 | 144 | - (NSManagedObjectContext *)mainManagedObjectContext { 145 | if (_mainManagedObjectContext != nil) { 146 | return _mainManagedObjectContext; 147 | } 148 | 149 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 150 | if (coordinator != nil) { 151 | // Make sure the main object context executes on the main queue 152 | _mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 153 | [_mainManagedObjectContext setPersistentStoreCoordinator:coordinator]; 154 | } 155 | return _mainManagedObjectContext; 156 | } 157 | 158 | - (NSManagedObjectContext*)backgroundQueueManagedObjectContext { 159 | 160 | // Make sure the background context executes on a private queue 161 | NSManagedObjectContext *backgroundQueueManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 162 | // Set the background context's parent to be the main context 163 | [backgroundQueueManagedObjectContext setParentContext:self.mainManagedObjectContext]; 164 | [backgroundQueueManagedObjectContext setUndoManager:nil]; 165 | 166 | return backgroundQueueManagedObjectContext; 167 | } 168 | 169 | - (NSManagedObjectModel *)managedObjectModel { 170 | if (_managedObjectModel != nil) { 171 | return _managedObjectModel; 172 | } 173 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]; 174 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 175 | return _managedObjectModel; 176 | } 177 | 178 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 179 | if (_persistentStoreCoordinator != nil) { 180 | return _persistentStoreCoordinator; 181 | } 182 | 183 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"JenkinsCI.sqlite"]; 184 | 185 | NSError *error = nil; 186 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 187 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{NSPersistentStoreFileProtectionKey : NSFileProtectionComplete} error:&error]) { 188 | 189 | DDLogError(@"Unresolved error %@, %@", error, [error userInfo]); 190 | abort(); 191 | } 192 | 193 | return _persistentStoreCoordinator; 194 | } 195 | 196 | #pragma mark - Application's Documents directory 197 | 198 | // Returns the URL to the application's Documents directory. 199 | - (NSURL *)applicationDocumentsDirectory { 200 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 201 | } 202 | 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataPlayerManger/CoreDataPlayerManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataPlayerManager.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "CoreDataEntityManager.h" 10 | #import "Player.h" 11 | 12 | @interface CoreDataPlayerManager : CoreDataEntityManager 13 | 14 | /** 15 | * Creates a Player entity object with a first name and a last name. 16 | * 17 | * @param firstName Player's first name. 18 | * @param lastName Player's last name. 19 | * 20 | * @return Player instance. 21 | */ 22 | - (Player *)createPlayerWithFirstName:(NSString *)firstName 23 | lastName:(NSString *)lastName; 24 | 25 | /** 26 | * Deletes a Player entity from its managed object context. 27 | * 28 | * @param player Player instance. 29 | */ 30 | - (void)deletePlayer:(Player *)player; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/CoreDataPlayerManger/CoreDataPlayerManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataPlayerManager.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "CoreDataPlayerManager.h" 10 | #import "CoreDataManager.h" 11 | 12 | @implementation CoreDataPlayerManager 13 | 14 | - (Player *)createPlayerWithFirstName:(NSString *)firstName 15 | lastName:(NSString *)lastName 16 | { 17 | // Get the player class name 18 | NSString *playerClassName = NSStringFromClass([Player class]); 19 | // Get the main context 20 | NSManagedObjectContext *context = [[CoreDataManager sharedInstance] mainManagedObjectContext]; 21 | // Create the entity 22 | Player *playerObject = (Player *)[self createNSManagedObjectWithEntityName:playerClassName 23 | onContext:context]; 24 | // Set it's properties 25 | playerObject.firstName = firstName; 26 | playerObject.lastName = lastName; 27 | 28 | return playerObject; 29 | } 30 | 31 | - (void)deletePlayer:(Player *)player { 32 | [self deleteObject:player]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/DataImporter/DataImporter.h: -------------------------------------------------------------------------------- 1 | // 2 | // DataImporter.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DataImporter : NSObject 12 | 13 | @property (nonatomic) BOOL didImportData; 14 | 15 | /** 16 | * Method that will import the players and club infos from an NSDictionary. 17 | * 18 | */ 19 | - (void)importData; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Managers/DataImporter/DataImporter.m: -------------------------------------------------------------------------------- 1 | // 2 | // DataImporter.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "DataImporter.h" 10 | #import "CoreDataManager.h" 11 | #import "CoreDataClubManager.h" 12 | #import "CoreDataPlayerManager.h" 13 | 14 | // NSUserDefaults import key 15 | static NSString * const kDidImportDataKey = @"kDidImportData"; 16 | 17 | // JSON import keys 18 | // Club 19 | static NSString * const kClubsKey = @"clubs"; 20 | static NSString * const kClubId = @"clubId"; 21 | static NSString * const kClubName = @"clubName"; 22 | static NSString * const kClubStadiumName = @"stadiumName"; 23 | // Player 24 | static NSString * const kPlayersKey = @"players"; 25 | static NSString * const kPlayerId = @"playerId"; 26 | static NSString * const kPlayerFirstName = @"firstName"; 27 | static NSString * const kPlayerLastName = @"lastName"; 28 | static NSString * const kPlayerPosition = @"position"; 29 | static NSString * const kPlayerShirtNumber = @"shirtNumber"; 30 | static NSString * const kPlayerClub = @"club"; 31 | 32 | // JSON 33 | static NSString * const kJSonFileName = @"db"; 34 | static NSString * const kJSonFileType = @"json"; 35 | 36 | @interface DataImporter () 37 | 38 | @property (nonatomic, strong) NSManagedObjectContext *importerContext; 39 | @property (nonatomic, strong) NSMutableDictionary *clubsById; 40 | 41 | @end 42 | 43 | 44 | @implementation DataImporter 45 | 46 | 47 | #pragma mark - Init 48 | 49 | - (instancetype)init { 50 | if (self = [super init]) { 51 | // Create a background context and asign it 52 | _importerContext = [[CoreDataManager sharedInstance] backgroundQueueManagedObjectContext]; 53 | // Prepare a dictionary for clubs - clubId pairing 54 | _clubsById = [[NSMutableDictionary alloc] init]; 55 | } 56 | 57 | return self; 58 | } 59 | 60 | #pragma mark - Importing data 61 | 62 | - (BOOL)didImportData { 63 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 64 | return [userDefaults boolForKey:kDidImportDataKey]; 65 | } 66 | 67 | - (void)setDidImportData:(BOOL)didImportData { 68 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 69 | [userDefaults setBool:didImportData forKey:kDidImportDataKey]; 70 | [userDefaults synchronize]; 71 | } 72 | 73 | - (void)importData { 74 | NSDictionary *dictionary = [self jsonFileData]; 75 | [self importDataFromDictionary:dictionary]; 76 | } 77 | 78 | - (void)importDataFromDictionary:(NSDictionary *)dictionary { 79 | 80 | __weak typeof(self)weakSelf = self; 81 | 82 | [self.importerContext performBlockAndWait:^{ 83 | // Create the clubs 84 | NSArray *clubs = [dictionary objectForKey:kClubsKey]; 85 | [weakSelf createClubsUsingArray:clubs]; 86 | 87 | // Create the players 88 | NSArray *players = [dictionary objectForKey:kPlayersKey]; 89 | [weakSelf createPlayersUsingArray:players]; 90 | 91 | __block NSError *error = nil; 92 | __block BOOL saved = [weakSelf.importerContext save:&error]; 93 | if (saved && weakSelf.importerContext.parentContext) { 94 | [weakSelf.importerContext.parentContext performBlockAndWait:^{ 95 | saved = [weakSelf.importerContext.parentContext save:&error]; 96 | }]; 97 | } 98 | 99 | if (!error) { 100 | // Mark data as imported 101 | [weakSelf setDidImportData:YES]; 102 | } else { 103 | DDLogError(@"CoreData error: %@", error); 104 | } 105 | 106 | }]; 107 | } 108 | 109 | #pragma mark - Club creation 110 | 111 | - (void)createClubsUsingArray:(NSArray *)clubs { 112 | NSAssert(([clubs count] > 0), @"The clubs array should not be empty."); 113 | // Create a CoreDataClubManager 114 | CoreDataClubManager *clubManager = [[CoreDataClubManager alloc] initWithContext:self.importerContext]; 115 | // Create the clubs 116 | for (NSDictionary *clubInfo in clubs) { 117 | [self createClubWithDictionary:clubInfo 118 | usingClubManager:clubManager]; 119 | } 120 | } 121 | 122 | - (void)createClubWithDictionary:(NSDictionary *)dictionary 123 | usingClubManager:(CoreDataClubManager *)clubManager 124 | { 125 | // Get the club data 126 | NSNumber *clubId = [dictionary objectForKey:kClubId]; 127 | NSString *clubName = [dictionary objectForKey:kClubName]; 128 | NSString *stadiumName = [dictionary objectForKey:kClubStadiumName]; 129 | 130 | // Create the club 131 | Club * club = [clubManager createClubWithName:clubName 132 | clubId:clubId]; 133 | club.stadiumName = stadiumName; 134 | // Create a club - club id pairing for easy player creation 135 | [self.clubsById setObject:club 136 | forKey:club.clubId]; 137 | } 138 | 139 | #pragma mark - Player creation 140 | 141 | - (void)createPlayersUsingArray:(NSArray *)players { 142 | NSAssert(([players count] > 0), @"The players array should not be empty."); 143 | // Create a CoreDataPlayerManager 144 | CoreDataPlayerManager *playerManager = [[CoreDataPlayerManager alloc] initWithContext:self.importerContext]; 145 | // Create the players 146 | for (NSDictionary *playerInfo in players) { 147 | [self createPlayerWithDictionary:playerInfo 148 | usingPlayerManager:playerManager]; 149 | } 150 | 151 | } 152 | 153 | - (void)createPlayerWithDictionary:(NSDictionary *)dictionary 154 | usingPlayerManager:(CoreDataPlayerManager *)playerManager 155 | { 156 | // Get player info 157 | NSString *firstName = [dictionary objectForKey:kPlayerFirstName]; 158 | NSString *lastName = [dictionary objectForKey:kPlayerLastName]; 159 | NSNumber *clubId = [dictionary objectForKey:kPlayerClub]; 160 | // Create player object 161 | Player *player = [playerManager createPlayerWithFirstName:firstName 162 | lastName:lastName]; 163 | player.playerId = [dictionary objectForKey:kPlayerId]; 164 | player.position = [dictionary objectForKey:kPlayerPosition]; 165 | player.shirtNumber = [dictionary objectForKey:kPlayerShirtNumber]; 166 | 167 | Club *club = [self.clubsById objectForKey:clubId]; 168 | player.club = club; 169 | 170 | } 171 | 172 | 173 | #pragma mark - JSON file 174 | 175 | - (NSDictionary *)jsonFileData { 176 | NSString *filePath = [[NSBundle mainBundle] pathForResource:kJSonFileName 177 | ofType:kJSonFileType]; 178 | NSString *myJSON = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL]; 179 | NSError *error = nil; 180 | NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:[myJSON dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error]; 181 | return jsonData; 182 | } 183 | 184 | @end 185 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Model/Club/Club.h: -------------------------------------------------------------------------------- 1 | // 2 | // Club.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class Player; 13 | 14 | @interface Club : NSManagedObject 15 | 16 | @property (nonatomic, retain) NSString * clubName; 17 | @property (nonatomic, retain) NSString * stadiumName; 18 | @property (nonatomic, retain) NSNumber * clubId; 19 | @property (nonatomic, retain) NSSet *squad; 20 | @end 21 | 22 | @interface Club (CoreDataGeneratedAccessors) 23 | 24 | - (void)addSquadObject:(Player *)value; 25 | - (void)removeSquadObject:(Player *)value; 26 | - (void)addSquad:(NSSet *)values; 27 | - (void)removeSquad:(NSSet *)values; 28 | 29 | @end 30 | 31 | @interface Club (Additions) 32 | 33 | - (UIImage *)logoImage; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Model/Club/Club.m: -------------------------------------------------------------------------------- 1 | // 2 | // Club.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "Club.h" 10 | #import "Player.h" 11 | #import 12 | 13 | @implementation Club 14 | 15 | @dynamic clubName; 16 | @dynamic stadiumName; 17 | @dynamic clubId; 18 | @dynamic squad; 19 | 20 | @end 21 | 22 | @implementation Club (Additions) 23 | 24 | - (UIImage *)logoImage { 25 | NSString *strippedString = [self.clubName stringByReplacingOccurrencesOfString:@" " withString:@"-"]; 26 | NSString *imageName = [NSString stringWithFormat:@"%@-logo", strippedString]; 27 | return [UIImage imageNamed:imageName]; 28 | } 29 | 30 | @end -------------------------------------------------------------------------------- /JenkinsCI/Classes/Model/Player/Player.h: -------------------------------------------------------------------------------- 1 | // 2 | // Player.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class Club; 13 | 14 | @interface Player : NSManagedObject 15 | 16 | @property (nonatomic, retain) NSString * firstName; 17 | @property (nonatomic, retain) NSString * lastName; 18 | @property (nonatomic, retain) NSString * position; 19 | @property (nonatomic, retain) NSNumber * playerId; 20 | @property (nonatomic, retain) NSNumber * shirtNumber; 21 | @property (nonatomic, retain) Club *club; 22 | 23 | @end 24 | 25 | @interface Player (Additions) 26 | 27 | - (NSString *)playerFullName; 28 | - (UIImage *)playerImage; 29 | 30 | @end -------------------------------------------------------------------------------- /JenkinsCI/Classes/Model/Player/Player.m: -------------------------------------------------------------------------------- 1 | // 2 | // Player.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "Player.h" 10 | #import "Club.h" 11 | #import 12 | 13 | @implementation Player 14 | 15 | @dynamic firstName; 16 | @dynamic lastName; 17 | @dynamic position; 18 | @dynamic playerId; 19 | @dynamic shirtNumber; 20 | @dynamic club; 21 | 22 | @end 23 | 24 | @implementation Player (Additions) 25 | 26 | 27 | - (NSString *)playerFullName { 28 | return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; 29 | } 30 | 31 | - (UIImage *)playerImage { 32 | NSString *strippedName = [[[self playerFullName] lowercaseString] stringByReplacingOccurrencesOfString:@" " withString:@"_"]; 33 | return [UIImage imageNamed:strippedName]; 34 | } 35 | 36 | 37 | @end -------------------------------------------------------------------------------- /JenkinsCI/Classes/Utils/UIImageView+RoundCorners/UIImageView+RoundCorners.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+RoundCorners.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImageView (RoundCorners) 12 | 13 | /** 14 | * Applies a corner radius to a given UIImageView with a border 15 | * with and color. 16 | * 17 | * @param radius Radius value. 18 | * @param border Border width. 19 | * @param color Border color. 20 | */ 21 | - (void)applyCornerRadius:(CGFloat)radius 22 | borderWidth:(CGFloat)border 23 | borderColor:(UIColor *)color; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/Utils/UIImageView+RoundCorners/UIImageView+RoundCorners.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+RoundCorners.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 20/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+RoundCorners.h" 10 | @import QuartzCore; 11 | 12 | @implementation UIImageView (RoundCorners) 13 | 14 | - (void)applyCornerRadius:(CGFloat)radius 15 | borderWidth:(CGFloat)border 16 | borderColor:(UIColor *)color 17 | { 18 | self.layer.cornerRadius = radius; 19 | self.clipsToBounds = YES; 20 | self.layer.borderColor = color.CGColor; 21 | self.layer.borderWidth = border; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/View/ClubTableViewCell/ClubTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ClubTableViewCell.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ClubTableViewCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *clubNameLabel; 14 | @property (weak, nonatomic) IBOutlet UILabel *squadSizeLabel; 15 | @property (weak, nonatomic) IBOutlet UIImageView *clubLogoView; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/View/ClubTableViewCell/ClubTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ClubTableViewCell.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "ClubTableViewCell.h" 10 | 11 | @implementation ClubTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | // Initialization code 15 | } 16 | 17 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 18 | [super setSelected:selected animated:animated]; 19 | 20 | // Configure the view for the selected state 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/View/PlayerTableViewCell/PlayerTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerTableViewCell.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PlayerTableViewCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *playerFullNameLabel; 14 | @property (weak, nonatomic) IBOutlet UILabel *clubNameLabel; 15 | @property (weak, nonatomic) IBOutlet UILabel *playerPositionLabel; 16 | @property (weak, nonatomic) IBOutlet UIImageView *playerImageView; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/View/PlayerTableViewCell/PlayerTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerTableViewCell.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "PlayerTableViewCell.h" 10 | #import "UIImageView+RoundCorners.h" 11 | 12 | @implementation PlayerTableViewCell 13 | 14 | - (void)awakeFromNib { 15 | // Initialization code 16 | 17 | CGFloat width = CGRectGetWidth(self.playerImageView.frame); 18 | [self.playerImageView applyCornerRadius:width/2 19 | borderWidth:1.0 20 | borderColor:[UIColor darkGrayColor]]; 21 | } 22 | 23 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 24 | [super setSelected:selected animated:animated]; 25 | 26 | // Configure the view for the selected state 27 | } 28 | 29 | //- (void)layoutSubviews { 30 | // [super layoutSubviews]; 31 | //} 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/View/SquadProfileTableViewCell/SquadProfileTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SquadProfileTableViewCell.h 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SquadProfileTableViewCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *playerFullNameLabel; 14 | @property (weak, nonatomic) IBOutlet UILabel *playerPositionLabel; 15 | @property (weak, nonatomic) IBOutlet UILabel *playerNumberLabel; 16 | @property (weak, nonatomic) IBOutlet UIImageView *playerPictureView; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /JenkinsCI/Classes/View/SquadProfileTableViewCell/SquadProfileTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SquadProfileTableViewCell.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 17/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #import "SquadProfileTableViewCell.h" 10 | #import "UIImageView+RoundCorners.h" 11 | 12 | @implementation SquadProfileTableViewCell 13 | 14 | - (void)awakeFromNib { 15 | // Initialization code 16 | CGFloat width = CGRectGetWidth(self.playerPictureView.frame); 17 | [self.playerPictureView applyCornerRadius:width/2 18 | borderWidth:1.0 19 | borderColor:[UIColor darkGrayColor]]; 20 | } 21 | 22 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 23 | [super setSelected:selected animated:animated]; 24 | 25 | // Configure the view for the selected state 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /JenkinsCI/CoreData/Model.xcdatamodeld/Model.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /JenkinsCI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.endava.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 0.1 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 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /JenkinsCI/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. All rights reserved. 7 | // 8 | 9 | #ifndef JenkinsCI_PrefixHeader_pch 10 | #define JenkinsCI_PrefixHeader_pch 11 | 12 | // Include any system framework and library headers here that should be included in all compilation units. 13 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 14 | #import 15 | 16 | 17 | // CocoaLumberjack log levels. 18 | #ifdef DEBUG 19 | static const int ddLogLevel = LOG_LEVEL_INFO; 20 | #else 21 | static const int ddLogLevel = LOG_LEVEL_WARN; 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /JenkinsCI/Resources/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-Small.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-Small@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Arsenal-FC-logo.imageset/Arsenal-FC-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/club-logos/Arsenal-FC-logo.imageset/Arsenal-FC-icon.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Arsenal-FC-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Arsenal-FC-icon.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Chelsea-FC-logo.imageset/Chelsea-FC-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/club-logos/Chelsea-FC-logo.imageset/Chelsea-FC-icon.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Chelsea-FC-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Chelsea-FC-icon.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Everton-FC-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Everton-FC-icon.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Everton-FC-logo.imageset/Everton-FC-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/club-logos/Everton-FC-logo.imageset/Everton-FC-icon.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Liverpool-FC-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Liverpool-FC-icon.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Liverpool-FC-logo.imageset/Liverpool-FC-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/club-logos/Liverpool-FC-logo.imageset/Liverpool-FC-icon.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Manchester-United-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Manchester-United-icon.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/club-logos/Manchester-United-logo.imageset/Manchester-United-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/club-logos/Manchester-United-logo.imageset/Manchester-United-icon.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/persons.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "persons@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x", 15 | "filename" : "persons@3x.png" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/persons.imageset/persons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/persons.imageset/persons@2x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/persons.imageset/persons@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/persons.imageset/persons@3x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/aaron_ramsey.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "aaron_ramsey.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/aaron_ramsey.imageset/aaron_ramsey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/aaron_ramsey.imageset/aaron_ramsey.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/angel_di_maria.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "angel_di_maria.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/angel_di_maria.imageset/angel_di_maria.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/angel_di_maria.imageset/angel_di_maria.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/daniel_sturridge.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "daniel_sturridge.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/daniel_sturridge.imageset/daniel_sturridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/daniel_sturridge.imageset/daniel_sturridge.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/eden_hazard.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "eden_hazard.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/eden_hazard.imageset/eden_hazard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/eden_hazard.imageset/eden_hazard.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/jordan_henderson.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "jordan_henderson.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/jordan_henderson.imageset/jordan_henderson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/jordan_henderson.imageset/jordan_henderson.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/martin_skrtel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "martin_skrtel.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/martin_skrtel.imageset/martin_skrtel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/martin_skrtel.imageset/martin_skrtel.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/player_placeholder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "player_placeholder.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/player_placeholder.imageset/player_placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/player_placeholder.imageset/player_placeholder.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/ross_barkley.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "ross_barkley.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/ross_barkley.imageset/ross_barkley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/ross_barkley.imageset/ross_barkley.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/steven_gerrard.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "steven_gerrard.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/steven_gerrard.imageset/steven_gerrard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/steven_gerrard.imageset/steven_gerrard.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/wayne_rooney.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "wayne_rooney.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/player-pictures/wayne_rooney.imageset/wayne_rooney.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/player-pictures/wayne_rooney.imageset/wayne_rooney.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/stadium.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "stadium@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x", 15 | "filename" : "stadium@3x.png" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/stadium.imageset/stadium@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/stadium.imageset/stadium@2x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/Images.xcassets/stadium.imageset/stadium@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/JenkinsCI/Resources/Images.xcassets/stadium.imageset/stadium@3x.png -------------------------------------------------------------------------------- /JenkinsCI/Resources/db.json: -------------------------------------------------------------------------------- 1 | { "clubs" : [ { "clubId" : 101, 2 | "clubName" : "Liverpool FC", 3 | "stadiumName" : "Anfield" 4 | }, 5 | { "clubId" : 102, 6 | "clubName" : "Manchester United", 7 | "stadiumName" : "Old Trafford" 8 | }, 9 | { "clubId" : 103, 10 | "clubName" : "Arsenal FC", 11 | "stadiumName" : "Emirates Stadium" 12 | }, 13 | { "clubId" : 104, 14 | "clubName" : "Chelsea FC", 15 | "stadiumName" : "Stamford Bridge" 16 | }, 17 | { "clubId" : 105, 18 | "clubName" : "Everton FC", 19 | "stadiumName" : "Stamford Bridge" 20 | } 21 | ], 22 | "players" : [ { "club" : 101, 23 | "firstName" : "Steven", 24 | "lastName" : "Gerrard", 25 | "playerId" : 100001, 26 | "position" : "Midfielder", 27 | "shirtNumber" : 8 28 | }, 29 | { "club" : 101, 30 | "firstName" : "Jordan", 31 | "lastName" : "Henderson", 32 | "playerId" : 100002, 33 | "position" : "Midfielder", 34 | "shirtNumber" : 14 35 | }, 36 | { "club" : 101, 37 | "firstName" : "Daniel", 38 | "lastName" : "Sturridge", 39 | "playerId" : 100003, 40 | "position" : "Striker", 41 | "shirtNumber" : 15 42 | }, 43 | { "club" : 101, 44 | "firstName" : "Martin", 45 | "lastName" : "Skrtel", 46 | "playerId" : 100004, 47 | "position" : "Defender", 48 | "shirtNumber" : 37 49 | }, 50 | { "club" : 105, 51 | "firstName" : "Ross", 52 | "lastName" : "Barkley", 53 | "playerId" : 100005, 54 | "position" : "Midfielder", 55 | "shirtNumber" : 20 56 | }, 57 | { "club" : 102, 58 | "firstName" : "Angel", 59 | "lastName" : "Di Maria", 60 | "playerId" : 100006, 61 | "position" : "Midfielder", 62 | "shirtNumber" : 7 63 | }, 64 | { "club" : 102, 65 | "firstName" : "Wayne", 66 | "lastName" : "Rooney", 67 | "playerId" : 100007, 68 | "position" : "Striker", 69 | "shirtNumber" : 10 70 | }, 71 | { "club" : 103, 72 | "firstName" : "Aaron", 73 | "lastName" : "Ramsey", 74 | "playerId" : 100007, 75 | "position" : "Midfielder", 76 | "shirtNumber" : 16 77 | }, 78 | { "club" : 104, 79 | "firstName" : "Eden", 80 | "lastName" : "Hazard", 81 | "playerId" : 100008, 82 | "position" : "Midfielder", 83 | "shirtNumber" : 10 84 | } 85 | ] 86 | } -------------------------------------------------------------------------------- /JenkinsCI/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JenkinsCI 4 | // 5 | // Created by Ciprian Redinciuc on 14/10/14. 6 | // Copyright (c) 2014 Ciprian Redinciuc. 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 | -------------------------------------------------------------------------------- /JenkinsCITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.endava.$(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 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '7.0' 3 | 4 | 5 | pod 'CocoaLumberjack' 6 | pod 'CrashlyticsFramework' -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - CocoaLumberjack (2.0.0-beta2): 3 | - CocoaLumberjack/CLI 4 | - CocoaLumberjack/Core 5 | - CocoaLumberjack/Extensions 6 | - CocoaLumberjack/CLI (2.0.0-beta2): 7 | - CocoaLumberjack/Core 8 | - CocoaLumberjack/Core (2.0.0-beta2) 9 | - CocoaLumberjack/Extensions (2.0.0-beta2): 10 | - CocoaLumberjack/Core 11 | - CrashlyticsFramework (2.2.5) 12 | 13 | DEPENDENCIES: 14 | - CocoaLumberjack 15 | - CrashlyticsFramework 16 | 17 | SPEC CHECKSUMS: 18 | CocoaLumberjack: 956d3fb98fed498a13d56499f262c975ef431c98 19 | CrashlyticsFramework: 82d124501d97d3b5d49bd6209dea21c6b7f0a33d 20 | 21 | COCOAPODS: 0.34.4 22 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/CLI/CLIColor.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import 17 | 18 | /** 19 | * This class represents an NSColor replacement for CLI projects that don't link with AppKit 20 | **/ 21 | 22 | @interface CLIColor : NSObject 23 | 24 | + (CLIColor *)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; 25 | - (void)getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/CLI/CLIColor.m: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "CLIColor.h" 17 | 18 | @interface CLIColor () { 19 | CGFloat _red, _green, _blue, _alpha; 20 | } 21 | 22 | @end 23 | 24 | 25 | @implementation CLIColor 26 | 27 | + (CLIColor *)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha { 28 | CLIColor *color = [CLIColor new]; 29 | 30 | color->_red = red; 31 | color->_green = green; 32 | color->_blue = blue; 33 | color->_alpha = alpha; 34 | return color; 35 | } 36 | 37 | - (void)getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha { 38 | if (red) { 39 | *red = _red; 40 | } 41 | 42 | if (green) { 43 | *green = _green; 44 | } 45 | 46 | if (blue) { 47 | *blue = _blue; 48 | } 49 | 50 | if (alpha) { 51 | *alpha = _alpha; 52 | } 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/CocoaLumberjack.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | /** 17 | * Welcome to CocoaLumberjack! 18 | * 19 | * The project page has a wealth of documentation if you have any questions. 20 | * https://github.com/CocoaLumberjack/CocoaLumberjack 21 | * 22 | * If you're new to the project you may wish to read "Getting Started" at: 23 | * Documentation/GettingStarted.md 24 | * 25 | * Otherwise, here is a quick refresher. 26 | * There are three steps to using the macros: 27 | * 28 | * Step 1: 29 | * Import the header in your implementation or prefix file: 30 | * 31 | * #import 32 | * 33 | * Step 2: 34 | * Define your logging level in your implementation file: 35 | * 36 | * // Log levels: off, error, warn, info, verbose 37 | * static const int ddLogLevel = LOG_LEVEL_VERBOSE; 38 | * 39 | * Step 2 [3rd party frameworks]: 40 | * 41 | * Define your LOG_LEVEL_DEF to a different variable/function than ddLogLevel: 42 | * 43 | * // #undef LOG_LEVEL_DEF // Undefine first only if needed 44 | * #define LOG_LEVEL_DEF myLibLogLevel 45 | * 46 | * Define your logging level in your implementation file: 47 | * 48 | * // Log levels: off, error, warn, info, verbose 49 | * static const int myLibLogLevel = LOG_LEVEL_VERBOSE; 50 | * 51 | * Step 3: 52 | * Replace your NSLog statements with DDLog statements according to the severity of the message. 53 | * 54 | * NSLog(@"Fatal error, no dohickey found!"); -> DDLogError(@"Fatal error, no dohickey found!"); 55 | * 56 | * DDLog works exactly the same as NSLog. 57 | * This means you can pass it multiple variables just like NSLog. 58 | **/ 59 | 60 | #import "DDLog.h" 61 | #import "DDLogMacros.h" 62 | #import "DDAssertMacros.h" 63 | 64 | // Loggers 65 | #import "DDTTYLogger.h" 66 | #import "DDASLLogger.h" 67 | #import "DDFileLogger.h" 68 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDASLLogCapture.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDASLLogger.h" 17 | 18 | @protocol DDLogger; 19 | 20 | /** 21 | * This class provides the ability to capture the ASL (Apple System Logs) 22 | */ 23 | @interface DDASLLogCapture : NSObject 24 | 25 | + (void)start; 26 | + (void)stop; 27 | 28 | // Default log level: LOG_LEVEL_VERBOSE (i.e. capture all ASL messages). 29 | + (int)captureLogLevel; 30 | + (void)setCaptureLogLevel:(int)LOG_LEVEL_XXX; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDASLLogCapture.m: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDASLLogCapture.h" 17 | #import "DDLog.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | static BOOL _cancel = YES; 25 | static int _captureLogLevel = LOG_LEVEL_VERBOSE; 26 | 27 | @implementation DDASLLogCapture 28 | 29 | + (void)start { 30 | // Ignore subsequent calls 31 | if (!_cancel) { 32 | return; 33 | } 34 | 35 | _cancel = NO; 36 | 37 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 38 | [DDASLLogCapture captureAslLogs]; 39 | }); 40 | } 41 | 42 | + (void)stop { 43 | _cancel = YES; 44 | } 45 | 46 | + (int)captureLogLevel { 47 | return _captureLogLevel; 48 | } 49 | 50 | + (void)setCaptureLogLevel:(int)LOG_LEVEL_XXX { 51 | _captureLogLevel = LOG_LEVEL_XXX; 52 | } 53 | 54 | # pragma mark - Private methods 55 | 56 | + (void)configureAslQuery:(aslmsg)query { 57 | const char param[] = "7"; // ASL_LEVEL_DEBUG, which is everything. We'll rely on regular DDlog log level to filter 58 | 59 | asl_set_query(query, ASL_KEY_LEVEL, param, ASL_QUERY_OP_LESS_EQUAL | ASL_QUERY_OP_NUMERIC); 60 | 61 | #if !TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR 62 | int processId = [[NSProcessInfo processInfo] processIdentifier]; 63 | char pid[16]; 64 | sprintf(pid, "%d", processId); 65 | asl_set_query(query, ASL_KEY_PID, pid, ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_NUMERIC); 66 | #endif 67 | } 68 | 69 | + (void)aslMessageRecieved:(aslmsg)msg { 70 | // NSString * sender = [NSString stringWithCString:asl_get(msg, ASL_KEY_SENDER) encoding:NSUTF8StringEncoding]; 71 | NSString *message = [NSString stringWithCString:asl_get(msg, ASL_KEY_MSG) encoding:NSUTF8StringEncoding]; 72 | NSString *level = [NSString stringWithCString:asl_get(msg, ASL_KEY_LEVEL) encoding:NSUTF8StringEncoding]; 73 | NSString *secondsStr = [NSString stringWithCString:asl_get(msg, ASL_KEY_TIME) encoding:NSUTF8StringEncoding]; 74 | NSString *nanoStr = [NSString stringWithCString:asl_get(msg, ASL_KEY_TIME_NSEC) encoding:NSUTF8StringEncoding]; 75 | 76 | NSTimeInterval seconds = [secondsStr doubleValue]; 77 | NSTimeInterval nanoSeconds = [nanoStr doubleValue]; 78 | NSTimeInterval totalSeconds = seconds + (nanoSeconds / 1e9); 79 | 80 | NSDate *timeStamp = [NSDate dateWithTimeIntervalSince1970:totalSeconds]; 81 | 82 | int flag; 83 | BOOL async; 84 | 85 | switch ([level intValue]) { 86 | // By default all NSLog's with a ASL_LEVEL_WARNING level 87 | case ASL_LEVEL_EMERG : 88 | case ASL_LEVEL_ALERT : 89 | case ASL_LEVEL_CRIT : flag = LOG_FLAG_ERROR; async = LOG_ASYNC_ERROR; break; 90 | case ASL_LEVEL_ERR : flag = LOG_FLAG_WARN; async = LOG_ASYNC_WARN; break; 91 | case ASL_LEVEL_WARNING : flag = LOG_FLAG_INFO; async = LOG_ASYNC_INFO; break; 92 | case ASL_LEVEL_NOTICE : flag = LOG_FLAG_DEBUG; async = LOG_ASYNC_DEBUG; break; 93 | case ASL_LEVEL_INFO : 94 | case ASL_LEVEL_DEBUG : 95 | default : flag = LOG_FLAG_VERBOSE; async = LOG_ASYNC_VERBOSE; break; 96 | } 97 | 98 | if (!(_captureLogLevel & flag)) { 99 | return; 100 | } 101 | 102 | DDLogMessage *logMessage = [[DDLogMessage alloc]initWithLogMsg:message 103 | level:_captureLogLevel 104 | flag:flag 105 | context:0 106 | file:"DDASLLogCapture" 107 | function:0 108 | line:0 109 | tag:nil 110 | options:0 111 | timestamp:timeStamp]; 112 | 113 | [DDLog log:async message:logMessage]; 114 | } 115 | 116 | + (void)captureAslLogs { 117 | @autoreleasepool 118 | { 119 | /* 120 | We use ASL_KEY_MSG_ID to see each message once, but there's no 121 | obvious way to get the "next" ID. To bootstrap the process, we'll 122 | search by timestamp until we've seen a message. 123 | */ 124 | 125 | struct timeval timeval = { 126 | .tv_sec = 0 127 | }; 128 | gettimeofday(&timeval, NULL); 129 | unsigned long long startTime = timeval.tv_sec; 130 | __block unsigned long long lastSeenID = 0; 131 | 132 | /* 133 | syslogd posts kNotifyASLDBUpdate (com.apple.system.logger.message) 134 | through the notify API when it saves messages to the ASL database. 135 | There is some coalescing - currently it is sent at most twice per 136 | second - but there is no documented guarantee about this. In any 137 | case, there may be multiple messages per notification. 138 | 139 | Notify notifications don't carry any payload, so we need to search 140 | for the messages. 141 | */ 142 | int notifyToken = 0; // Can be used to unregister with notify_cancel(). 143 | notify_register_dispatch(kNotifyASLDBUpdate, ¬ifyToken, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(int token) 144 | { 145 | // At least one message has been posted; build a search query. 146 | @autoreleasepool 147 | { 148 | aslmsg query = asl_new(ASL_TYPE_QUERY); 149 | char stringValue[64]; 150 | 151 | if (lastSeenID > 0) { 152 | snprintf(stringValue, sizeof stringValue, "%llu", lastSeenID); 153 | asl_set_query(query, ASL_KEY_MSG_ID, stringValue, ASL_QUERY_OP_GREATER | ASL_QUERY_OP_NUMERIC); 154 | } else { 155 | snprintf(stringValue, sizeof stringValue, "%llu", startTime); 156 | asl_set_query(query, ASL_KEY_TIME, stringValue, ASL_QUERY_OP_GREATER_EQUAL | ASL_QUERY_OP_NUMERIC); 157 | } 158 | 159 | [DDASLLogCapture configureAslQuery:query]; 160 | 161 | // Iterate over new messages. 162 | aslmsg msg; 163 | aslresponse response = asl_search(NULL, query); 164 | #if defined(__IPHONE_8_0) || defined(__MAC_10_10) 165 | 166 | while ((msg = asl_next(response))) 167 | #else 168 | 169 | while ((msg = aslresponse_next(response))) 170 | #endif 171 | { 172 | [DDASLLogCapture aslMessageRecieved:msg]; 173 | 174 | // Keep track of which messages we've seen. 175 | lastSeenID = atoll(asl_get(msg, ASL_KEY_MSG_ID)); 176 | } 177 | #if defined(__IPHONE_8_0) || defined(__MAC_10_10) 178 | asl_release(response); 179 | #else 180 | aslresponse_free(response); 181 | #endif 182 | 183 | if (_cancel) { 184 | notify_cancel(notifyToken); 185 | return; 186 | } 187 | 188 | free(query); 189 | } 190 | }); 191 | } 192 | } 193 | 194 | @end -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDASLLogger.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import 17 | #import "DDLog.h" 18 | 19 | /** 20 | * This class provides a logger for the Apple System Log facility. 21 | * 22 | * As described in the "Getting Started" page, 23 | * the traditional NSLog() function directs it's output to two places: 24 | * 25 | * - Apple System Log 26 | * - StdErr (if stderr is a TTY) so log statements show up in Xcode console 27 | * 28 | * To duplicate NSLog() functionality you can simply add this logger and a tty logger. 29 | * However, if you instead choose to use file logging (for faster performance), 30 | * you may choose to use a file logger and a tty logger. 31 | **/ 32 | 33 | @interface DDASLLogger : DDAbstractLogger 34 | 35 | + (instancetype)sharedInstance; 36 | 37 | // Inherited from DDAbstractLogger 38 | 39 | // - (id )logFormatter; 40 | // - (void)setLogFormatter:(id )formatter; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDASLLogger.m: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDASLLogger.h" 17 | #import 18 | 19 | #if !__has_feature(objc_arc) 20 | #error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 21 | #endif 22 | 23 | static DDASLLogger *sharedInstance; 24 | 25 | @interface DDASLLogger () { 26 | aslclient _client; 27 | } 28 | 29 | @end 30 | 31 | 32 | @implementation DDASLLogger 33 | 34 | + (instancetype)sharedInstance { 35 | static dispatch_once_t DDASLLoggerOnceToken; 36 | 37 | dispatch_once(&DDASLLoggerOnceToken, ^{ 38 | sharedInstance = [[[self class] alloc] init]; 39 | }); 40 | 41 | return sharedInstance; 42 | } 43 | 44 | - (id)init { 45 | if (sharedInstance != nil) { 46 | return nil; 47 | } 48 | 49 | if ((self = [super init])) { 50 | // A default asl client is provided for the main thread, 51 | // but background threads need to create their own client. 52 | 53 | _client = asl_open(NULL, "com.apple.console", 0); 54 | } 55 | 56 | return self; 57 | } 58 | 59 | - (void)logMessage:(DDLogMessage *)logMessage { 60 | // Skip captured log messages. 61 | if (strcmp(logMessage->file, "DDASLLogCapture") == 0) { 62 | return; 63 | } 64 | 65 | NSString *logMsg = logMessage->logMsg; 66 | 67 | if (formatter) { 68 | logMsg = [formatter formatLogMessage:logMessage]; 69 | } 70 | 71 | if (logMsg) { 72 | const char *msg = [logMsg UTF8String]; 73 | 74 | size_t aslLogLevel; 75 | switch (logMessage->logFlag) { 76 | // Note: By default ASL will filter anything above level 5 (Notice). 77 | // So our mappings shouldn't go above that level. 78 | case LOG_FLAG_ERROR : aslLogLevel = ASL_LEVEL_CRIT; break; 79 | case LOG_FLAG_WARN : aslLogLevel = ASL_LEVEL_ERR; break; 80 | case LOG_FLAG_INFO : aslLogLevel = ASL_LEVEL_WARNING; break; // Regular NSLog's level 81 | case LOG_FLAG_DEBUG : 82 | case LOG_FLAG_VERBOSE : 83 | default : aslLogLevel = ASL_LEVEL_NOTICE; break; 84 | } 85 | 86 | static char const *const level_strings[] = { "0", "1", "2", "3", "4", "5", "6", "7" }; 87 | 88 | // NSLog uses the current euid to set the ASL_KEY_READ_UID. 89 | uid_t const readUID = geteuid(); 90 | 91 | char readUIDString[16]; 92 | int l = snprintf(readUIDString, sizeof(readUIDString), "%d", readUID); 93 | 94 | NSAssert(l < sizeof(readUIDString), 95 | @"Formatted euid is too long."); 96 | NSAssert(aslLogLevel < (sizeof(level_strings) / sizeof(level_strings[0])), 97 | @"Unhandled ASL log level."); 98 | 99 | aslmsg m = asl_new(ASL_TYPE_MSG); 100 | if (m != NULL) { 101 | if (asl_set(m, ASL_KEY_LEVEL, level_strings[aslLogLevel]) == 0 && 102 | asl_set(m, ASL_KEY_MSG, msg) == 0 && 103 | asl_set(m, ASL_KEY_READ_UID, readUIDString) == 0) { 104 | asl_send(_client, m); 105 | } 106 | asl_free(m); 107 | } 108 | //TODO handle asl_* failures non-silently? 109 | } 110 | } 111 | 112 | - (NSString *)loggerName { 113 | return @"cocoa.lumberjack.aslLogger"; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDLog.h" 17 | 18 | /** 19 | * This class provides an abstract implementation of a database logger. 20 | * 21 | * That is, it provides the base implementation for a database logger to build atop of. 22 | * All that is needed for a concrete database logger is to extend this class 23 | * and override the methods in the implementation file that are prefixed with "db_". 24 | **/ 25 | 26 | @interface DDAbstractDatabaseLogger : DDAbstractLogger { 27 | 28 | @protected 29 | NSUInteger _saveThreshold; 30 | NSTimeInterval _saveInterval; 31 | NSTimeInterval _maxAge; 32 | NSTimeInterval _deleteInterval; 33 | BOOL _deleteOnEverySave; 34 | 35 | BOOL _saveTimerSuspended; 36 | NSUInteger _unsavedCount; 37 | dispatch_time_t _unsavedTime; 38 | dispatch_source_t _saveTimer; 39 | dispatch_time_t _lastDeleteTime; 40 | dispatch_source_t _deleteTimer; 41 | } 42 | 43 | /** 44 | * Specifies how often to save the data to disk. 45 | * Since saving is an expensive operation (disk io) it is not done after every log statement. 46 | * These properties allow you to configure how/when the logger saves to disk. 47 | * 48 | * A save is done when either (whichever happens first): 49 | * 50 | * - The number of unsaved log entries reaches saveThreshold 51 | * - The amount of time since the oldest unsaved log entry was created reaches saveInterval 52 | * 53 | * You can optionally disable the saveThreshold by setting it to zero. 54 | * If you disable the saveThreshold you are entirely dependent on the saveInterval. 55 | * 56 | * You can optionally disable the saveInterval by setting it to zero (or a negative value). 57 | * If you disable the saveInterval you are entirely dependent on the saveThreshold. 58 | * 59 | * It's not wise to disable both saveThreshold and saveInterval. 60 | * 61 | * The default saveThreshold is 500. 62 | * The default saveInterval is 60 seconds. 63 | **/ 64 | @property (assign, readwrite) NSUInteger saveThreshold; 65 | @property (assign, readwrite) NSTimeInterval saveInterval; 66 | 67 | /** 68 | * It is likely you don't want the log entries to persist forever. 69 | * Doing so would allow the database to grow infinitely large over time. 70 | * 71 | * The maxAge property provides a way to specify how old a log statement can get 72 | * before it should get deleted from the database. 73 | * 74 | * The deleteInterval specifies how often to sweep for old log entries. 75 | * Since deleting is an expensive operation (disk io) is is done on a fixed interval. 76 | * 77 | * An alternative to the deleteInterval is the deleteOnEverySave option. 78 | * This specifies that old log entries should be deleted during every save operation. 79 | * 80 | * You can optionally disable the maxAge by setting it to zero (or a negative value). 81 | * If you disable the maxAge then old log statements are not deleted. 82 | * 83 | * You can optionally disable the deleteInterval by setting it to zero (or a negative value). 84 | * 85 | * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted. 86 | * 87 | * It's not wise to enable both deleteInterval and deleteOnEverySave. 88 | * 89 | * The default maxAge is 7 days. 90 | * The default deleteInterval is 5 minutes. 91 | * The default deleteOnEverySave is NO. 92 | **/ 93 | @property (assign, readwrite) NSTimeInterval maxAge; 94 | @property (assign, readwrite) NSTimeInterval deleteInterval; 95 | @property (assign, readwrite) BOOL deleteOnEverySave; 96 | 97 | /** 98 | * Forces a save of any pending log entries (flushes log entries to disk). 99 | **/ 100 | - (void)savePendingLogEntries; 101 | 102 | /** 103 | * Removes any log entries that are older than maxAge. 104 | **/ 105 | - (void)deleteOldLogEntries; 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDAssertMacros.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDLogMacros.h" 17 | 18 | /** 19 | * NSAsset replacement that will output a log message even when assertions are disabled. 20 | **/ 21 | 22 | #define DDAssert(condition, frmt, ...) \ 23 | if (!(condition)) { \ 24 | NSString *description = [NSString stringWithFormat:frmt, ## __VA_ARGS__]; \ 25 | DDLogError(@"%@", description); \ 26 | NSAssert(NO, description); \ 27 | } 28 | 29 | #define DDAssertCondition(condition) DDAssert(condition, @"Condition not satisfied: %s", #condition) 30 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDLog+LOGV.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #ifndef Lumberjack_DDLog_LOGV_h 17 | #define Lumberjack_DDLog_LOGV_h 18 | 19 | #import "DDLog.h" 20 | 21 | 22 | #define LOGV_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, avalist) \ 23 | [DDLog log:isAsynchronous \ 24 | level:lvl \ 25 | flag:flg \ 26 | context:ctx \ 27 | file:__FILE__ \ 28 | function:fnct \ 29 | line:__LINE__ \ 30 | tag:atag \ 31 | format:frmt \ 32 | args:avalist] 33 | 34 | #define LOGV_OBJC_MACRO(async, lvl, flg, ctx, frmt, avalist) \ 35 | LOGV_MACRO(async, lvl, flg, ctx, nil, sel_getName(_cmd), frmt, avalist) 36 | 37 | #define LOGV_C_MACRO(async, lvl, flg, ctx, frmt, avalist) \ 38 | LOGV_MACRO(async, lvl, flg, ctx, nil, __FUNCTION__, frmt, avalist) 39 | 40 | 41 | 42 | #define SYNC_LOGV_OBJC_MACRO(lvl, flg, ctx, frmt, avalist) \ 43 | LOGV_OBJC_MACRO(NO, lvl, flg, ctx, frmt, avalist) 44 | 45 | #define ASYNC_LOGV_OBJC_MACRO(lvl, flg, ctx, frmt, avalist) \ 46 | LOGV_OBJC_MACRO(YES, lvl, flg, ctx, frmt, avalist) 47 | 48 | #define SYNC_LOGV_C_MACRO(lvl, flg, ctx, frmt, avalist) \ 49 | LOGV_C_MACRO(NO, lvl, flg, ctx, frmt, avalist) 50 | 51 | #define ASYNC_LOGV_C_MACRO(lvl, flg, ctx, frmt, avalist) \ 52 | LOGV_C_MACRO(YES, lvl, flg, ctx, frmt, avalist) 53 | 54 | 55 | 56 | #define LOGV_MAYBE(async, lvl, flg, ctx, fnct, frmt, avalist) \ 57 | do { if(lvl & flg) LOGV_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, avalist); } while(0) 58 | 59 | 60 | #define LOGV_OBJC_MAYBE(async, lvl, flg, ctx, frmt, avalist) \ 61 | LOGV_MAYBE(async, lvl, flg, ctx, sel_getName(_cmd), frmt, avalist) 62 | 63 | #define LOGV_C_MAYBE(async, lvl, flg, ctx, frmt, avalist) \ 64 | LOGV_MAYBE(async, lvl, flg, ctx, __FUNCTION__, frmt, avalist) 65 | 66 | #define SYNC_LOGV_OBJC_MAYBE(lvl, flg, ctx, frmt, avalist) \ 67 | LOGV_OBJC_MAYBE(NO, lvl, flg, ctx, frmt, avalist) 68 | 69 | #define ASYNC_LOGV_OBJC_MAYBE(lvl, flg, ctx, frmt, avalist) \ 70 | LOGV_OBJC_MAYBE(YES, lvl, flg, ctx, frmt, avalist) 71 | 72 | #define SYNC_LOGV_C_MAYBE(lvl, flg, ctx, frmt, avalist) \ 73 | LOGV_C_MAYBE(NO, lvl, flg, ctx, frmt, avalist) 74 | 75 | #define ASYNC_LOGV_C_MAYBE(lvl, flg, ctx, frmt, avalist) \ 76 | LOGV_C_MAYBE(YES, lvl, flg, ctx, frmt, avalist) 77 | 78 | 79 | 80 | #define LOGV_OBJC_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, avalist) \ 81 | LOGV_MACRO(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, avalist) 82 | 83 | #define LOGV_C_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, avalist) \ 84 | LOGV_MACRO(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, avalist) 85 | 86 | #define LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, avalist) \ 87 | do { if(lvl & flg) LOGV_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, avalist); } while(0) 88 | 89 | #define LOGV_OBJC_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, avalist) \ 90 | LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, avalist) 91 | 92 | #define LOGV_C_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, avalist) \ 93 | LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, avalist) 94 | 95 | 96 | 97 | #define DDLogvError(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, avalist) 98 | #define DDLogvWarn(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, avalist) 99 | #define DDLogvInfo(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, avalist) 100 | #define DDLogvVerbose(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, avalist) 101 | 102 | #define DDLogvCError(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, avalist) 103 | #define DDLogvCWarn(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, avalist) 104 | #define DDLogvCInfo(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, avalist) 105 | #define DDLogvCVerbose(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, avalist) 106 | 107 | #endif /* ifndef Lumberjack_DDLog_LOGV_h */ 108 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDLogMacros.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDLog.h" 17 | 18 | /** 19 | * Ready to use log macros. 20 | **/ 21 | 22 | #ifndef LOG_LEVEL_DEF 23 | #define LOG_LEVEL_DEF ddLogLevel 24 | #endif 25 | 26 | #define DDLogError(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_ERROR, LOG_LEVEL_DEF, LOG_FLAG_ERROR, 0, frmt, ## __VA_ARGS__) 27 | #define DDLogWarn(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_WARN, LOG_LEVEL_DEF, LOG_FLAG_WARN, 0, frmt, ## __VA_ARGS__) 28 | #define DDLogInfo(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_INFO, LOG_LEVEL_DEF, LOG_FLAG_INFO, 0, frmt, ## __VA_ARGS__) 29 | #define DDLogDebug(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_DEBUG, LOG_LEVEL_DEF, LOG_FLAG_DEBUG, 0, frmt, ## __VA_ARGS__) 30 | #define DDLogVerbose(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ## __VA_ARGS__) 31 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/DDTTYLogger.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDLog.h" 17 | 18 | #define LOG_CONTEXT_ALL INT_MAX 19 | 20 | /** 21 | * This class provides a logger for Terminal output or Xcode console output, 22 | * depending on where you are running your code. 23 | * 24 | * As described in the "Getting Started" page, 25 | * the traditional NSLog() function directs it's output to two places: 26 | * 27 | * - Apple System Log (so it shows up in Console.app) 28 | * - StdErr (if stderr is a TTY, so log statements show up in Xcode console) 29 | * 30 | * To duplicate NSLog() functionality you can simply add this logger and an asl logger. 31 | * However, if you instead choose to use file logging (for faster performance), 32 | * you may choose to use only a file logger and a tty logger. 33 | **/ 34 | 35 | #import "DDLog.h" 36 | 37 | #define LOG_CONTEXT_ALL INT_MAX 38 | 39 | #if TARGET_OS_IPHONE 40 | // iOS 41 | #import 42 | #define DDColor UIColor 43 | #define DDMakeColor(r, g, b) [UIColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f] 44 | #elif __has_include() 45 | // OS X with AppKit 46 | #import 47 | #define DDColor NSColor 48 | #define DDMakeColor(r, g, b) [NSColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f] 49 | #else 50 | // OS X CLI 51 | #import "CLIColor.h" 52 | #define DDColor CLIColor 53 | #define DDMakeColor(r, g, b) [CLIColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f] 54 | #endif 55 | 56 | @interface DDTTYLogger : DDAbstractLogger 57 | 58 | + (instancetype)sharedInstance; 59 | 60 | /* Inherited from the DDLogger protocol: 61 | * 62 | * Formatters may optionally be added to any logger. 63 | * 64 | * If no formatter is set, the logger simply logs the message as it is given in logMessage, 65 | * or it may use its own built in formatting style. 66 | * 67 | * More information about formatters can be found here: 68 | * Documentation/CustomFormatters.md 69 | * 70 | * The actual implementation of these methods is inherited from DDAbstractLogger. 71 | 72 | - (id )logFormatter; 73 | - (void)setLogFormatter:(id )formatter; 74 | 75 | */ 76 | 77 | /** 78 | * Want to use different colors for different log levels? 79 | * Enable this property. 80 | * 81 | * If you run the application via the Terminal (not Xcode), 82 | * the logger will map colors to xterm-256color or xterm-color (if available). 83 | * 84 | * Xcode does NOT natively support colors in the Xcode debugging console. 85 | * You'll need to install the XcodeColors plugin to see colors in the Xcode console. 86 | * https://github.com/robbiehanson/XcodeColors 87 | * 88 | * The default value is NO. 89 | **/ 90 | @property (readwrite, assign) BOOL colorsEnabled; 91 | 92 | /** 93 | * When using a custom formatter you can set the logMessage method not to append 94 | * '\n' character after each output. This allows for some greater flexibility with 95 | * custom formatters. Default value is YES. 96 | **/ 97 | 98 | @property (readwrite, assign) BOOL automaticallyAppendNewlineForCustomFormatters; 99 | 100 | /** 101 | * The default color set (foregroundColor, backgroundColor) is: 102 | * 103 | * - LOG_FLAG_ERROR = (red, nil) 104 | * - LOG_FLAG_WARN = (orange, nil) 105 | * 106 | * You can customize the colors however you see fit. 107 | * Please note that you are passing a flag, NOT a level. 108 | * 109 | * GOOD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_FLAG_INFO]; // <- Good :) 110 | * BAD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_LEVEL_INFO]; // <- BAD! :( 111 | * 112 | * LOG_FLAG_INFO = 0...00100 113 | * LOG_LEVEL_INFO = 0...00111 <- Would match LOG_FLAG_INFO and LOG_FLAG_WARN and LOG_FLAG_ERROR 114 | * 115 | * If you run the application within Xcode, then the XcodeColors plugin is required. 116 | * 117 | * If you run the application from a shell, then DDTTYLogger will automatically map the given color to 118 | * the closest available color. (xterm-256color or xterm-color which have 256 and 16 supported colors respectively.) 119 | * 120 | * This method invokes setForegroundColor:backgroundColor:forFlag:context: and applies it to `LOG_CONTEXT_ALL`. 121 | **/ 122 | - (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forFlag:(int)mask; 123 | 124 | /** 125 | * Just like setForegroundColor:backgroundColor:flag, but allows you to specify a particular logging context. 126 | * 127 | * A logging context is often used to identify log messages coming from a 3rd party framework, 128 | * although logging context's can be used for many different functions. 129 | * 130 | * Use LOG_CONTEXT_ALL to set the deafult color for all contexts that have no specific color set defined. 131 | * 132 | * Logging context's are explained in further detail here: 133 | * Documentation/CustomContext.md 134 | **/ 135 | - (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forFlag:(int)mask context:(int)ctxt; 136 | 137 | /** 138 | * Similar to the methods above, but allows you to map DDLogMessage->tag to a particular color profile. 139 | * For example, you could do something like this: 140 | * 141 | * static NSString *const PurpleTag = @"PurpleTag"; 142 | * 143 | * #define DDLogPurple(frmt, ...) LOG_OBJC_TAG_MACRO(NO, 0, 0, 0, PurpleTag, frmt, ##__VA_ARGS__) 144 | * 145 | * And then where you configure CocoaLumberjack: 146 | * 147 | * purple = DDMakeColor((64/255.0), (0/255.0), (128/255.0)); 148 | * 149 | * or any UIColor/NSColor constructor. 150 | * 151 | * Note: For CLI OS X projects that don't link with AppKit use CLIColor objects instead 152 | * 153 | * [[DDTTYLogger sharedInstance] setForegroundColor:purple backgroundColor:nil forTag:PurpleTag]; 154 | * [DDLog addLogger:[DDTTYLogger sharedInstance]]; 155 | * 156 | * This would essentially give you a straight NSLog replacement that prints in purple: 157 | * 158 | * DDLogPurple(@"I'm a purple log message!"); 159 | **/ 160 | - (void)setForegroundColor:(DDColor *)txtColor backgroundColor:(DDColor *)bgColor forTag:(id )tag; 161 | 162 | /** 163 | * Clearing color profiles. 164 | **/ 165 | - (void)clearColorsForFlag:(int)mask; 166 | - (void)clearColorsForFlag:(int)mask context:(int)context; 167 | - (void)clearColorsForTag:(id )tag; 168 | - (void)clearColorsForAllFlags; 169 | - (void)clearColorsForAllTags; 170 | - (void)clearAllColors; 171 | 172 | @end 173 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import 17 | #import "DDLog.h" 18 | 19 | /** 20 | * This class provides a log formatter that filters log statements from a logging context not on the whitelist. 21 | * 22 | * A log formatter can be added to any logger to format and/or filter its output. 23 | * You can learn more about log formatters here: 24 | * Documentation/CustomFormatters.md 25 | * 26 | * You can learn more about logging context's here: 27 | * Documentation/CustomContext.md 28 | * 29 | * But here's a quick overview / refresher: 30 | * 31 | * Every log statement has a logging context. 32 | * These come from the underlying logging macros defined in DDLog.h. 33 | * The default logging context is zero. 34 | * You can define multiple logging context's for use in your application. 35 | * For example, logically separate parts of your app each have a different logging context. 36 | * Also 3rd party frameworks that make use of Lumberjack generally use their own dedicated logging context. 37 | **/ 38 | @interface DDContextWhitelistFilterLogFormatter : NSObject 39 | 40 | - (id)init; 41 | 42 | - (void)addToWhitelist:(int)loggingContext; 43 | - (void)removeFromWhitelist:(int)loggingContext; 44 | 45 | - (NSArray *)whitelist; 46 | 47 | - (BOOL)isOnWhitelist:(int)loggingContext; 48 | 49 | @end 50 | 51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | #pragma mark - 53 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | 55 | /** 56 | * This class provides a log formatter that filters log statements from a logging context on the blacklist. 57 | **/ 58 | @interface DDContextBlacklistFilterLogFormatter : NSObject 59 | 60 | - (id)init; 61 | 62 | - (void)addToBlacklist:(int)loggingContext; 63 | - (void)removeFromBlacklist:(int)loggingContext; 64 | 65 | - (NSArray *)blacklist; 66 | 67 | - (BOOL)isOnBlacklist:(int)loggingContext; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.m: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDContextFilterLogFormatter.h" 17 | #import 18 | 19 | #if !__has_feature(objc_arc) 20 | #error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 21 | #endif 22 | 23 | @interface DDLoggingContextSet : NSObject 24 | 25 | - (void)addToSet:(int)loggingContext; 26 | - (void)removeFromSet:(int)loggingContext; 27 | 28 | - (NSArray *)currentSet; 29 | 30 | - (BOOL)isInSet:(int)loggingContext; 31 | 32 | @end 33 | 34 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | #pragma mark - 36 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | 38 | @interface DDContextWhitelistFilterLogFormatter () { 39 | DDLoggingContextSet *_contextSet; 40 | } 41 | 42 | @end 43 | 44 | 45 | @implementation DDContextWhitelistFilterLogFormatter 46 | 47 | - (id)init { 48 | if ((self = [super init])) { 49 | _contextSet = [[DDLoggingContextSet alloc] init]; 50 | } 51 | 52 | return self; 53 | } 54 | 55 | - (void)addToWhitelist:(int)loggingContext { 56 | [_contextSet addToSet:loggingContext]; 57 | } 58 | 59 | - (void)removeFromWhitelist:(int)loggingContext { 60 | [_contextSet removeFromSet:loggingContext]; 61 | } 62 | 63 | - (NSArray *)whitelist { 64 | return [_contextSet currentSet]; 65 | } 66 | 67 | - (BOOL)isOnWhitelist:(int)loggingContext { 68 | return [_contextSet isInSet:loggingContext]; 69 | } 70 | 71 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { 72 | if ([self isOnWhitelist:logMessage->logContext]) { 73 | return logMessage->logMsg; 74 | } else { 75 | return nil; 76 | } 77 | } 78 | 79 | @end 80 | 81 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 82 | #pragma mark - 83 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | 85 | @interface DDContextBlacklistFilterLogFormatter () { 86 | DDLoggingContextSet *_contextSet; 87 | } 88 | 89 | @end 90 | 91 | 92 | @implementation DDContextBlacklistFilterLogFormatter 93 | 94 | - (id)init { 95 | if ((self = [super init])) { 96 | _contextSet = [[DDLoggingContextSet alloc] init]; 97 | } 98 | 99 | return self; 100 | } 101 | 102 | - (void)addToBlacklist:(int)loggingContext { 103 | [_contextSet addToSet:loggingContext]; 104 | } 105 | 106 | - (void)removeFromBlacklist:(int)loggingContext { 107 | [_contextSet removeFromSet:loggingContext]; 108 | } 109 | 110 | - (NSArray *)blacklist { 111 | return [_contextSet currentSet]; 112 | } 113 | 114 | - (BOOL)isOnBlacklist:(int)loggingContext { 115 | return [_contextSet isInSet:loggingContext]; 116 | } 117 | 118 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { 119 | if ([self isOnBlacklist:logMessage->logContext]) { 120 | return nil; 121 | } else { 122 | return logMessage->logMsg; 123 | } 124 | } 125 | 126 | @end 127 | 128 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 129 | #pragma mark - 130 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 131 | 132 | 133 | @interface DDLoggingContextSet () { 134 | OSSpinLock _lock; 135 | NSMutableSet *_set; 136 | } 137 | 138 | @end 139 | 140 | 141 | @implementation DDLoggingContextSet 142 | 143 | - (id)init { 144 | if ((self = [super init])) { 145 | _set = [[NSMutableSet alloc] init]; 146 | } 147 | 148 | return self; 149 | } 150 | 151 | - (void)addToSet:(int)loggingContext { 152 | OSSpinLockLock(&_lock); 153 | { 154 | [_set addObject:@(loggingContext)]; 155 | } 156 | OSSpinLockUnlock(&_lock); 157 | } 158 | 159 | - (void)removeFromSet:(int)loggingContext { 160 | OSSpinLockLock(&_lock); 161 | { 162 | [_set removeObject:@(loggingContext)]; 163 | } 164 | OSSpinLockUnlock(&_lock); 165 | } 166 | 167 | - (NSArray *)currentSet { 168 | NSArray *result = nil; 169 | 170 | OSSpinLockLock(&_lock); 171 | { 172 | result = [_set allObjects]; 173 | } 174 | OSSpinLockUnlock(&_lock); 175 | 176 | return result; 177 | } 178 | 179 | - (BOOL)isInSet:(int)loggingContext { 180 | BOOL result = NO; 181 | 182 | OSSpinLockLock(&_lock); 183 | { 184 | result = [_set containsObject:@(loggingContext)]; 185 | } 186 | OSSpinLockUnlock(&_lock); 187 | 188 | return result; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import 17 | #import 18 | #import "DDLog.h" 19 | 20 | 21 | /** 22 | * This class provides a log formatter that prints the dispatch_queue label instead of the mach_thread_id. 23 | * 24 | * A log formatter can be added to any logger to format and/or filter its output. 25 | * You can learn more about log formatters here: 26 | * Documentation/CustomFormatters.md 27 | * 28 | * A typical NSLog (or DDTTYLogger) prints detailed info as [:]. 29 | * For example: 30 | * 31 | * 2011-10-17 20:21:45.435 AppName[19928:5207] Your log message here 32 | * 33 | * Where: 34 | * - 19928 = process id 35 | * - 5207 = thread id (mach_thread_id printed in hex) 36 | * 37 | * When using grand central dispatch (GCD), this information is less useful. 38 | * This is because a single serial dispatch queue may be run on any thread from an internally managed thread pool. 39 | * For example: 40 | * 41 | * 2011-10-17 20:32:31.111 AppName[19954:4d07] Message from my_serial_dispatch_queue 42 | * 2011-10-17 20:32:31.112 AppName[19954:5207] Message from my_serial_dispatch_queue 43 | * 2011-10-17 20:32:31.113 AppName[19954:2c55] Message from my_serial_dispatch_queue 44 | * 45 | * This formatter allows you to replace the standard [box:info] with the dispatch_queue name. 46 | * For example: 47 | * 48 | * 2011-10-17 20:32:31.111 AppName[img-scaling] Message from my_serial_dispatch_queue 49 | * 2011-10-17 20:32:31.112 AppName[img-scaling] Message from my_serial_dispatch_queue 50 | * 2011-10-17 20:32:31.113 AppName[img-scaling] Message from my_serial_dispatch_queue 51 | * 52 | * If the dispatch_queue doesn't have a set name, then it falls back to the thread name. 53 | * If the current thread doesn't have a set name, then it falls back to the mach_thread_id in hex (like normal). 54 | * 55 | * Note: If manually creating your own background threads (via NSThread/alloc/init or NSThread/detachNeThread), 56 | * you can use [[NSThread currentThread] setName:(NSString *)]. 57 | **/ 58 | @interface DDDispatchQueueLogFormatter : NSObject 59 | 60 | /** 61 | * Standard init method. 62 | * Configure using properties as desired. 63 | **/ 64 | - (id)init; 65 | 66 | /** 67 | * The minQueueLength restricts the minimum size of the [detail box]. 68 | * If the minQueueLength is set to 0, there is no restriction. 69 | * 70 | * For example, say a dispatch_queue has a label of "diskIO": 71 | * 72 | * If the minQueueLength is 0: [diskIO] 73 | * If the minQueueLength is 4: [diskIO] 74 | * If the minQueueLength is 5: [diskIO] 75 | * If the minQueueLength is 6: [diskIO] 76 | * If the minQueueLength is 7: [diskIO ] 77 | * If the minQueueLength is 8: [diskIO ] 78 | * 79 | * The default minQueueLength is 0 (no minimum, so [detail box] won't be padded). 80 | * 81 | * If you want every [detail box] to have the exact same width, 82 | * set both minQueueLength and maxQueueLength to the same value. 83 | **/ 84 | @property (assign, atomic) NSUInteger minQueueLength; 85 | 86 | /** 87 | * The maxQueueLength restricts the number of characters that will be inside the [detail box]. 88 | * If the maxQueueLength is 0, there is no restriction. 89 | * 90 | * For example, say a dispatch_queue has a label of "diskIO": 91 | * 92 | * If the maxQueueLength is 0: [diskIO] 93 | * If the maxQueueLength is 4: [disk] 94 | * If the maxQueueLength is 5: [diskI] 95 | * If the maxQueueLength is 6: [diskIO] 96 | * If the maxQueueLength is 7: [diskIO] 97 | * If the maxQueueLength is 8: [diskIO] 98 | * 99 | * The default maxQueueLength is 0 (no maximum, so [detail box] won't be truncated). 100 | * 101 | * If you want every [detail box] to have the exact same width, 102 | * set both minQueueLength and maxQueueLength to the same value. 103 | **/ 104 | @property (assign, atomic) NSUInteger maxQueueLength; 105 | 106 | /** 107 | * Sometimes queue labels have long names like "com.apple.main-queue", 108 | * but you'd prefer something shorter like simply "main". 109 | * 110 | * This method allows you to set such preferred replacements. 111 | * The above example is set by default. 112 | * 113 | * To remove/undo a previous replacement, invoke this method with nil for the 'shortLabel' parameter. 114 | **/ 115 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel; 116 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel; 117 | 118 | @end 119 | 120 | /** 121 | * Method declarations that make it easier to extend/modify DDDispatchQueueLogFormatter 122 | **/ 123 | @interface DDDispatchQueueLogFormatter (OverridableMethods) 124 | 125 | - (NSString *)stringFromDate:(NSDate *)date; 126 | - (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage; 127 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage; 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.m: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDDispatchQueueLogFormatter.h" 17 | #import 18 | 19 | 20 | #if !__has_feature(objc_arc) 21 | #error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 22 | #endif 23 | 24 | @interface DDDispatchQueueLogFormatter () { 25 | NSString *_dateFormatString; 26 | 27 | int32_t _atomicLoggerCount; 28 | NSDateFormatter *_threadUnsafeDateFormatter; // Use [self stringFromDate] 29 | 30 | OSSpinLock _lock; 31 | 32 | NSUInteger _minQueueLength; // _prefix == Only access via atomic property 33 | NSUInteger _maxQueueLength; // _prefix == Only access via atomic property 34 | NSMutableDictionary *_replacements; // _prefix == Only access from within spinlock 35 | } 36 | 37 | @end 38 | 39 | 40 | @implementation DDDispatchQueueLogFormatter 41 | 42 | - (id)init { 43 | if ((self = [super init])) { 44 | _dateFormatString = @"yyyy-MM-dd HH:mm:ss:SSS"; 45 | 46 | _atomicLoggerCount = 0; 47 | _threadUnsafeDateFormatter = nil; 48 | 49 | _minQueueLength = 0; 50 | _maxQueueLength = 0; 51 | _replacements = [[NSMutableDictionary alloc] init]; 52 | 53 | // Set default replacements: 54 | 55 | _replacements[@"com.apple.main-thread"] = @"main"; 56 | } 57 | 58 | return self; 59 | } 60 | 61 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 62 | #pragma mark Configuration 63 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | 65 | @synthesize minQueueLength = _minQueueLength; 66 | @synthesize maxQueueLength = _maxQueueLength; 67 | 68 | - (NSString *)replacementStringForQueueLabel:(NSString *)longLabel { 69 | NSString *result = nil; 70 | 71 | OSSpinLockLock(&_lock); 72 | { 73 | result = _replacements[longLabel]; 74 | } 75 | OSSpinLockUnlock(&_lock); 76 | 77 | return result; 78 | } 79 | 80 | - (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel { 81 | OSSpinLockLock(&_lock); 82 | { 83 | if (shortLabel) { 84 | _replacements[longLabel] = shortLabel; 85 | } else { 86 | [_replacements removeObjectForKey:longLabel]; 87 | } 88 | } 89 | OSSpinLockUnlock(&_lock); 90 | } 91 | 92 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 93 | #pragma mark DDLogFormatter 94 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 95 | 96 | - (NSString *)stringFromDate:(NSDate *)date { 97 | int32_t loggerCount = OSAtomicAdd32(0, &_atomicLoggerCount); 98 | 99 | NSString *calendarIdentifier = nil; 100 | 101 | #if defined(__IPHONE_8_0) || defined(__MAC_10_10) 102 | calendarIdentifier = NSCalendarIdentifierGregorian; 103 | #else 104 | calendarIdentifier = NSGregorianCalendar; 105 | #endif 106 | 107 | if (loggerCount <= 1) { 108 | // Single-threaded mode. 109 | 110 | if (_threadUnsafeDateFormatter == nil) { 111 | _threadUnsafeDateFormatter = [[NSDateFormatter alloc] init]; 112 | [_threadUnsafeDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; 113 | [_threadUnsafeDateFormatter setDateFormat:_dateFormatString]; 114 | } 115 | 116 | [_threadUnsafeDateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier]]; 117 | return [_threadUnsafeDateFormatter stringFromDate:date]; 118 | } else { 119 | // Multi-threaded mode. 120 | // NSDateFormatter is NOT thread-safe. 121 | 122 | NSString *key = @"DispatchQueueLogFormatter_NSDateFormatter"; 123 | 124 | NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary]; 125 | NSDateFormatter *dateFormatter = threadDictionary[key]; 126 | 127 | if (dateFormatter == nil) { 128 | dateFormatter = [[NSDateFormatter alloc] init]; 129 | [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; 130 | [dateFormatter setDateFormat:_dateFormatString]; 131 | 132 | threadDictionary[key] = dateFormatter; 133 | } 134 | 135 | [dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier]]; 136 | return [dateFormatter stringFromDate:date]; 137 | } 138 | } 139 | 140 | - (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage { 141 | // As per the DDLogFormatter contract, this method is always invoked on the same thread/dispatch_queue 142 | 143 | NSUInteger minQueueLength = self.minQueueLength; 144 | NSUInteger maxQueueLength = self.maxQueueLength; 145 | 146 | // Get the name of the queue, thread, or machID (whichever we are to use). 147 | 148 | NSString *queueThreadLabel = nil; 149 | 150 | BOOL useQueueLabel = YES; 151 | BOOL useThreadName = NO; 152 | 153 | if (logMessage->queueLabel) { 154 | // If you manually create a thread, it's dispatch_queue will have one of the thread names below. 155 | // Since all such threads have the same name, we'd prefer to use the threadName or the machThreadID. 156 | 157 | char *names[] = { 158 | "com.apple.root.low-priority", 159 | "com.apple.root.default-priority", 160 | "com.apple.root.high-priority", 161 | "com.apple.root.low-overcommit-priority", 162 | "com.apple.root.default-overcommit-priority", 163 | "com.apple.root.high-overcommit-priority" 164 | }; 165 | 166 | int length = sizeof(names) / sizeof(char *); 167 | 168 | int i; 169 | 170 | for (i = 0; i < length; i++) { 171 | if (strcmp(logMessage->queueLabel, names[i]) == 0) { 172 | useQueueLabel = NO; 173 | useThreadName = [logMessage->threadName length] > 0; 174 | break; 175 | } 176 | } 177 | } else { 178 | useQueueLabel = NO; 179 | useThreadName = [logMessage->threadName length] > 0; 180 | } 181 | 182 | if (useQueueLabel || useThreadName) { 183 | NSString *fullLabel; 184 | NSString *abrvLabel; 185 | 186 | if (useQueueLabel) { 187 | fullLabel = @(logMessage->queueLabel); 188 | } else { 189 | fullLabel = logMessage->threadName; 190 | } 191 | 192 | OSSpinLockLock(&_lock); 193 | { 194 | abrvLabel = _replacements[fullLabel]; 195 | } 196 | OSSpinLockUnlock(&_lock); 197 | 198 | if (abrvLabel) { 199 | queueThreadLabel = abrvLabel; 200 | } else { 201 | queueThreadLabel = fullLabel; 202 | } 203 | } else { 204 | queueThreadLabel = [NSString stringWithFormat:@"%x", logMessage->machThreadID]; 205 | } 206 | 207 | // Now use the thread label in the output 208 | 209 | NSUInteger labelLength = [queueThreadLabel length]; 210 | 211 | // labelLength > maxQueueLength : truncate 212 | // labelLength < minQueueLength : padding 213 | // : exact 214 | 215 | if ((maxQueueLength > 0) && (labelLength > maxQueueLength)) { 216 | // Truncate 217 | 218 | return [queueThreadLabel substringToIndex:maxQueueLength]; 219 | } else if (labelLength < minQueueLength) { 220 | // Padding 221 | 222 | NSUInteger numSpaces = minQueueLength - labelLength; 223 | 224 | char spaces[numSpaces + 1]; 225 | memset(spaces, ' ', numSpaces); 226 | spaces[numSpaces] = '\0'; 227 | 228 | return [NSString stringWithFormat:@"%@%s", queueThreadLabel, spaces]; 229 | } else { 230 | // Exact 231 | 232 | return queueThreadLabel; 233 | } 234 | } 235 | 236 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { 237 | NSString *timestamp = [self stringFromDate:(logMessage->timestamp)]; 238 | NSString *queueThreadLabel = [self queueThreadLabelForLogMessage:logMessage]; 239 | 240 | return [NSString stringWithFormat:@"%@ [%@] %@", timestamp, queueThreadLabel, logMessage->logMsg]; 241 | } 242 | 243 | - (void)didAddToLogger:(id )logger { 244 | OSAtomicIncrement32(&_atomicLoggerCount); 245 | } 246 | 247 | - (void)willRemoveFromLogger:(id )logger { 248 | OSAtomicDecrement32(&_atomicLoggerCount); 249 | } 250 | 251 | @end 252 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import 17 | #import "DDLog.h" 18 | 19 | /** 20 | * This formatter can be used to chain different formatters together. 21 | * The log message will processed in the order of the formatters added. 22 | **/ 23 | 24 | @interface DDMultiFormatter : NSObject 25 | 26 | /** 27 | * Array of chained formatters 28 | */ 29 | @property (readonly) NSArray *formatters; 30 | 31 | - (void)addFormatter:(id)formatter; 32 | - (void)removeFormatter:(id)formatter; 33 | - (void)removeAllFormatters; 34 | - (BOOL)isFormattingWithFormatter:(id)formatter; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.m: -------------------------------------------------------------------------------- 1 | // Software License Agreement (BSD License) 2 | // 3 | // Copyright (c) 2010-2014, Deusty, LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use of this software in source and binary forms, 7 | // with or without modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // * Neither the name of Deusty nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without specific 14 | // prior written permission of Deusty, LLC. 15 | 16 | #import "DDMultiFormatter.h" 17 | 18 | 19 | #if TARGET_OS_IPHONE 20 | // Compiling for iOS 21 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later 22 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 23 | #else // iOS 5.X or earlier 24 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 25 | #endif 26 | #else 27 | // Compiling for Mac OS X 28 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later 29 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 30 | #else // Mac OS X 10.7 or earlier 31 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 32 | #endif 33 | #endif 34 | 35 | 36 | #if !__has_feature(objc_arc) 37 | #error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 38 | #endif 39 | 40 | 41 | @interface DDMultiFormatter () { 42 | dispatch_queue_t _queue; 43 | NSMutableArray *_formatters; 44 | } 45 | 46 | - (DDLogMessage *)logMessageForLine:(NSString *)line originalMessage:(DDLogMessage *)message; 47 | 48 | @end 49 | 50 | 51 | @implementation DDMultiFormatter 52 | 53 | - (id)init { 54 | self = [super init]; 55 | 56 | if (self) { 57 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 58 | _queue = dispatch_queue_create("cocoa.lumberjack.multiformatter", DISPATCH_QUEUE_CONCURRENT); 59 | #else 60 | _queue = dispatch_queue_create("cocoa.lumberjack.multiformatter", NULL); 61 | #endif 62 | _formatters = [NSMutableArray new]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | #if NEEDS_DISPATCH_RETAIN_RELEASE 69 | - (void)dealloc { 70 | dispatch_release(_queue); 71 | } 72 | 73 | #endif 74 | 75 | #pragma mark Processing 76 | 77 | - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { 78 | __block NSString *line = logMessage->logMsg; 79 | 80 | dispatch_sync(_queue, ^{ 81 | for (id formatter in _formatters) { 82 | DDLogMessage *message = [self logMessageForLine:line originalMessage:logMessage]; 83 | line = [formatter formatLogMessage:message]; 84 | 85 | if (!line) { 86 | break; 87 | } 88 | } 89 | }); 90 | 91 | return line; 92 | } 93 | 94 | - (DDLogMessage *)logMessageForLine:(NSString *)line originalMessage:(DDLogMessage *)message { 95 | DDLogMessage *newMessage = [message copy]; 96 | 97 | newMessage->logMsg = line; 98 | return newMessage; 99 | } 100 | 101 | #pragma mark Formatters 102 | 103 | - (NSArray *)formatters { 104 | __block NSArray *formatters; 105 | 106 | dispatch_sync(_queue, ^{ 107 | formatters = [_formatters copy]; 108 | }); 109 | 110 | return formatters; 111 | } 112 | 113 | - (void)addFormatter:(id)formatter { 114 | dispatch_barrier_async(_queue, ^{ 115 | [_formatters addObject:formatter]; 116 | }); 117 | } 118 | 119 | - (void)removeFormatter:(id)formatter { 120 | dispatch_barrier_async(_queue, ^{ 121 | [_formatters removeObject:formatter]; 122 | }); 123 | } 124 | 125 | - (void)removeAllFormatters { 126 | dispatch_barrier_async(_queue, ^{ 127 | [_formatters removeAllObjects]; 128 | }); 129 | } 130 | 131 | - (BOOL)isFormattingWithFormatter:(id)formatter { 132 | __block BOOL hasFormatter; 133 | 134 | dispatch_sync(_queue, ^{ 135 | hasFormatter = [_formatters containsObject:formatter]; 136 | }); 137 | 138 | return hasFormatter; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2010-2014, Deusty, LLC 4 | All rights reserved. 5 | 6 | Redistribution and use of this software in source and binary forms, 7 | with or without modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Neither the name of Deusty nor the names of its 14 | contributors may be used to endorse or promote products 15 | derived from this software without specific prior 16 | written permission of Deusty, LLC. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Pods/CocoaLumberjack/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | CocoaLumberjack 6 | =============== 7 | [![Build Status](http://img.shields.io/travis/CocoaLumberjack/CocoaLumberjack/master.svg?style=flat)](https://travis-ci.org/CocoaLumberjack/CocoaLumberjack) 8 | [![Pod Version](http://img.shields.io/cocoapods/v/CocoaLumberjack.svg?style=flat)](http://cocoadocs.org/docsets/CocoaLumberjack/) 9 | [![Pod Platform](http://img.shields.io/cocoapods/p/CocoaLumberjack.svg?style=flat)](http://cocoadocs.org/docsets/CocoaLumberjack/) 10 | [![Pod License](http://img.shields.io/cocoapods/l/CocoaLumberjack.svg?style=flat)](http://opensource.org/licenses/BSD-3-Clause) 11 | [![Reference Status](https://www.versioneye.com/objective-c/cocoalumberjack/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/cocoalumberjack/references) 12 | 13 | **CocoaLumberjack** is a fast & simple, yet powerful & flexible logging framework for Mac and iOS. 14 | 15 | ### CocoaLumberjack 2 pre-release notes 16 | 17 | #### Migrating to 2.x-beta 18 | 19 | * Replace `DDLog.h` imports by `#import `. 20 | * Replace all `DDLogC` macros for regular `DDLog` macros. 21 | 22 | #### Forcing 1.x 23 | 24 | If an included library requires it, you can force CocoaLumberjack 1.x by setting the version before the conflicting library: 25 | 26 | ```ruby 27 | pod 'CocoaLumberjack', '~> 1.9' 28 | pod 'ConflictingLibrary' 29 | ``` 30 | 31 | ### Features 32 | 33 | #### Lumberjack is Fast & Simple, yet Powerful & Flexible. 34 | 35 | It is similar in concept to other popular logging frameworks such as log4j, yet is designed specifically for Objective-C, and takes advantage of features such as multi-threading, grand central dispatch (if available), lockless atomic operations, and the dynamic nature of the Objective-C runtime. 36 | 37 | #### Lumberjack is Fast 38 | 39 | In most cases it is an order of magnitude faster than NSLog. 40 | 41 | #### Lumberjack is Simple 42 | 43 | It takes as little as a single line of code to configure lumberjack when your application launches. Then simply replace your NSLog statements with DDLog statements and that's about it. (And the DDLog macros have the exact same format and syntax as NSLog, so it's super easy.) 44 | 45 | #### Lumberjack is Powerful: 46 | 47 | One log statement can be sent to multiple loggers, meaning you can log to a file and the console simultaneously. Want more? Create your own loggers (it's easy) and send your log statements over the network. Or to a database or distributed file system. The sky is the limit. 48 | 49 | #### Lumberjack is Flexible: 50 | 51 | Configure your logging however you want. Change log levels per file (perfect for debugging). Change log levels per logger (verbose console, but concise log file). Change log levels per xcode configuration (verbose debug, but concise release). Have your log statements compiled out of the release build. Customize the number of log levels for your application. Add your own fine-grained logging. Dynamically change log levels during runtime. Choose how & when you want your log files to be rolled. Upload your log files to a central server. Compress archived log files to save disk space... 52 | 53 | ### This framework is for you if: 54 | 55 | - You're looking for a way to track down that impossible-to-reproduce bug that keeps popping up in the field. 56 | - You're frustrated with the super short console log on the iPhone. 57 | - You're looking to take your application to the next level in terms of support and stability. 58 | - You're looking for an enterprise level logging solution for your application (Mac or iPhone). 59 | 60 | ### How to get started 61 | - install via [CocoaPods](http://cocoapods.org) 62 | 63 | ```ruby 64 | platform :ios, '6.1' 65 | pod 'CocoaLumberjack' 66 | ``` 67 | - read the [Getting started](Documentation/GettingStarted.md) guide, check out the [FAQ](Documentation/FAQ.md) section or the other [docs](Documentation/) 68 | - if you find issues or want to suggest improvements, create an issue or a pull request 69 | - for all kinds of questions involving CocoaLumberjack, use the [Google group](http://groups.google.com/group/cocoalumberjack) or StackOverflow (use [#lumberjack](http://stackoverflow.com/questions/tagged/lumberjack)). 70 | 71 | ### Documentation 72 | 73 | - **[Get started using Lumberjack](Documentation/GettingStarted.md)**
74 | - [Different log levels for Debug and Release builds](Documentation/XcodeTricks.md)
75 | - [Different log levels for each logger](Documentation/PerLoggerLogLevels.md)
76 | - [Use colors in the Xcode debugging console](Documentation/XcodeColors.md)
77 | - [Write your own custom formatters](Documentation/CustomFormatters.md)
78 | - [FAQ](Documentation/FAQ.md)
79 | - [Analysis of performance with benchmarks](Documentation/Performance.md)
80 | - [Common issues you may encounter and their solutions](Documentation/ProblemSolution.md)
81 | - [AppCode support](Documentation/AppCode-support.md) 82 | - **[Full Lumberjack documentation](Documentation/)**
83 | 84 | ### Requirements 85 | - Xcode 4.4 or later is required 86 | - iOS 5 or later 87 | - OS X 10.7 or later 88 | - for OS X < 10.7 support, use the 1.6.0 version 89 | 90 | ### Author 91 | - [Robbie Hanson](https://github.com/robbiehanson) 92 | - Love the project? Wanna buy me a coffee? (or a beer :D) [![donation](http://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UZRA26JPJB3DA) 93 | 94 | ### Collaborators 95 | - [Ernesto Rivera](https://github.com/rivera-ernesto) 96 | - [Dmitry Vorobyov](https://github.com/dvor) 97 | - [Bogdan Poplauschi](https://github.com/bpoplauschi) 98 | 99 | ### License 100 | - CocoaLumberjack is available under the BSD license. See the [LICENSE file](https://github.com/CocoaLumberjack/CocoaLumberjack/blob/master/LICENSE.txt). 101 | -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Crashlytics: -------------------------------------------------------------------------------- 1 | Versions/Current/Crashlytics -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module Crashlytics { 2 | umbrella header "Crashlytics.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Versions/A/Crashlytics: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/Pods/CrashlyticsFramework/Crashlytics.framework/Versions/A/Crashlytics -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Versions/A/Headers/Crashlytics.h: -------------------------------------------------------------------------------- 1 | // 2 | // Crashlytics.h 3 | // Crashlytics 4 | // 5 | // Copyright 2013 Crashlytics, Inc. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /** 11 | * 12 | * The CLS_LOG macro provides as easy way to gather more information in your log messages that are 13 | * sent with your crash data. CLS_LOG prepends your custom log message with the function name and 14 | * line number where the macro was used. If your app was built with the DEBUG preprocessor macro 15 | * defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog. 16 | * If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only. 17 | * 18 | * Example output: 19 | * -[AppDelegate login:] line 134 $ login start 20 | * 21 | * If you would like to change this macro, create a new header file, unset our define and then define 22 | * your own version. Make sure this new header file is imported after the Crashlytics header file. 23 | * 24 | * #undef CLS_LOG 25 | * #define CLS_LOG(__FORMAT__, ...) CLSNSLog... 26 | * 27 | **/ 28 | #ifdef DEBUG 29 | #define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 30 | #else 31 | #define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 32 | #endif 33 | 34 | /** 35 | * 36 | * Add logging that will be sent with your crash data. This logging will not show up in the system.log 37 | * and will only be visible in your Crashlytics dashboard. 38 | * 39 | **/ 40 | OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); 41 | OBJC_EXTERN void CLSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0); 42 | 43 | /** 44 | * 45 | * Add logging that will be sent with your crash data. This logging will show up in the system.log 46 | * and your Crashlytics dashboard. It is not recommended for Release builds. 47 | * 48 | **/ 49 | OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); 50 | OBJC_EXTERN void CLSNSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0); 51 | 52 | 53 | @protocol CrashlyticsDelegate; 54 | 55 | @interface Crashlytics : NSObject 56 | 57 | @property (nonatomic, readonly, copy) NSString *apiKey; 58 | @property (nonatomic, readonly, copy) NSString *version; 59 | @property (nonatomic, assign) BOOL debugMode; 60 | 61 | @property (nonatomic, assign) NSObject *delegate; 62 | 63 | /** 64 | * 65 | * The recommended way to install Crashlytics into your application is to place a call 66 | * to +startWithAPIKey: in your -application:didFinishLaunchingWithOptions: method. 67 | * 68 | * This delay defaults to 1 second in order to generally give the application time to 69 | * fully finish launching. 70 | * 71 | **/ 72 | + (Crashlytics *)startWithAPIKey:(NSString *)apiKey; 73 | + (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay; 74 | 75 | /** 76 | * 77 | * If you need the functionality provided by the CrashlyticsDelegate protocol, you can use 78 | * these convenience methods to activate the framework and set the delegate in one call. 79 | * 80 | **/ 81 | + (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject *)delegate; 82 | + (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject *)delegate afterDelay:(NSTimeInterval)delay; 83 | 84 | /** 85 | * 86 | * Access the singleton Crashlytics instance. 87 | * 88 | **/ 89 | + (Crashlytics *)sharedInstance; 90 | 91 | /** 92 | * 93 | * The easiest way to cause a crash - great for testing! 94 | * 95 | **/ 96 | - (void)crash; 97 | 98 | /** 99 | * 100 | * Many of our customers have requested the ability to tie crashes to specific end-users of their 101 | * application in order to facilitate responses to support requests or permit the ability to reach 102 | * out for more information. We allow you to specify up to three separate values for display within 103 | * the Crashlytics UI - but please be mindful of your end-user's privacy. 104 | * 105 | * We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record 106 | * in your system. This could be a database id, hash, or other value that is meaningless to a 107 | * third-party observer but can be indexed and queried by you. 108 | * 109 | * Optionally, you may also specify the end-user's name or username, as well as email address if you 110 | * do not have a system that works well with obscured identifiers. 111 | * 112 | * Pursuant to our EULA, this data is transferred securely throughout our system and we will not 113 | * disseminate end-user data unless required to by law. That said, if you choose to provide end-user 114 | * contact information, we strongly recommend that you disclose this in your application's privacy 115 | * policy. Data privacy is of our utmost concern. 116 | * 117 | **/ 118 | - (void)setUserIdentifier:(NSString *)identifier; 119 | - (void)setUserName:(NSString *)name; 120 | - (void)setUserEmail:(NSString *)email; 121 | 122 | + (void)setUserIdentifier:(NSString *)identifier; 123 | + (void)setUserName:(NSString *)name; 124 | + (void)setUserEmail:(NSString *)email; 125 | 126 | /** 127 | * 128 | * Set a value for a key to be associated with your crash data. 129 | * 130 | **/ 131 | - (void)setObjectValue:(id)value forKey:(NSString *)key; 132 | - (void)setIntValue:(int)value forKey:(NSString *)key; 133 | - (void)setBoolValue:(BOOL)value forKey:(NSString *)key; 134 | - (void)setFloatValue:(float)value forKey:(NSString *)key; 135 | 136 | + (void)setObjectValue:(id)value forKey:(NSString *)key; 137 | + (void)setIntValue:(int)value forKey:(NSString *)key; 138 | + (void)setBoolValue:(BOOL)value forKey:(NSString *)key; 139 | + (void)setFloatValue:(float)value forKey:(NSString *)key; 140 | 141 | @end 142 | 143 | /** 144 | * The CLSCrashReport protocol exposes methods that you can call on crash report objects passed 145 | * to delegate methods. If you want these values or the entire object to stay in memory retain 146 | * them or copy them. 147 | **/ 148 | @protocol CLSCrashReport 149 | @required 150 | 151 | /** 152 | * Returns the session identifier for the crash report. 153 | **/ 154 | @property (nonatomic, readonly) NSString *identifier; 155 | 156 | /** 157 | * Returns the custom key value data for the crash report. 158 | **/ 159 | @property (nonatomic, readonly) NSDictionary *customKeys; 160 | 161 | /** 162 | * Returns the CFBundleVersion of the application that crashed. 163 | **/ 164 | @property (nonatomic, readonly) NSString *bundleVersion; 165 | 166 | /** 167 | * Returns the CFBundleShortVersionString of the application that crashed. 168 | **/ 169 | @property (nonatomic, readonly) NSString *bundleShortVersionString; 170 | 171 | /** 172 | * Returns the date that the application crashed at. 173 | **/ 174 | @property (nonatomic, readonly) NSDate *crashedOnDate; 175 | 176 | /** 177 | * Returns the os version that the application crashed on. 178 | **/ 179 | @property (nonatomic, readonly) NSString *OSVersion; 180 | 181 | /** 182 | * Returns the os build version that the application crashed on. 183 | **/ 184 | @property (nonatomic, readonly) NSString *OSBuildVersion; 185 | 186 | @end 187 | 188 | /** 189 | * 190 | * The CrashlyticsDelegate protocol provides a mechanism for your application to take 191 | * action on events that occur in the Crashlytics crash reporting system. You can make 192 | * use of these calls by assigning an object to the Crashlytics' delegate property directly, 193 | * or through the convenience startWithAPIKey:delegate:... methods. 194 | * 195 | **/ 196 | @protocol CrashlyticsDelegate 197 | @optional 198 | 199 | /** 200 | * 201 | * Called once a Crashlytics instance has determined that the last execution of the 202 | * application ended in a crash. This is called some time after the crash reporting 203 | * process has begun. If you have specified a delay in one of the 204 | * startWithAPIKey:... calls, this will take at least that long to be invoked. 205 | * 206 | **/ 207 | - (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics; 208 | 209 | /** 210 | * 211 | * Just like crashlyticsDidDetectCrashDuringPreviousExecution this delegate method is 212 | * called once a Crashlytics instance has determined that the last execution of the 213 | * application ended in a crash. A CLSCrashReport is passed back that contains data about 214 | * the last crash report that was generated. See the CLSCrashReport protocol for method details. 215 | * This method is called after crashlyticsDidDetectCrashDuringPreviousExecution. 216 | * 217 | **/ 218 | - (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id )crash; 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | Crashlytics 9 | CFBundleIdentifier 10 | com.crashlytics.ios 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Crashlytics 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.5 19 | CFBundleSupportedPlatforms 20 | 21 | iPhoneOS 22 | 23 | CFBundleVersion 24 | 40 25 | DTPlatformName 26 | iphoneos 27 | MinimumOSVersion 28 | 4.0 29 | 30 | 31 | -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/run: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/Pods/CrashlyticsFramework/Crashlytics.framework/run -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/Crashlytics.framework/submit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/Pods/CrashlyticsFramework/Crashlytics.framework/submit -------------------------------------------------------------------------------- /Pods/CrashlyticsFramework/README.md: -------------------------------------------------------------------------------- 1 | CrashlyticsFramework 2 | ==================== 3 | [![Build Status](http://img.shields.io/travis/bpoplauschi/CrashlyticsFramework/master.svg?style=flat)](https://travis-ci.org/bpoplauschi/CrashlyticsFramework) 4 | [![Pod Version](http://img.shields.io/cocoapods/v/CrashlyticsFramework.svg?style=flat)](http://cocoadocs.org/docsets/CrashlyticsFramework/) 5 | [![Pod Platform](http://img.shields.io/cocoapods/p/CrashlyticsFramework.svg?style=flat)](http://cocoadocs.org/docsets/CrashlyticsFramework/) 6 | [![Pod License](http://img.shields.io/cocoapods/l/CrashlyticsFramework.svg?style=flat)](http://try.crashlytics.com/terms/terms-of-use.pdf) 7 | 8 | **The most powerful, yet lightest weight crash reporting solution for iOS and Android developers. | Crashlytics** 9 | 10 | ## Reason 11 | *The reason for making this repo was that the Crashlytics framework is not directly available for download anywhere and it's super easy to integrate it via Cocoapods* 12 | 13 | ## Usage via CocoaPods 14 | ``` ruby 15 | pod 'CrashlyticsFramework' 16 | ``` 17 | 18 | *Note: the path you should use for the `run` script is `./Pods/CrashlyticsFramework/Crashlytics.framework/run`* 19 | 20 | ## License 21 | - [Crashlytics - Terms of Use](http://try.crashlytics.com/terms/terms-of-service.pdf) 22 | - [Crashlytics - Privacy Policy](http://try.crashlytics.com/terms/privacy-policy.pdf) 23 | - [Crashlytics - Open Source licenses](http://try.crashlytics.com/terms/opensource.txt) 24 | 25 | ## Contact 26 | - [Crashlytics homepage](crashlytics.com) 27 | - [Crashlytics blog](http://www.crashlytics.com/blog/) 28 | - [Crashlytics support](http://support.crashlytics.com/knowledgebase) 29 | -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/CLIColor.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/CLI/CLIColor.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/CocoaLumberjack.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/CocoaLumberjack.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDASLLogCapture.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDASLLogCapture.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDASLLogger.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDASLLogger.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDAbstractDatabaseLogger.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDAssertMacros.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDAssertMacros.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDContextFilterLogFormatter.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDDispatchQueueLogFormatter.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDFileLogger.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDFileLogger.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDLog+LOGV.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDLog+LOGV.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDLog.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDLog.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDLogMacros.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDLogMacros.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDMultiFormatter.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CocoaLumberjack/DDTTYLogger.h: -------------------------------------------------------------------------------- 1 | ../../../CocoaLumberjack/Classes/DDTTYLogger.h -------------------------------------------------------------------------------- /Pods/Headers/Public/CrashlyticsFramework/Crashlytics.h: -------------------------------------------------------------------------------- 1 | ../../../CrashlyticsFramework/Crashlytics.framework/Versions/A/Headers/Crashlytics.h -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - CocoaLumberjack (2.0.0-beta2): 3 | - CocoaLumberjack/CLI 4 | - CocoaLumberjack/Core 5 | - CocoaLumberjack/Extensions 6 | - CocoaLumberjack/CLI (2.0.0-beta2): 7 | - CocoaLumberjack/Core 8 | - CocoaLumberjack/Core (2.0.0-beta2) 9 | - CocoaLumberjack/Extensions (2.0.0-beta2): 10 | - CocoaLumberjack/Core 11 | - CrashlyticsFramework (2.2.5) 12 | 13 | DEPENDENCIES: 14 | - CocoaLumberjack 15 | - CrashlyticsFramework 16 | 17 | SPEC CHECKSUMS: 18 | CocoaLumberjack: 956d3fb98fed498a13d56499f262c975ef431c98 19 | CrashlyticsFramework: 82d124501d97d3b5d49bd6209dea21c6b7f0a33d 20 | 21 | COCOAPODS: 0.34.4 22 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-CocoaLumberjack.xcconfig" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/CocoaLumberjack" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/CrashlyticsFramework" 4 | OTHER_LDFLAGS = -ObjC 5 | PODS_ROOT = ${SRCROOT} -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_CocoaLumberjack : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_CocoaLumberjack 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-environment.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack.xcconfig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyupa/JenkinsCI-iOS/8e6856dcec7caa2450b09f4a6b6e64f34bf26568/Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack.xcconfig -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CrashlyticsFramework/Pods-CrashlyticsFramework-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-CrashlyticsFramework.xcconfig" 2 | FRAMEWORK_SEARCH_PATHS = ${PODS_CRASHLYTICSFRAMEWORK_FRAMEWORK_SEARCH_PATHS} 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/CrashlyticsFramework" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/CrashlyticsFramework" 5 | OTHER_LDFLAGS = ${PODS_CRASHLYTICSFRAMEWORK_OTHER_LDFLAGS} -ObjC 6 | PODS_ROOT = ${SRCROOT} -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CrashlyticsFramework/Pods-CrashlyticsFramework-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_CrashlyticsFramework : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_CrashlyticsFramework 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CrashlyticsFramework/Pods-CrashlyticsFramework-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-environment.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-CrashlyticsFramework/Pods-CrashlyticsFramework.xcconfig: -------------------------------------------------------------------------------- 1 | PODS_CRASHLYTICSFRAMEWORK_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PODS_ROOT)/CrashlyticsFramework" 2 | PODS_CRASHLYTICSFRAMEWORK_OTHER_LDFLAGS = -framework "Crashlytics" -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-environment.h: -------------------------------------------------------------------------------- 1 | 2 | // To check if a library is compiled with CocoaPods you 3 | // can use the `COCOAPODS` macro definition which is 4 | // defined in the xcconfigs so it is available in 5 | // headers also when they are imported in the client 6 | // project. 7 | 8 | 9 | // CocoaLumberjack 10 | #define COCOAPODS_POD_AVAILABLE_CocoaLumberjack 11 | #define COCOAPODS_VERSION_MAJOR_CocoaLumberjack 2 12 | #define COCOAPODS_VERSION_MINOR_CocoaLumberjack 0 13 | #define COCOAPODS_VERSION_PATCH_CocoaLumberjack 0 14 | 15 | // CocoaLumberjack/CLI 16 | #define COCOAPODS_POD_AVAILABLE_CocoaLumberjack_CLI 17 | #define COCOAPODS_VERSION_MAJOR_CocoaLumberjack_CLI 2 18 | #define COCOAPODS_VERSION_MINOR_CocoaLumberjack_CLI 0 19 | #define COCOAPODS_VERSION_PATCH_CocoaLumberjack_CLI 0 20 | 21 | // CocoaLumberjack/Core 22 | #define COCOAPODS_POD_AVAILABLE_CocoaLumberjack_Core 23 | #define COCOAPODS_VERSION_MAJOR_CocoaLumberjack_Core 2 24 | #define COCOAPODS_VERSION_MINOR_CocoaLumberjack_Core 0 25 | #define COCOAPODS_VERSION_PATCH_CocoaLumberjack_Core 0 26 | 27 | // CocoaLumberjack/Extensions 28 | #define COCOAPODS_POD_AVAILABLE_CocoaLumberjack_Extensions 29 | #define COCOAPODS_VERSION_MAJOR_CocoaLumberjack_Extensions 2 30 | #define COCOAPODS_VERSION_MINOR_CocoaLumberjack_Extensions 0 31 | #define COCOAPODS_VERSION_PATCH_CocoaLumberjack_Extensions 0 32 | 33 | // CrashlyticsFramework 34 | #define COCOAPODS_POD_AVAILABLE_CrashlyticsFramework 35 | #define COCOAPODS_VERSION_MAJOR_CrashlyticsFramework 2 36 | #define COCOAPODS_VERSION_MINOR_CrashlyticsFramework 2 37 | #define COCOAPODS_VERSION_PATCH_CrashlyticsFramework 5 38 | 39 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | install_resource() 10 | { 11 | case $1 in 12 | *.storyboard) 13 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 14 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 15 | ;; 16 | *.xib) 17 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 18 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 19 | ;; 20 | *.framework) 21 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 22 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 23 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 25 | ;; 26 | *.xcdatamodel) 27 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 28 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 29 | ;; 30 | *.xcdatamodeld) 31 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 32 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 33 | ;; 34 | *.xcassets) 35 | ;; 36 | /*) 37 | echo "$1" 38 | echo "$1" >> "$RESOURCES_TO_COPY" 39 | ;; 40 | *) 41 | echo "${PODS_ROOT}/$1" 42 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 43 | ;; 44 | esac 45 | } 46 | 47 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 48 | if [[ "${ACTION}" == "install" ]]; then 49 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 50 | fi 51 | rm -f "$RESOURCES_TO_COPY" 52 | 53 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ] 54 | then 55 | case "${TARGETED_DEVICE_FAMILY}" in 56 | 1,2) 57 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 58 | ;; 59 | 1) 60 | TARGET_DEVICE_ARGS="--target-device iphone" 61 | ;; 62 | 2) 63 | TARGET_DEVICE_ARGS="--target-device ipad" 64 | ;; 65 | *) 66 | TARGET_DEVICE_ARGS="--target-device mac" 67 | ;; 68 | esac 69 | find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 70 | fi 71 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PODS_ROOT)/CrashlyticsFramework" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/CrashlyticsFramework" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/CrashlyticsFramework" 5 | OTHER_LDFLAGS = -ObjC -l"Pods-CocoaLumberjack" -l"Pods-CrashlyticsFramework" -framework "Crashlytics" 6 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 7 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PODS_ROOT)/CrashlyticsFramework" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/CrashlyticsFramework" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/CrashlyticsFramework" 5 | OTHER_LDFLAGS = -ObjC -l"Pods-CocoaLumberjack" -l"Pods-CrashlyticsFramework" -framework "Crashlytics" 6 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 7 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JenkinsCI-iOS 2 | ============= 3 | 4 | A Jenkins job setup for your Xcode project. 5 | 6 | ## Contents:
7 | [Installing Jenkins](#installing-jenkins)
8 | [Xcode project setup](#xcode-project-setup)
9 | [Jenkins plugins](#jenkins-plugins)
10 | [Installing code metrics tools](#installing-code-metrics-tools)
11 | [Setting up the job](#setting-up-the-job)
12 | [Troubleshooting](#troubleshooting)
13 | 14 | ## Installing Jenkins 15 | 16 | Download Jenkins from here: https://www.jenkins.io/download/weekly/macos/
17 | I would recommend that the install should be made under the administrator user and not let the Jenkins installer create it's own user. That will generate issues when trying to access the keychain. 18 | 19 | To run Jenkins go to `/Applications/Jenkins` and run the `jenkins.war` file. Make sure you have the latest Java JDK installed. 20 | 21 | After that, you can access the Jenkins Dashboard using the following URL: [http://localhost:8080](http://localhost:8080) 22 | 23 | ## Xcode project setup 24 | 25 | First, go to your project target from the left top corner of Xcode, click on the target and select "Manage Schemes". 26 | There you should check the "Shared" option for your Xcode project (do not check shared for the Pods project).
27 | Target - > Manage schemes - > Check “Shared” 28 | 29 | Then, in the project's Build Settings turn on Generate Test Coverage Files and Instrument Program Flow for the Debug configuration on your main target and for both Debug an Release for your test target. 30 | 31 | To take advantage of the generated files you need to set the Build Products and Intermediates to be saved in a folder relative to the Workspace. You can do this by accessing Xcode Preferences -> Locations -> Custom -> Relative to Workspace. 32 | 33 | 34 | To check if everything it's OK you can build the project and check the following folders for .gcno and .gcda files 35 | `Build/Intermediates/YOUR-TEST-TARGET-NAME.build/Objects-normal/i386'` 36 | and 37 | `Build/Intermediates/YOUR-MAIN-TARGET-NAME.build/Objects-normal/i386'` 38 | You can find these based on the setting you have in Xcode for Locations. 39 | 40 | ## Jenkins plugins 41 | To setup you job, you will need the following plugins: 42 | 43 | Xcode plugin
44 | Git plugin
45 | Keychains and Provisioning Profiles Plugin
46 | Duplicate Code Scanner Plug-in
47 | Cobertura plugin
48 | SLOCCount Plugin
49 | EnvInject Plugin
50 | 51 | To add Jenkins plugins you must go to Jenkins -> Manage Jenkins -> Manage plugins. 52 | 53 | ## Installing code metrics tools 54 | ##### Install Homebrew 55 | To install Homebrew, simply copy-paste this code into your Terminal and press enter: 56 | 57 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 58 | 59 | ##### Installing sloccount:
`brew install sloccount` 60 | 61 | ##### Installing xctool:
`brew install xctool` 62 | 63 | ##### Installing pmd:
64 | You can download 4.3 from [here](http://sourceforge.net/projects/pmd/files/pmd/4.3/pmd-bin-4.3.zip/download). The latest versions have suffered major changes that aren't supported by the ObjectiveC language definition yet.
65 | To be able to make use of PMD you will also need to dowload the PMD Objective-C language definition from [here](https://github.com/jkennedy1980/Objective-C-CPD-Language/blob/master/releases/ObjCLanguage-0.0.7-SNAPSHOT.jar) - courtesy of Josh Kennedy. 66 | 67 | 68 | ##### Installing gcovr: 69 | ``` 70 | cd ~ 71 | git clone https://github.com/gcovr/gcovr.git 72 | sudo cp ./gcovr/scripts/gcovr /usr/local/bin 73 | sudo chown root:wheel /usr/local/bin/gcovr 74 | sudo chmod 755 /usr/local/bin/gcovr 75 | cd ~ 76 | rm -rf ./gcovr/ 77 | ``` 78 | 79 | 80 | ## Setting up the job 81 | 82 | Here comes the fun part: setting up the Jenkins job. 83 | The first step is creating the job: New item -> Freestyle project. This will let you do all the configuration of a job. 84 | 85 | #### Source Code Management 86 | Our project is usually stored in a Git or SVN repository. The Jenkins job begins with this step: cloning the latest version of your branch. 87 | You can setup this by adding your repository info & credentials in the Source Code Management section. For our job, we have a GitHub repostiory: https://github.com/cyupa/JenkinsCI-iOS.git and your GitHub credentials. Then you can specify the branch you want to clone and build, in this case: `*/master`. 88 | 89 | #### Build Environment 90 | A Jenkins job does not have access to environment variables such as PATH, that allows us the invoke different scripts and tools without specifing the full path to that script. This scripts are stored at different locations and this variable knows about those locations. 91 | 92 | You can check the PATH variableby opening a Terminal window and type `echo $PATH`.
93 | In my case: `/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Server.app/Contents/ServerRoot/usr/bin:/Applications/Server.app/Contents/ServerRoot/usr/sbin:/usr/local/Cellar/` 94 | 95 | Next, in the Build Environment section, we will add the line `PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Server.app/Contents/ServerRoot/usr/bin:/Applications/Server.app/Contents/ServerRoot/usr/sbin:/usr/local/Cellar/` in the Properties Content field. 96 | 97 | #### Running tests 98 | 99 | Before we go on, we should run our unit tests on our project, to make sure everything is OK. 100 | Add a new Execute Shell build step with the following code: 101 | ``` 102 | xctool -workspace ${WORKSPACE}/JenkinsCI.xcworkspace \ 103 | -scheme JenkinsCI \ 104 | -reporter plain \ 105 | -sdk iphonesimulator \ 106 | -reporter junit:test-reports/ios-report.xml \ 107 | test \ 108 | -resetSimulator \ 109 | -freshInstall 110 | ``` 111 | After this, add a Publish JUnit test results post build action to view the results of your test in your Dashboard. 112 | 113 | At this point you can take a step back and try to build the project to check if everything is ok. 114 | 115 | #### Compute code coverage 116 | 117 | Obtaining code coverage can be tricky. First, you must check that your Intermediates/{PROJECT NAME}.build/Debug-iphonesimulator/{PROJECT NAME}.build/Objects-normal/i386 contains .gcno and .gcda files. After that, running the following command via an Execute shell build step will generate the code coverage. 118 | 119 | ``` 120 | gcovr -r . --object-directory ${WORKSPACE}/Build/Intermediates/JenkinsCI.build/Debug-iphonesimulator/JenkinsCI.build/Objects-normal/i386 --exclude '.*Tests.*' --xml > ${WORKSPACE}/test-reports/ios-cobertura-coverage.xml 121 | ``` 122 | 123 | The results can be published by adding a "Publish Cobertura coverage report" as a post build step. 124 | 125 | #### Lines of code metric 126 | 127 | This one is quite simple: it runs a script to see the total lines of code in your project, modules and in each file. To take advantage of SLOCCount you must add a build step with an Execute shell script: 128 | ``` 129 | sloccount --duplicates --wide --details ${WORKSPACE}/JenkinsCI/Classes > ${WORKSPACE}/test-reports/ios-sloccount.sc 130 | ``` 131 | Then you can publish the results just by adding a Post build step: Publish SLOCCount analisys results and use the `test-reports/ios-sloccount.sc` output as a source. 132 | 133 | #### Duplicate code metric 134 | 135 | Now comes the tricky part: setting up the duplicate code metric. 136 | We'll be using PMD 4.2.6 because the ObjectiveC Language dictionary isn't up to date with the latest PMD versions. After you downloaded both (links posted up in the Read me file), you must use the full path to the files you compose your shell script. 137 | In my case I have dowloaded the files in `/usr/local/Cellar/pmd/`. In this case, the script will look something like this: 138 | 139 | ``` 140 | java -Xmx512m -classpath /usr/local/Cellar/pmd/4.3/lib/pmd-4.3.jar:/usr/local/Cellar/pmd/ObjCLanguage-0.0.7-SNAPSHOT.jar net.sourceforge.pmd.cpd.CPD \ 141 | --minimum-tokens 100 \ 142 | --files ${WORKSPACE}/JenkinsCI/Classes \ 143 | --language ObjectiveC \ 144 | --encoding UTF-8 \ 145 | --format net.sourceforge.pmd.cpd.XMLRenderer > ${WORKSPACE}/test-reports/ios-cpd-output.xml 146 | ``` 147 | 148 | If the `test-reports/ios-cpd-output.xml` is generated you can publish the results by adding a Publish duplicate code analisys results in the Post build section. 149 | 150 | #### Xcode build 151 | 152 | If everything is fine until this point, you can move on to the buil & distribute part of the job. 153 | Go on and add an Xcode build step. This plugin will invoke the xcodebuild command line tool and you can add all the build parameters here. Keep in mind that I'm using CocoaPods. 154 | 155 | In this case: 156 | * Target: JenkinsCI 157 | * Clean before build? YES 158 | * Generate Archive? YES 159 | * Pack application and build .ipa? YES 160 | * .ipa filename pattern: ${VERSION} 161 | * Output directory: ${workspace}/Builds/${BUILD_NUMBER}/${BUILD_ID} 162 | * Unlock Keychain? YES 163 | * Keychain path: ${HOME}/Library/Keychains/login.keychain 164 | * Keychain password: your administrator user password 165 | * Xcode Schema File: JenkinsCI 166 | * Xcode Workspace File: ${WORKSPACE}/JenkinsCI 167 | * Xcode Project Directory: ${WORKSPACE} 168 | * Xcode Project File: ${WORKSPACE}/JenkinsCI 169 | * Build output directory: ${WORKSPACE}/Build 170 | * Provide version number and run avgtool? YES 171 | * Technical version: ${BUILD_ID} 172 | 173 | 174 | After you configured this to your needs you should check if the job finishes successfully before moving on to the next step. 175 | 176 | #### Upload to Crashlytics 177 | 178 | The Crashlytics frameworks comes with a really nice tool to distribute your build to the testers, client and your team. To simply upload and notify your user groups about a new build you can add another Execute shell build step with the following command: 179 | ``` 180 | ${WORKSPACE}/Pods/CrashlyticsFramework/Crashlytics.framework/submit \ 181 | \ 182 | \ 183 | -ipaPath ${WORKSPACE}/builds/${BUILD_NUMBER}/${BUILD_ID}/${BUILD_ID}.ipa \ 184 | -groupAliases clients,developers,testers \ 185 | ``` 186 | 187 | 188 | If you would like to add some notes to your upload you could add a "Release notes extractios" step. You can do this by adding an Execute shell build step: 189 | ``` 190 | curl -s "http://localhost:8080/job/JenkinsCI/$BUILD_NUMBER/api/xml?wrapper=changes&xpath=//changeSet//comment" | sed -e "s/<\/comment>//g; s///g; s/<\/*changes\/*>//g" | sed '/^$/d;G' > ${WORKSPACE}/changelog.txt 191 | ``` 192 | This will extract the comments from your commits since the last build and put them into the changelog.txt file. Once you've done this, add the following option in your Crashlytics submission script: `-notesPath ${WORKSPACE}/changelog.txt \`. 193 | 194 | ## Troubleshooting 195 | 196 | ###### Homebrew dependencies 197 | If you encounter issues when running 'brew install sloccount' such as: 198 | `looking for OpenSSL headers 'openssl/md5.h'... Cannot find it. 199 | Please run this script as such: SSLINCPATH= ./configure` 200 | 201 | Install OpenSSL via Homebrew ('brew install openssl') and retry.
202 | If that doesn't work, go to /Library/Caches/Homebrew/, unpack the md5sha1sum archive, open it, and run the following command in the Terminal: SSLINCPATH=/usr/local/Cellar/openssl/1.0.1i/include ./configure. 203 | 204 | ###### Linker errors while building with Xcode 6 205 | If your build fails with a linker error in the Build step while trying to build and archive (for some reason xcodebuild tries to build the test scheme in the Archive configuration) for some class included in your test case, go to Build Settings and turn Symbols Hidden by Default to NO on your main target. 206 | --------------------------------------------------------------------------------