├── .DS_Store ├── README.md ├── _config.yml ├── iOS_APIParser.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── dhruvikrao.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── dro.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── dhruvikrao.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── iOS_APIParser.xcscheme │ │ └── xcschememanagement.plist │ └── dro.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── iOS_APIParser.xcscheme │ └── xcschememanagement.plist ├── iOS_APIParser ├── AppControllers │ ├── FeedVC.h │ └── FeedVC.m ├── AppDelegate.h ├── AppDelegate.m ├── AppModelClasses │ ├── FeedObject.h │ └── FeedObject.m ├── ApplicationAPI │ ├── APIConstants.h │ ├── APILogger │ │ ├── Controller │ │ │ ├── APILogDetailVC.h │ │ │ ├── APILogDetailVC.m │ │ │ ├── APILogsVC.h │ │ │ ├── APILogsVC.m │ │ │ ├── InternetConnectionStatusVC.h │ │ │ └── InternetConnectionStatusVC.m │ │ ├── Model │ │ │ ├── APIInfoObject.h │ │ │ ├── APIInfoObject.m │ │ │ ├── AppCacheManagement.h │ │ │ └── AppCacheManagement.m │ │ └── View │ │ │ ├── DeveloperInsights.storyboard │ │ │ └── InternetConnection.storyboard │ ├── APIParser+User.h │ ├── APIParser+User.m │ ├── APIParser.h │ ├── APIParser.m │ ├── AppMacros.h │ └── Reachability │ │ ├── Reachability.h │ │ └── Reachability.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── internet_reachability.imageset │ │ ├── Contents.json │ │ └── no-internet-connection-sign-of-phone-interface.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CategoryClasses │ └── NSString+ContainString.m ├── CustomCell │ ├── OrderSummaryCell.h │ ├── OrderSummaryCell.m │ ├── OrderSummaryVC.h │ └── OrderSummaryVC.m ├── Helper │ ├── UIViewController+Helper.h │ └── UIViewController+Helper.m ├── Info.plist ├── Objects │ ├── RechargePlanCommonObject.h │ ├── RechargePlanCommonObject.m │ ├── RechargePlansMainObject.h │ ├── RechargePlansMainObject.m │ ├── RechargeTurboObject.h │ └── RechargeTurboObject.m ├── iOS_APIParser-Prefix.pch └── main.m ├── iOS_APIParserTests ├── Info.plist └── iOS_APIParserTests.m └── iOS_APIParserUITests ├── Info.plist └── iOS_APIParserUITests.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhruvik13/iOS-Webservice/1b5d2f0a8152760e9f0b67be17cc8bcf81ef8648/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS-WebService 2 | 3 | This will helps you to integrate API (web service) communication architecture within your project, without any third party tool required. Easy to implement in project. 4 | 5 | ## Usage 6 | 7 | Here is a example of how to use this architecture to communicate with API server. 8 | 9 | ```objc 10 | APIParser *service = [APIParser sharedMediaServer]; //set your shared Instanse for calling an API 11 | 12 | [service URLRequestWithType:APIGetComments //specify your current calling API name 13 | parameters:@"" //pass request parameter as POST param orr GET param as per requirement 14 | cookieValue:nil //pass any cookie if required by the specific request 15 | customeobject:nil //pass any custom object as parameter if service required 16 | withRequestType:APIRequestMethodGET //define you request method 17 | withRequestHeaders:nil //pass anny additional header parameters if required by the server or request 18 | block:^(NSError *error, id objects, NSString *responseString, NSString *nextUrl, NSMutableArray *responseArray, NSURLResponse *URLResponseObject) { 19 | 20 | if (error) { 21 | 22 | //Handle Error 23 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[error domain] message:[NSString stringWithFormat:@"%@", error.localizedDescription] preferredStyle:UIAlertControllerStyleAlert]; 24 | 25 | UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; 26 | [alertController addAction:ok]; 27 | 28 | [self presentViewController:alertController animated:YES completion:nil]; 29 | } 30 | else { 31 | 32 | if (responseArray.count > 0) { 33 | 34 | //Handle Response Array 35 | if (self.commentArrayCount == nil) { 36 | self.commentArrayCount = [NSMutableArray new]; 37 | self.commentArrayCount = [responseArray mutableCopy]; 38 | } else { 39 | [self.commentArrayCount addObjectsFromArray:[responseArray copy]]; 40 | } 41 | 42 | [self.tableView reloadData]; 43 | } 44 | else { 45 | 46 | //Handle null response array 47 | } 48 | } 49 | }]; 50 | 51 | 52 | - Added support for NSINvocation 53 | - Enhancement for CacheManagement 54 | - Reachabilty support improved 55 | - Debug logs for API calling 56 | - Connection Lost UI added (Image source Google) 57 | - Call API from where connection lost (maintained with parameters) 58 | 59 | 60 | To enanble API Logs 61 | [[AppCacheManagement sharedCacheManager] setAPILoggingEnabled:true]; 62 | 63 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/project.xcworkspace/xcuserdata/dhruvikrao.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhruvik13/iOS-Webservice/1b5d2f0a8152760e9f0b67be17cc8bcf81ef8648/iOS_APIParser.xcodeproj/project.xcworkspace/xcuserdata/dhruvikrao.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/project.xcworkspace/xcuserdata/dro.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhruvik13/iOS-Webservice/1b5d2f0a8152760e9f0b67be17cc8bcf81ef8648/iOS_APIParser.xcodeproj/project.xcworkspace/xcuserdata/dro.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/xcuserdata/dhruvikrao.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/xcuserdata/dhruvikrao.xcuserdatad/xcschemes/iOS_APIParser.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/xcuserdata/dhruvikrao.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOS_APIParser.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 19428EA41BFA0B3300C135C8 16 | 17 | primary 18 | 19 | 20 | 19428EBD1BFA0B3500C135C8 21 | 22 | primary 23 | 24 | 25 | 19428EC81BFA0B3500C135C8 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/xcuserdata/dro.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/xcuserdata/dro.xcuserdatad/xcschemes/iOS_APIParser.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /iOS_APIParser.xcodeproj/xcuserdata/dro.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOS_APIParser.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 19428EA41BFA0B3300C135C8 16 | 17 | primary 18 | 19 | 20 | 19428EBD1BFA0B3500C135C8 21 | 22 | primary 23 | 24 | 25 | 19428EC81BFA0B3500C135C8 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /iOS_APIParser/AppControllers/FeedVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // FeedVC.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FeedVC : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /iOS_APIParser/AppControllers/FeedVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // FeedVC.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "FeedVC.h" 10 | #import "APIParser+User.h" 11 | #import "APILogsVC.h" 12 | #include 13 | 14 | @interface CommentCell : UITableViewCell 15 | 16 | @property (weak , nonatomic) IBOutlet UIImageView *imgProfileImage; 17 | @property (weak , nonatomic) IBOutlet UILabel *lblName; 18 | @property (weak , nonatomic) IBOutlet UILabel *lblEmail; 19 | @property (weak , nonatomic) IBOutlet UILabel *lblCommentDesc; 20 | 21 | @end 22 | 23 | @implementation CommentCell 24 | 25 | @synthesize imgProfileImage, lblName, lblEmail, lblCommentDesc; 26 | 27 | @end 28 | 29 | 30 | @interface FeedVC () 31 | 32 | @property (nonatomic, strong) NSMutableArray *commentArrayCount; 33 | 34 | @end 35 | 36 | @implementation FeedVC 37 | 38 | - (void)viewDidLoad { 39 | 40 | [super viewDidLoad]; 41 | [self getPostForUser:nil]; 42 | } 43 | 44 | - (void)didReceiveMemoryWarning { 45 | [super didReceiveMemoryWarning]; 46 | // Dispose of any resources that can be recreated. 47 | } 48 | 49 | #pragma mark - Sample web service calling 50 | 51 | - (IBAction) getPostForUser :(id)sender { 52 | if (sender) { // To check API method stack 53 | [self getposts]; 54 | [self getposts]; 55 | [self getposts]; 56 | } else { 57 | [self getposts]; 58 | } 59 | } 60 | 61 | 62 | //Sample API 63 | - (void)getposts { 64 | APIParser *service = [APIParser sharedMediaServer]; 65 | 66 | [service URLRequestWithType:APIGetComments 67 | parameters:nil 68 | cookieValue:nil 69 | customeobject:nil 70 | withRequestType:APIRequestMethodGET 71 | withRequestHeaders:nil 72 | block:^(NSError *error, id objects, NSString *responseString, NSString *nextUrl, NSMutableArray *responseArray, NSURLResponse *URLResponseObject) { 73 | 74 | if (error) { 75 | 76 | //Handle Error 77 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[error domain] message:[NSString stringWithFormat:@"%@", error.localizedDescription] preferredStyle:UIAlertControllerStyleAlert]; 78 | 79 | UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; 80 | [alertController addAction:ok]; 81 | 82 | [self presentViewController:alertController animated:YES completion:nil]; 83 | } 84 | else { 85 | 86 | if (responseArray.count > 0) { 87 | 88 | //Handle Response Array 89 | if (self.commentArrayCount == nil) { 90 | self.commentArrayCount = [NSMutableArray new]; 91 | self.commentArrayCount = [responseArray mutableCopy]; 92 | } else { 93 | [self.commentArrayCount addObjectsFromArray:[responseArray copy]]; 94 | } 95 | 96 | [self.tableView reloadData]; 97 | } 98 | else { 99 | 100 | //Handle null response array 101 | } 102 | } 103 | }]; 104 | } 105 | 106 | #pragma mark - Login API 107 | //Sample API 108 | -(IBAction)loginUser:(id)sender { 109 | 110 | APIParser *service = [APIParser sharedMediaServer]; 111 | 112 | NSDictionary *params = @{ 113 | @"uname":@"xyz@abc.com", 114 | @"password":[self MD5HashFor:@"654321"] 115 | }; 116 | 117 | NSString *urlWithQuerystring = [service serializeParams:params]; 118 | 119 | [service URLRequestWithType:APIUserLogIn 120 | parameters:urlWithQuerystring 121 | cookieValue:nil 122 | customeobject:nil 123 | withRequestType:APIRequestMethodPOST 124 | withRequestHeaders:nil 125 | block:^(NSError *error, id objects, NSString *responseString, NSString *nextUrl, NSMutableArray *responseArray, NSURLResponse *URLResponseObject) { 126 | 127 | if (error) { 128 | 129 | //Handle Error 130 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Failure!" message:[NSString stringWithFormat:@"%@", error.localizedDescription] preferredStyle:UIAlertControllerStyleAlert]; 131 | 132 | UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; 133 | [alertController addAction:ok]; 134 | 135 | [self presentViewController:alertController animated:YES completion:nil]; 136 | } 137 | else { 138 | 139 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Success! Login Response" message:[NSString stringWithFormat:@"%@", objects] preferredStyle:UIAlertControllerStyleAlert]; 140 | 141 | UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; 142 | [alertController addAction:ok]; 143 | 144 | [self presentViewController:alertController animated:YES completion:nil]; 145 | } 146 | }]; 147 | } 148 | 149 | #pragma mark - Table view data source 150 | 151 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 152 | return 1; 153 | } 154 | 155 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 156 | return self.commentArrayCount.count; 157 | } 158 | 159 | 160 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 161 | CommentCell *cell = (CommentCell *) [tableView dequeueReusableCellWithIdentifier:@"commentcell" forIndexPath:indexPath]; 162 | 163 | cell.lblName.text = [(NSDictionary *)self.commentArrayCount[indexPath.row] valueForKey:@"name"]; 164 | cell.lblEmail.text = [[(NSDictionary *)self.commentArrayCount[indexPath.row] valueForKey:@"email"] length] >= 20 ? [[(NSDictionary *)self.commentArrayCount[indexPath.row] valueForKey:@"email"] substringWithRange:NSMakeRange(0, 20)] : [(NSDictionary *)self.commentArrayCount[indexPath.row] valueForKey:@"email"]; 165 | cell.lblCommentDesc.text = [(NSDictionary *)self.commentArrayCount[indexPath.row] valueForKey:@"body"]; 166 | 167 | return cell; 168 | } 169 | 170 | 171 | -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{ 172 | return 40; 173 | } 174 | 175 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 176 | return UITableViewAutomaticDimension; 177 | } 178 | 179 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 180 | [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 181 | } 182 | 183 | 184 | #pragma mark - Navigate to API logs 185 | 186 | - (IBAction)navigateAPILog:(id)sender { 187 | APILogsVC *apiDetailVC = loadViewController(@"DeveloperInsights", @"idAPILogsVC"); 188 | [self.navigationController pushViewController:apiDetailVC animated:YES]; 189 | } 190 | 191 | - (NSString *) MD5HashFor:(NSString *)pass 192 | { 193 | const char *cStr = [pass UTF8String]; 194 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 195 | CC_MD5( cStr, (int)strlen(cStr), result ); 196 | return [NSString stringWithFormat: 197 | @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 198 | result[0], result[1], result[2], result[3], 199 | result[4], result[5], result[6], result[7], 200 | result[8], result[9], result[10], result[11], 201 | result[12], result[13], result[14], result[15] 202 | ]; 203 | } 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /iOS_APIParser/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Reachability.h" 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | #pragma mark - Check Host Reachability 17 | - (NetworkStatus) checkHostReachability; 18 | 19 | @property (nonatomic, strong) Reachability *hostReachability; 20 | 21 | @property (nonatomic, strong) UINavigationController *appNavigationController; 22 | 23 | - (UIViewController*) topMostController; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /iOS_APIParser/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "AppCacheManagement.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | 22 | //Start Logging API request / response 23 | [[AppCacheManagement sharedCacheManager] setAPILoggingEnabled:true]; 24 | 25 | return YES; 26 | } 27 | 28 | - (void)applicationWillResignActive:(UIApplication *)application { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application { 34 | // 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. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | - (void)applicationWillEnterForeground:(UIApplication *)application { 39 | // 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. 40 | } 41 | 42 | - (void)applicationDidBecomeActive:(UIApplication *)application { 43 | // 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. 44 | } 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | #pragma mark - Check Host Reachability 51 | 52 | - (NetworkStatus) checkHostReachability { 53 | self.hostReachability = [Reachability reachabilityForInternetConnection]; 54 | return self.hostReachability.currentReachabilityStatus; 55 | } 56 | 57 | - (UIViewController*) topMostController 58 | { 59 | UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; 60 | 61 | while (topController.presentedViewController) { 62 | topController = topController.presentedViewController; 63 | } 64 | 65 | return topController; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /iOS_APIParser/AppModelClasses/FeedObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // FeedObject.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FeedObject : NSObject 12 | 13 | @property (nonatomic, strong) NSString *email; 14 | @property (nonatomic, assign) double internalBaseClassIdentifier; 15 | @property (nonatomic, assign) double postId; 16 | @property (nonatomic, strong) NSString *body; 17 | @property (nonatomic, strong) NSString *name; 18 | 19 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 20 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 21 | - (NSDictionary *)dictionaryRepresentation; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /iOS_APIParser/AppModelClasses/FeedObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // FeedObject.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "FeedObject.h" 10 | 11 | NSString *const kBaseClassEmail = @"email"; 12 | NSString *const kBaseClassId = @"id"; 13 | NSString *const kBaseClassPostId = @"postId"; 14 | NSString *const kBaseClassBody = @"body"; 15 | NSString *const kBaseClassName = @"name"; 16 | 17 | @interface FeedObject () 18 | 19 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 20 | 21 | @end 22 | 23 | @implementation FeedObject 24 | 25 | @synthesize email = _email; 26 | @synthesize internalBaseClassIdentifier = _internalBaseClassIdentifier; 27 | @synthesize postId = _postId; 28 | @synthesize body = _body; 29 | @synthesize name = _name; 30 | 31 | 32 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict { 33 | return [[self alloc] initWithDictionary:dict]; 34 | } 35 | 36 | - (instancetype)initWithDictionary:(NSDictionary *)dict { 37 | self = [super init]; 38 | 39 | // This check serves to make sure that a non-NSDictionary object 40 | // passed into the model class doesn't break the parsing. 41 | if (self && [dict isKindOfClass:[NSDictionary class]]) { 42 | self.email = [self objectOrNilForKey:kBaseClassEmail fromDictionary:dict]; 43 | self.internalBaseClassIdentifier = [[self objectOrNilForKey:kBaseClassId fromDictionary:dict] doubleValue]; 44 | self.postId = [[self objectOrNilForKey:kBaseClassPostId fromDictionary:dict] doubleValue]; 45 | self.body = [self objectOrNilForKey:kBaseClassBody fromDictionary:dict]; 46 | self.name = [self objectOrNilForKey:kBaseClassName fromDictionary:dict]; 47 | } 48 | 49 | return self; 50 | 51 | } 52 | 53 | - (NSDictionary *)dictionaryRepresentation { 54 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 55 | [mutableDict setValue:self.email forKey:kBaseClassEmail]; 56 | [mutableDict setValue:[NSNumber numberWithDouble:self.internalBaseClassIdentifier] forKey:kBaseClassId]; 57 | [mutableDict setValue:[NSNumber numberWithDouble:self.postId] forKey:kBaseClassPostId]; 58 | [mutableDict setValue:self.body forKey:kBaseClassBody]; 59 | [mutableDict setValue:self.name forKey:kBaseClassName]; 60 | 61 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 62 | } 63 | 64 | - (NSString *)description { 65 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 66 | } 67 | 68 | #pragma mark - Helper Method 69 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict { 70 | id object = [dict objectForKey:aKey]; 71 | return [object isEqual:[NSNull null]] ? nil : object; 72 | } 73 | 74 | 75 | #pragma mark - NSCoding Methods 76 | 77 | - (id)initWithCoder:(NSCoder *)aDecoder { 78 | self = [super init]; 79 | 80 | self.email = [aDecoder decodeObjectForKey:kBaseClassEmail]; 81 | self.internalBaseClassIdentifier = [aDecoder decodeDoubleForKey:kBaseClassId]; 82 | self.postId = [aDecoder decodeDoubleForKey:kBaseClassPostId]; 83 | self.body = [aDecoder decodeObjectForKey:kBaseClassBody]; 84 | self.name = [aDecoder decodeObjectForKey:kBaseClassName]; 85 | return self; 86 | } 87 | 88 | - (void)encodeWithCoder:(NSCoder *)aCoder 89 | { 90 | [aCoder encodeObject:_email forKey:kBaseClassEmail]; 91 | [aCoder encodeDouble:_internalBaseClassIdentifier forKey:kBaseClassId]; 92 | [aCoder encodeDouble:_postId forKey:kBaseClassPostId]; 93 | [aCoder encodeObject:_body forKey:kBaseClassBody]; 94 | [aCoder encodeObject:_name forKey:kBaseClassName]; 95 | } 96 | 97 | - (id)copyWithZone:(NSZone *)zone { 98 | FeedObject *copy = [[FeedObject alloc] init]; 99 | 100 | if (copy) { 101 | 102 | copy.email = [self.email copyWithZone:zone]; 103 | copy.internalBaseClassIdentifier = self.internalBaseClassIdentifier; 104 | copy.postId = self.postId; 105 | copy.body = [self.body copyWithZone:zone]; 106 | copy.name = [self.name copyWithZone:zone]; 107 | } 108 | 109 | return copy; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APIConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // APIConstants.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #ifndef iOS_APIParser_APIConstants_h 10 | #define iOS_APIParser_APIConstants_h 11 | 12 | #define DEFAULT_TIMEOUT 120000.0f 13 | 14 | #define ServerPath "https://jsonplaceholder.typicode.com" 15 | 16 | #pragma mark - Test 17 | 18 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000 19 | 20 | #define SCREEN_WIDTH ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIApplication sharedApplication].keyWindow bounds].size.width : [[UIApplication sharedApplication].keyWindow bounds].size.height) 21 | 22 | #define SCREEN_HEIGHT ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIApplication sharedApplication].keyWindow bounds].size.height : [[UIApplication sharedApplication].keyWindow bounds].size.width) 23 | 24 | #else 25 | 26 | #define SCREEN_WIDTH ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) 27 | 28 | #define SCREEN_HEIGHT ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) 29 | 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Controller/APILogDetailVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // APILogDetailVC.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "APIInfoObject.h" 11 | 12 | @interface APILogDetailVC : UITableViewController 13 | 14 | @property (nonatomic, strong) APIInfoObject *selectedAPIForDetail; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Controller/APILogDetailVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // APILogDetailVC.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "APILogDetailVC.h" 10 | 11 | @interface APILogDetailVC () 12 | { 13 | __weak IBOutlet UILabel *lblRequestURL; 14 | __weak IBOutlet UILabel *lblRequestParameters; 15 | __weak IBOutlet UILabel *lblRequestHeaders; 16 | 17 | __weak IBOutlet UITextView *txtURLResponse; 18 | __weak IBOutlet UILabel *lblResponseHeader; 19 | 20 | __weak IBOutlet UISegmentedControl *responseDisplaySegmentControl; 21 | } 22 | @end 23 | 24 | @implementation APILogDetailVC 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | self.title = [NSString stringWithFormat:@"%@ : Status (%ld) ",self.selectedAPIForDetail.APITitle, (long)((NSHTTPURLResponse *)self.selectedAPIForDetail.APIResponce).statusCode]; 30 | 31 | lblRequestURL.text = self.selectedAPIForDetail.APIRequest.URL.absoluteString; 32 | lblRequestHeaders.text = [NSString stringWithFormat:@"%@",self.selectedAPIForDetail.APIRequest.allHTTPHeaderFields]; 33 | lblRequestParameters.text = [[[NSString alloc] initWithData:[self.selectedAPIForDetail.APIRequest HTTPBody] encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"&" withString:@"\n"]; 34 | 35 | txtURLResponse.scrollEnabled = NO; 36 | 37 | // txtURLResponse.text = (self.selectedAPIForDetail.responseDictionary) ? [NSString stringWithFormat:@"%@", self.selectedAPIForDetail.responseDictionary] : (self.selectedAPIForDetail.responseString.length>0) ? self.selectedAPIForDetail.responseString : @""; 38 | 39 | txtURLResponse.text = self.selectedAPIForDetail.responseString; 40 | 41 | [txtURLResponse layoutSubviews]; 42 | 43 | [txtURLResponse resignFirstResponder]; 44 | [txtURLResponse becomeFirstResponder]; 45 | 46 | [self.tableView reloadData]; 47 | 48 | [self.tableView beginUpdates]; 49 | [self.tableView endUpdates]; 50 | 51 | [responseDisplaySegmentControl addTarget:self 52 | action:@selector(responseDisplaySegmentChanged:) 53 | forControlEvents:UIControlEventValueChanged]; 54 | } 55 | 56 | - (void)didReceiveMemoryWarning { 57 | [super didReceiveMemoryWarning]; 58 | } 59 | 60 | #pragma mark - Table view data source 61 | 62 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 63 | return 2; 64 | } 65 | 66 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 67 | return (section ==0) ? 3: 1; 68 | } 69 | 70 | -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{ 71 | return 46; 72 | } 73 | 74 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 75 | return UITableViewAutomaticDimension; 76 | } 77 | 78 | #pragma mark - Response Display Segment changed 79 | 80 | - (void)responseDisplaySegmentChanged:(id)sender { 81 | switch (responseDisplaySegmentControl.selectedSegmentIndex) { 82 | case 0: //RAW Response 83 | { 84 | txtURLResponse.text = self.selectedAPIForDetail.responseString; 85 | } 86 | break; 87 | case 1: //FORMATTED Response 88 | { 89 | txtURLResponse.text = [NSString stringWithFormat:@"%@", self.selectedAPIForDetail.responseDictionary]; 90 | } 91 | break; 92 | default: 93 | break; 94 | } 95 | [self.tableView reloadData]; 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Controller/APILogsVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // APILogsVC.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface APIDetailCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *lblStatusIndicator; 14 | @property (weak, nonatomic) IBOutlet UILabel *lblAPITitle; 15 | @property (weak, nonatomic) IBOutlet UILabel *lblAPIURL; 16 | @property (weak, nonatomic) IBOutlet UIButton *btnStatusCode; 17 | 18 | @end 19 | 20 | @interface APILogsVC : UITableViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Controller/APILogsVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // APILogsVC.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "APILogsVC.h" 10 | #import "AppCacheManagement.h" 11 | #import "APIInfoObject.h" 12 | #import "APILogDetailVC.h" 13 | #import "APIParser.h" 14 | 15 | @implementation APIDetailCell 16 | 17 | @end 18 | 19 | 20 | @interface APILogsVC () 21 | 22 | @property (nonatomic, strong) NSMutableArray *APIDetailArray; 23 | 24 | @end 25 | 26 | @implementation APILogsVC 27 | 28 | - (void)viewDidLoad { 29 | [super viewDidLoad]; 30 | 31 | self.tableView.showsVerticalScrollIndicator = false; 32 | 33 | self.title = @"API Logs"; 34 | 35 | [[AppCacheManagement sharedCacheManager] getcachedataArrayFor_:kDeveloperDebugAPILog myMethod:^(BOOL status, NSMutableArray *retrivedArray) { 36 | 37 | if (retrivedArray != nil) { 38 | 39 | _APIDetailArray = [[[retrivedArray reverseObjectEnumerator] allObjects] mutableCopy]; 40 | 41 | [self.tableView reloadData]; 42 | 43 | [self.tableView beginUpdates]; 44 | [self.tableView endUpdates]; 45 | } 46 | }]; 47 | } 48 | 49 | - (void)didReceiveMemoryWarning { 50 | [super didReceiveMemoryWarning]; 51 | } 52 | 53 | #pragma mark - Table view data source 54 | 55 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 56 | return 1; 57 | } 58 | 59 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 60 | return _APIDetailArray.count; 61 | } 62 | 63 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 64 | APIDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:@"APICell" forIndexPath:indexPath]; 65 | 66 | APIInfoObject *apiDetail = (APIInfoObject *) [_APIDetailArray objectAtIndex:indexPath.row]; 67 | 68 | if (((NSHTTPURLResponse *)apiDetail.APIResponce).statusCode == 200) { 69 | cell.lblStatusIndicator.backgroundColor = RGBCOLOR(10, 168, 50, 1.0); 70 | } else { 71 | cell.lblStatusIndicator.backgroundColor = RGBCOLOR(255, 0, 28, 1.0); 72 | } 73 | 74 | [cell.btnStatusCode setTitle:[NSString stringWithFormat:@"%ld", (long)((NSHTTPURLResponse *)apiDetail.APIResponce).statusCode] forState:UIControlStateNormal]; 75 | 76 | cell.lblAPITitle.text = apiDetail.APITitle; 77 | 78 | cell.lblAPIURL.text = apiDetail.APIRequest.URL.absoluteString; 79 | 80 | return cell; 81 | } 82 | 83 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 84 | { 85 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 86 | 87 | APILogDetailVC *APIDetail = loadViewController(@"DeveloperInsights", @"idAPILogDetailVC"); 88 | APIDetail.selectedAPIForDetail = (APIInfoObject *) [_APIDetailArray objectAtIndex:indexPath.row]; 89 | [self.navigationController pushViewController:APIDetail animated:YES]; 90 | } 91 | 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Controller/InternetConnectionStatusVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // InternetConnectionStatusVC.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface InternetConnectionStatusVC : UIViewController 12 | 13 | typedef void (^NetworkCompletion)(InternetConnectionStatusVC *); 14 | 15 | @property (nonatomic, readwrite) NSString *headerMessage; 16 | @property (nonatomic, readwrite) NSString *descriptionMessage; 17 | 18 | //Parent View Controller 19 | @property (nonatomic, strong) UIViewController *parentVC; 20 | 21 | //Completion block 22 | @property (nonatomic,copy) NetworkCompletion completionBlock; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Controller/InternetConnectionStatusVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // InternetConnectionStatusVC.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "InternetConnectionStatusVC.h" 10 | #import "UIViewController+Helper.h" 11 | 12 | @interface InternetConnectionStatusVC () 13 | { 14 | IBOutlet UILabel *lblInternetStatusHeader; 15 | IBOutlet UILabel *lblInternetStatusDescription; 16 | IBOutlet UIImageView *imgInternetStatus; 17 | IBOutlet UIButton *btnTryAgain; 18 | } 19 | @end 20 | 21 | @implementation InternetConnectionStatusVC 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | self.title = @"Newtwork Issue!"; 27 | 28 | [self.navigationController.navigationBar setTitleTextAttributes:@{ 29 | NSForegroundColorAttributeName : RGBCOLOR(49, 146, 181, 1.0), 30 | NSFontAttributeName : [UIFont systemFontOfSize:20.0] 31 | }]; 32 | 33 | //Add Right bar button 34 | UIButton *btnRight = [UIButton buttonWithType:UIButtonTypeSystem]; 35 | [btnRight setFrame:CGRectMake(0, 0, 40, 40)]; 36 | [btnRight setTintColor:[UIColor whiteColor]]; 37 | [btnRight setImage:[UIImage imageNamed:@"close_navigationbar"] forState:UIControlStateNormal]; 38 | [btnRight addTarget:self action:@selector(closeConnectivityView:) forControlEvents:UIControlEventTouchUpInside]; 39 | 40 | [btnRight setContentHorizontalAlignment:UIControlContentHorizontalAlignmentRight]; 41 | 42 | btnRight.imageView.contentMode = UIViewContentModeScaleAspectFit; 43 | btnRight.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; 44 | btnRight.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; 45 | 46 | UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:btnRight]; 47 | [rightBarButton setTintColor:[UIColor whiteColor]]; 48 | // self.navigationItem.rightBarButtonItem = rightBarButton; 49 | } 50 | 51 | - (void) viewWillAppear:(BOOL)animated 52 | { 53 | [super viewWillAppear:animated]; 54 | } 55 | 56 | -(UIBarPosition)positionForBar:(id)bar { 57 | return UIBarPositionTopAttached; 58 | } 59 | 60 | - (void)didReceiveMemoryWarning { 61 | [super didReceiveMemoryWarning]; 62 | // Dispose of any resources that can be recreated. 63 | } 64 | 65 | #pragma mark - Close presented View 66 | 67 | - (IBAction)closeConnectivityView:(id)sender { 68 | 69 | [self dismissViewControllerAnimated:YES completion:^{ 70 | 71 | }]; 72 | } 73 | 74 | #pragma mark - Try Again Click 75 | 76 | - (IBAction)retryClicked:(id)sender { 77 | 78 | UIButton *btnSender = (UIButton *)sender; 79 | 80 | UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 81 | indicator.tag = 200; 82 | indicator.tintColor = [UIColor whiteColor]; 83 | CGFloat halfButtonHeight = btnSender.bounds.size.height / 2; 84 | CGFloat buttonWidth = btnSender.bounds.size.width; 85 | indicator.center = CGPointMake(buttonWidth - halfButtonHeight , halfButtonHeight); 86 | indicator.hidesWhenStopped = YES; 87 | [btnSender addSubview:indicator]; 88 | [indicator startAnimating]; 89 | 90 | [btnTryAgain setEnabled:NO]; 91 | 92 | [self checkHostReachabilityWithIndicator:indicator]; 93 | } 94 | 95 | 96 | - (void) checkHostReachabilityWithIndicator :(UIActivityIndicatorView*)indicator { 97 | 98 | NetworkStatus currentStatus = [APP_CONTEXT checkHostReachability]; 99 | 100 | switch (currentStatus) { 101 | case NotReachable: 102 | { 103 | __weak UIActivityIndicatorView *weakindicator = indicator; 104 | 105 | [self _shake:7 direction:1 currentTimes:0 withDelta:2 speed:0.06 shakeDirection:ShakeDirectionHorizontal forView:btnTryAgain completion:^{ 106 | 107 | [weakindicator stopAnimating]; 108 | [weakindicator removeFromSuperview]; 109 | 110 | [btnTryAgain setEnabled:YES]; 111 | }]; 112 | } 113 | break; 114 | case ReachableViaWiFi: 115 | case ReachableViaWWAN: 116 | { 117 | [self dismissViewControllerAnimated:YES completion:^{ 118 | 119 | if (self.completionBlock) { 120 | self.completionBlock(self); 121 | } 122 | }]; 123 | 124 | } 125 | } 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Model/APIInfoObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // APIInfoObject.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface APIInfoObject : NSObject 12 | 13 | @property (nonatomic, strong) NSString *APITitle; 14 | 15 | @property (nonatomic, strong) NSURLRequest *APIRequest; 16 | 17 | @property (nonatomic, strong) NSURLResponse *APIResponce; 18 | 19 | @property (nonatomic, strong) NSDictionary *responseDictionary; 20 | 21 | @property (nonatomic, strong) NSString *responseString; 22 | 23 | + (instancetype)modelObjectWithDetails:(NSString *)apiTitle request:(NSURLRequest *)apiRequest response:(NSURLResponse *)apiResponse responseDictionary:(NSDictionary *)responseDict responseString:(NSString *)responseString; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Model/APIInfoObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // APIInfoObject.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "APIInfoObject.h" 10 | 11 | @implementation APIInfoObject 12 | 13 | + (instancetype)modelObjectWithDetails:(NSString *)apiTitle request:(NSURLRequest *)apiRequest response:(NSURLResponse *)apiResponse responseDictionary:(NSDictionary *)responseDict responseString:(NSString *)responseString 14 | { 15 | return [[self alloc] initWithDetail:apiTitle request:apiRequest response:apiResponse responseDictionary:responseDict responseString:responseString]; 16 | } 17 | 18 | - (instancetype)initWithDetail:(NSString *)apiTitle request:(NSURLRequest *)apiRequest response:(NSURLResponse *)apiResponse responseDictionary:(NSDictionary *)responseDict responseString:(NSString *)responseString 19 | { 20 | self = [super init]; 21 | 22 | self.APITitle = apiTitle; 23 | self.APIRequest = apiRequest; 24 | self.APIResponce = apiResponse; 25 | self.responseDictionary = responseDict; 26 | self.responseString = responseString; 27 | 28 | return self; 29 | } 30 | 31 | #pragma mark - NSCoding Methods 32 | 33 | - (id)initWithCoder:(NSCoder *)aDecoder 34 | { 35 | self = [super init]; 36 | 37 | self.APITitle = [aDecoder decodeObjectForKey:@"Title"]; 38 | self.APIRequest = [aDecoder decodeObjectForKey:@"Request"]; 39 | self.APIResponce = [aDecoder decodeObjectForKey:@"Response"]; 40 | self.responseDictionary = [aDecoder decodeObjectForKey:@"ResponseDictionary"]; 41 | self.responseString = [aDecoder decodeObjectForKey:@"ResponseString"]; 42 | 43 | return self; 44 | } 45 | 46 | - (void)encodeWithCoder:(NSCoder *)aCoder 47 | { 48 | [aCoder encodeObject:_APITitle forKey:@"Title"]; 49 | [aCoder encodeObject:_APIRequest forKey:@"Request"]; 50 | [aCoder encodeObject:_APIResponce forKey:@"Response"]; 51 | [aCoder encodeObject:_responseDictionary forKey:@"ResponseDictionary"]; 52 | [aCoder encodeObject:_responseString forKey:@"ResponseString"]; 53 | } 54 | 55 | - (id)copyWithZone:(NSZone *)zone 56 | { 57 | APIInfoObject *copy = [[APIInfoObject alloc] init]; 58 | 59 | if (copy) { 60 | 61 | copy.APITitle = [self.APITitle copyWithZone:zone]; 62 | copy.APIRequest = [self.APIRequest copyWithZone:zone]; 63 | copy.APIResponce = [self.APIResponce copyWithZone:zone]; 64 | copy.responseDictionary = [self.responseDictionary copyWithZone:zone]; 65 | copy.responseString = [self.responseString copyWithZone:zone]; 66 | } 67 | 68 | return copy; 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Model/AppCacheManagement.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppCacheManagement.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | static NSString* kDeveloperDebugAPILog = @"DeveloperDebugAPILog"; 12 | 13 | static int kConstMaxDebugAPICount = 50; 14 | 15 | typedef void(^cacheArrayGetCompletion)(BOOL status, NSMutableArray* retrivedArray); 16 | 17 | typedef void(^cacheObjectGetCompletion)(BOOL status, id obj); 18 | 19 | @interface AppCacheManagement : NSObject 20 | 21 | 22 | + (id)sharedCacheManager; 23 | 24 | #pragma mark - Enable / Disable API Logger 25 | 26 | - (BOOL)APILoggingEnabled; 27 | - (void)setAPILoggingEnabled:(BOOL)value; 28 | 29 | 30 | #pragma mark - Cache Saving mechanisam 31 | - (void)setCacheToUserDefaults:(NSMutableArray *)resPonseArrayList ForKey:(NSString *)strKey ; 32 | - (void)getcachedataArrayFor_:(NSString *)strKey myMethod:(cacheArrayGetCompletion) compblock ; 33 | - (void)removeCacheForKey:(NSString *)objectKey ; 34 | 35 | 36 | #pragma mark - Object 37 | - (void)setObjectCacheToUserDefaults:(id)resPonseObject ForKey:(NSString *)strKey ; 38 | - (void)getObjectCachedataFor_:(NSString *)strKey myMethod:(cacheObjectGetCompletion) compblock; 39 | 40 | 41 | #pragma mark - Remove all cache fro Current User 42 | - (void) removeAllAPICachedObjects ; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/Model/AppCacheManagement.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppCacheManagement.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "AppCacheManagement.h" 10 | 11 | static BOOL APILoggingEnabled; 12 | 13 | @implementation AppCacheManagement 14 | 15 | #pragma mark Singleton Methods 16 | 17 | + (id)sharedCacheManager { 18 | static AppCacheManagement *sharedCacheManager = nil; 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | sharedCacheManager = [[self alloc] init]; 22 | }); 23 | return sharedCacheManager; 24 | } 25 | 26 | 27 | #pragma mark - Enable / Disable API Logger 28 | 29 | - (BOOL)APILoggingEnabled { 30 | return APILoggingEnabled; 31 | } 32 | 33 | - (void)setAPILoggingEnabled:(BOOL)value { 34 | APILoggingEnabled = value; 35 | } 36 | 37 | #pragma mark - Cache Saving mechanisam 38 | 39 | - (void)setCacheToUserDefaults:(NSMutableArray *)resPonseArrayList ForKey:(NSString *)strKey 40 | { 41 | @autoreleasepool 42 | { 43 | [self setCustomObject:resPonseArrayList forKey:strKey]; 44 | resPonseArrayList = nil; 45 | } 46 | } 47 | 48 | - (void)getcachedataArrayFor_:(NSString *)strKey 49 | myMethod:(cacheArrayGetCompletion) compblock 50 | { 51 | @autoreleasepool 52 | { 53 | NSMutableArray *retrivedCacheData = [[NSMutableArray alloc] init]; 54 | [retrivedCacheData addObjectsFromArray:[self customObjectForKey:strKey]]; 55 | 56 | compblock(YES, retrivedCacheData); 57 | } 58 | } 59 | 60 | #pragma mark - object 61 | - (void)setObjectCacheToUserDefaults:(id)resPonseObject ForKey:(NSString *)strKey 62 | { 63 | @autoreleasepool 64 | { 65 | [self setCustomObject:resPonseObject forKey:strKey]; 66 | resPonseObject = nil; 67 | } 68 | } 69 | 70 | - (void) getObjectCachedataFor_:(NSString *)strKey 71 | myMethod:(cacheObjectGetCompletion) compblock 72 | { 73 | @autoreleasepool 74 | { 75 | id retrivedObject; 76 | retrivedObject = [self customObjectForKey:strKey]; 77 | 78 | compblock(YES, retrivedObject); 79 | } 80 | } 81 | 82 | #pragma mark - Remove key 83 | 84 | - (void)removeCacheForKey:(NSString *)objectKey 85 | { 86 | @autoreleasepool 87 | { 88 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:objectKey]; 89 | [[NSUserDefaults standardUserDefaults] synchronize]; 90 | } 91 | } 92 | 93 | #pragma mark - Remove all cache fro Current User 94 | - (void) removeAllAPICachedObjects 95 | { 96 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kDeveloperDebugAPILog]; 97 | [[NSUserDefaults standardUserDefaults] synchronize]; 98 | } 99 | 100 | #pragma mark - Encode Array of objects or object 101 | 102 | - (id)customObjectForKey:(NSString *)key { 103 | 104 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 105 | NSData *encodedObject = [defaults objectForKey:key]; 106 | id obj = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject]; 107 | return obj; 108 | } 109 | 110 | - (void)setCustomObject:(id)obj forKey:(NSString *)key { 111 | if ([obj respondsToSelector:@selector(encodeWithCoder:)] == NO) { 112 | return; 113 | } 114 | NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:obj]; 115 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 116 | [defaults setObject:encodedObject forKey:key]; 117 | [defaults synchronize]; 118 | } 119 | 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/View/DeveloperInsights.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | SourceSansPro-Black 15 | 16 | 17 | SourceSansPro-Light 18 | 19 | 20 | SourceSansPro-Semibold 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 51 | 57 | 66 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 180 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 214 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APILogger/View/InternetConnection.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | SourceSansPro-Regular 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 77 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APIParser+User.h: -------------------------------------------------------------------------------- 1 | // 2 | // APIParser+User.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 17/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "APIParser.h" 10 | 11 | @interface APIParser (User) 12 | 13 | typedef enum 14 | { 15 | APIUserLogIn, 16 | APIGetComments 17 | } APIType; 18 | 19 | - (void)URLRequestWithType:(APIType)serviceName 20 | parameters:(NSString *)parameters 21 | cookieValue:(NSMutableArray *)cookies 22 | customeobject:(id)object 23 | withRequestType:(APIRequestType) requestType 24 | withRequestHeaders:(NSDictionary *) headerDictionaries 25 | block:(ResponseBlock)block; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APIParser+User.m: -------------------------------------------------------------------------------- 1 | // 2 | // APIParser+User.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 17/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "APIParser+User.h" 10 | #import "FeedObject.h" 11 | 12 | @implementation APIParser (User) 13 | 14 | - (void)URLRequestWithType:(APIType)serviceName 15 | parameters:(NSString *)parameters 16 | cookieValue:(NSMutableArray *)cookies 17 | customeobject:(id)object 18 | withRequestType:(APIRequestType) requestType 19 | withRequestHeaders:(NSDictionary *) headerDictionaries 20 | block:(ResponseBlock)block 21 | { 22 | //Check Internet Connectivity 23 | NetworkStatus currentStatus = [APP_CONTEXT checkHostReachability]; 24 | 25 | switch (currentStatus) { 26 | case ReachableViaWiFi: 27 | case ReachableViaWWAN: 28 | { 29 | NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 30 | 31 | NSString *URLString; 32 | NSData *jsonData; 33 | NSString *nextStartRecord; 34 | 35 | NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; 36 | NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject]; 37 | NSURLSessionDataTask * dataTask; 38 | 39 | switch (serviceName) 40 | { 41 | case APIUserLogIn: 42 | { 43 | URLString = @""; 44 | } 45 | break; 46 | case APIGetComments: 47 | { 48 | URLString = [NSString stringWithFormat:@"%s/posts/1/comments", ServerPath]; 49 | } 50 | break; 51 | default: 52 | break; 53 | } 54 | 55 | NSMutableURLRequest *request; 56 | 57 | if (object == nil) { 58 | 59 | jsonData = [parameters dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 60 | request = [self urlRequestForURL:[NSURL URLWithString:URLString] withObjects:jsonData withReqCookies:cookies isObject:NO withParameters:parameters reqType:requestType reqHeaders:headerDictionaries]; 61 | } 62 | else { 63 | 64 | jsonData = [self dictionaryWithPropertiesOfObject:object]; 65 | request = [self urlRequestForURL:[NSURL URLWithString:URLString] withObjects:jsonData withReqCookies:cookies isObject:YES withParameters:parameters reqType:requestType reqHeaders:headerDictionaries]; 66 | } 67 | 68 | __block id Responceobjects = nil; 69 | 70 | runOnMainQueueWithoutDeadlocking(^{ 71 | ShowNetworkIndicator(1); 72 | }); 73 | 74 | dataTask = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { 75 | { 76 | if (((NSHTTPURLResponse *)response).statusCode == 401) { 77 | 78 | error = [NSError errorWithDomain:@"Session time out" code:401 userInfo:nil]; 79 | 80 | runOnMainQueueWithoutDeadlocking(^{ 81 | //Show Alert for Session Time Out. 82 | }); 83 | 84 | NSString *responseString; 85 | 86 | NSDictionary *jsonDict; 87 | 88 | if (data) { 89 | responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 90 | 91 | jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 92 | } 93 | 94 | NSMutableArray *responceDataArray; 95 | 96 | //API cache Logger 97 | [self saveAPIDetailsToCacheForRequestTitle:[[NSURL URLWithString:URLString] lastPathComponent] 98 | andResponse:response 99 | andRequest:request 100 | responseDictionary:(jsonDict) ? : nil 101 | responseString:(responseString) ? : @""]; 102 | 103 | 104 | dispatch_async(dispatch_get_main_queue(), ^(){ 105 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 106 | if ( error ) 107 | { 108 | ShowNetworkIndicator(0); 109 | block(error,Responceobjects,responseString, nil, responceDataArray, response); 110 | } 111 | else 112 | { 113 | ShowNetworkIndicator(0); 114 | block(error,Responceobjects,responseString, nextStartRecord, responceDataArray, response); 115 | } 116 | }]; 117 | }); 118 | } 119 | else if(error != nil) 120 | { 121 | NSString *responseString; 122 | 123 | NSDictionary *jsonDict; 124 | 125 | if (data) { 126 | responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 127 | 128 | jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 129 | } 130 | 131 | 132 | 133 | NSMutableArray *responceDataArray; 134 | 135 | runOnMainQueueWithoutDeadlocking(^{ 136 | //Show Alert for Request Failed. 137 | }); 138 | 139 | //API cache Logger 140 | [self saveAPIDetailsToCacheForRequestTitle:[[NSURL URLWithString:URLString] lastPathComponent] 141 | andResponse:response 142 | andRequest:request 143 | responseDictionary:(jsonDict) ? : nil 144 | responseString:(responseString) ? : @""]; 145 | 146 | dispatch_async(dispatch_get_main_queue(), ^(){ 147 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 148 | if ( error ) 149 | { 150 | ShowNetworkIndicator(0); 151 | block(error,Responceobjects,responseString, nil, responceDataArray, response); 152 | } 153 | else 154 | { 155 | ShowNetworkIndicator(0); 156 | block(error,Responceobjects,responseString, nextStartRecord, responceDataArray, response); 157 | } 158 | }]; 159 | }); 160 | } 161 | else if(error == nil) 162 | { 163 | 164 | NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 165 | 166 | NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 167 | 168 | //API cache Logger 169 | [self saveAPIDetailsToCacheForRequestTitle:[[NSURL URLWithString:URLString] lastPathComponent] 170 | andResponse:response 171 | andRequest:request 172 | responseDictionary:jsonDict 173 | responseString:responseString]; 174 | 175 | NSMutableArray *responceDataArray; 176 | 177 | if (data.length>0) 178 | { 179 | Responceobjects = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; 180 | responceDataArray = [NSMutableArray array]; 181 | 182 | NSLog(@"ResponseString :: %@", responseString); 183 | 184 | switch (serviceName) 185 | { 186 | case APIUserLogIn: 187 | { 188 | /* 189 | If Any status has been passed from Server then first check SUCCESS / FAILURE status 190 | Then Parse your response within condition 191 | */ 192 | if ([[[(NSDictionary *)Responceobjects valueForKey:@"STATUS"] stringValue] isEqualToString:Success]) 193 | { 194 | Responceobjects = [(NSDictionary *)Responceobjects valueForKey:@"DATA"]; 195 | } 196 | else if ([[[(NSDictionary *)Responceobjects valueForKey:@"STATUS"] stringValue] isEqualToString:Failure]) 197 | { 198 | NSDictionary *errorDict = [[NSDictionary alloc]initWithObjectsAndKeys:[(NSDictionary *)Responceobjects valueForKey:@"MESSAGE"], @"msg", nil]; 199 | error = [NSError errorWithDomain:@"Internal Error" code:2 userInfo:errorDict]; 200 | } 201 | else if ([[[(NSDictionary *)Responceobjects valueForKey:@"STATUS"] stringValue] isEqualToString:InvalidResponce]) 202 | { 203 | NSDictionary *errorDict = [[NSDictionary alloc]initWithObjectsAndKeys:[(NSDictionary *)Responceobjects valueForKey:@"MESSAGE"], @"msg", nil]; 204 | error = [NSError errorWithDomain:@"Internal Error" code:2 userInfo:errorDict]; 205 | } 206 | } 207 | break; 208 | case APIGetComments : 209 | { 210 | // responceDataArray = (NSMutableArray *)Responceobjects; 211 | for (NSDictionary *dictionary in Responceobjects) { 212 | FeedObject *feedObj = [FeedObject modelObjectWithDictionary:dictionary]; 213 | [responceDataArray addObject:feedObj]; 214 | } 215 | break; 216 | } 217 | default: 218 | break; 219 | } 220 | } 221 | else if(error != nil) 222 | { 223 | runOnMainQueueWithoutDeadlocking(^{ 224 | //Handle Error as per your requirement 225 | }); 226 | } 227 | else if(data.length == 0) 228 | { 229 | runOnMainQueueWithoutDeadlocking(^{ 230 | //No response Received 231 | }); 232 | } 233 | 234 | dispatch_async(dispatch_get_main_queue(), ^(){ 235 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 236 | if ( error ) 237 | { 238 | ShowNetworkIndicator(0); 239 | block(error,Responceobjects,responseString, nil, responceDataArray, response); 240 | } 241 | else 242 | { 243 | ShowNetworkIndicator(0); 244 | block(error,Responceobjects,responseString, nextStartRecord, responceDataArray,response); 245 | } 246 | }]; 247 | }); 248 | } 249 | } 250 | }]; 251 | 252 | [dataTask resume]; 253 | }]; 254 | 255 | [operation setQueuePriority:NSOperationQueuePriorityVeryHigh]; 256 | [self.WSoperationQueue addOperation:operation]; 257 | } 258 | break; 259 | case NotReachable: 260 | { 261 | if (!self.APIRequestsArray) { 262 | self.APIRequestsArray = [NSMutableArray new]; 263 | } 264 | //Get current selector 265 | SEL aSelector = @selector(URLRequestWithType: 266 | parameters: 267 | cookieValue: 268 | customeobject: 269 | withRequestType: 270 | withRequestHeaders: 271 | block:); 272 | NSMethodSignature *signature = [self methodSignatureForSelector:aSelector]; 273 | 274 | //Set arguments in Invocation 275 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 276 | [invocation setTarget:self]; 277 | [invocation setSelector:aSelector]; 278 | [invocation setArgument:&serviceName atIndex:2]; 279 | [invocation setArgument:¶meters atIndex:3]; 280 | [invocation setArgument:&cookies atIndex:4]; 281 | [invocation setArgument:&object atIndex:5]; 282 | [invocation setArgument:&requestType atIndex:6]; 283 | [invocation setArgument:&headerDictionaries atIndex:7]; 284 | [invocation setArgument:&block atIndex:8]; 285 | 286 | //Retaining the arguments to invoke method later on 287 | [invocation retainArguments]; 288 | 289 | [self.APIRequestsArray addObject:invocation]; 290 | 291 | 292 | if (!self.isnetworkStatusVCPresented) { 293 | 294 | InternetConnectionStatusVC *networkStatus = loadViewController(@"InternetConnection", @"idInternetConnectionStatusVC"); 295 | 296 | //Set specific message for network connectivity 297 | networkStatus.headerMessage = @""; 298 | networkStatus.descriptionMessage = @""; 299 | 300 | networkStatus.completionBlock = ^(InternetConnectionStatusVC *controller) 301 | { 302 | 303 | //Network connected, call previous WS 304 | for (NSInvocation *WSInvocationCall in self.APIRequestsArray) { 305 | //Invoke (call) stored WS functions 306 | [WSInvocationCall performSelector:@selector(invoke) withObject:nil afterDelay:0.0]; 307 | } 308 | self.APIRequestsArray = nil; 309 | 310 | self.isnetworkStatusVCPresented = NO; 311 | }; 312 | 313 | self.isnetworkStatusVCPresented = YES; 314 | 315 | UIViewController *vc = APP_CONTEXT.window.rootViewController; 316 | 317 | if (!APP_CONTEXT.appNavigationController) { 318 | APP_CONTEXT.appNavigationController = [[UINavigationController alloc] init]; 319 | } 320 | 321 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:networkStatus]; 322 | 323 | [vc presentViewController:navigationController animated:YES 324 | completion:^{ 325 | 326 | }]; 327 | } 328 | } 329 | break; 330 | default: 331 | break; 332 | } 333 | } 334 | 335 | 336 | 337 | @end 338 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APIParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // APIParser.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Reachability.h" 11 | #import "APIConstants.h" 12 | #import "objc/runtime.h" 13 | #import "InternetConnectionStatusVC.h" 14 | 15 | 16 | typedef enum 17 | { 18 | APIRequestMethodGET, 19 | APIRequestMethodPOST, 20 | APIRequestMethodDELETE, 21 | APIRequestMethodPUT 22 | } APIRequestType; 23 | 24 | typedef void (^ResponseBlock) (NSError *error, id objects, NSString *responseString,NSString *nextUrl, NSMutableArray *responseArray, NSURLResponse *URLResponseObject); 25 | 26 | enum RESPONCESTATUTS 27 | { 28 | NORESPONCE=0, 29 | VALID = 1, 30 | INVALID = 2 31 | }; 32 | 33 | #define Success @"1" 34 | #define InvalidResponce @"2" 35 | #define Failure @"3" 36 | 37 | @interface APIParser : NSObject 38 | { 39 | Reachability *reachability; 40 | } 41 | 42 | @property (nonatomic, assign) APIRequestType requestType; 43 | 44 | @property (strong) NSOperationQueue *WSoperationQueue; 45 | 46 | @property (nonatomic, assign) BOOL isnetworkStatusVCPresented; 47 | 48 | @property (nonatomic, strong) NSMutableArray *APIRequestsArray; 49 | 50 | + (id)sharedMediaServer; 51 | 52 | - (NSData *)dictionaryWithPropertiesOfObject:(id)obj; 53 | - (NSData *)dictionaryWithmembersOfObject:(id)obj formembers:(NSArray *)members; 54 | - (NSData *)dictionaryToJSONData:(NSDictionary *)dict; 55 | 56 | - (NSMutableURLRequest *)urlRequestForURL:(NSURL *)url withObjects:(NSData *)objData 57 | withReqCookies:(NSMutableArray *)arrCookies 58 | isObject:(bool)customObj 59 | withParameters :(NSString *) params 60 | reqType :(APIRequestType) requestType 61 | reqHeaders:(NSDictionary *) requestHeaders; 62 | 63 | #pragma mark - Cancel all API request with operation 64 | - (void)cancelALLCurrentlyExecutingRequest; 65 | 66 | #pragma mark - Dictionary to QueryString 67 | -(NSString *)serializeParams:(NSDictionary *)params; 68 | 69 | #pragma mark - DEVELOPER API DEBUG LOGS 70 | - (void) saveAPIDetailsToCacheForRequestTitle:(NSString *)apiName //Title of API 71 | andResponse:(NSURLResponse *)response //Response object 72 | andRequest:(NSURLRequest *)request //Request object 73 | responseDictionary:(NSDictionary *)responseDict //Formatted response 74 | responseString:(NSString *)responseString; //Raw response 75 | 76 | #pragma mark - Run On Main Thread 77 | void runOnMainQueueWithoutDeadlocking(void (^block)(void)); 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/APIParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // APIParser.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "APIParser.h" 10 | #import "APIInfoObject.h" 11 | #import "AppCacheManagement.h" 12 | 13 | @implementation APIParser 14 | 15 | #pragma mark - Properties 16 | 17 | @synthesize WSoperationQueue = WSoperationQueue; 18 | 19 | #pragma mark - Init NSObject 20 | 21 | - (id)init 22 | { 23 | if ( ( self = [super init] ) ) 24 | { 25 | // The maxConcurrentOperationCount should reflect the number of open 26 | // connections the server can handle. Right now, limit it to two for 27 | // the sake of this example. 28 | WSoperationQueue = [[NSOperationQueue alloc] init]; 29 | WSoperationQueue.maxConcurrentOperationCount = 16; 30 | 31 | if (IOS_NEWER_OR_EQUAL_TO_X(8.0)) { 32 | 33 | WSoperationQueue.qualityOfService = NSQualityOfServiceBackground; 34 | } 35 | 36 | // Allocate a reachability object 37 | Reachability* reach = [Reachability reachabilityWithHostname:@ServerPath]; 38 | 39 | // Set the blocks 40 | reach.reachableBlock = ^(Reachability*reach) 41 | { 42 | ////TRC_DBG(@"%s REACHABLE!",ServerPath); 43 | }; 44 | 45 | reach.unreachableBlock = ^(Reachability*reach) 46 | { 47 | ////TRC_DBG(@"%s UNREACHABLE!",ServerPath); 48 | }; 49 | 50 | // Start the notifier, which will cause the reachability object to retain itself! 51 | [reach startNotifier]; 52 | 53 | [WSoperationQueue addObserver:self forKeyPath:@"operations" options:0 context:NULL]; 54 | } 55 | return self; 56 | } 57 | 58 | - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 59 | change:(NSDictionary *)change context:(void *)context 60 | { 61 | APIParser *parser =[APIParser sharedMediaServer]; 62 | 63 | if (object == parser.WSoperationQueue && [keyPath isEqualToString:@"operations"]) 64 | { 65 | if ([parser.WSoperationQueue.operations count] == 0) 66 | { 67 | runOnMainQueueWithoutDeadlocking(^{ 68 | ShowNetworkIndicator(0); 69 | }); 70 | } 71 | } 72 | else { 73 | [super observeValueForKeyPath:keyPath ofObject:object 74 | change:change context:context]; 75 | } 76 | } 77 | 78 | #pragma mark - Cancel all API request with operation 79 | 80 | - (void)cancelALLCurrentlyExecutingRequest { 81 | [WSoperationQueue cancelAllOperations]; 82 | ShowNetworkIndicator(0); 83 | } 84 | 85 | #pragma mark - API 86 | 87 | + (id)sharedMediaServer; 88 | { 89 | static dispatch_once_t onceToken; 90 | static id sharedMediaServer = nil; 91 | 92 | dispatch_once( &onceToken, ^{ 93 | sharedMediaServer = [[[self class] alloc] init]; 94 | }); 95 | 96 | return sharedMediaServer; 97 | } 98 | 99 | - (NSData *) dictionaryWithPropertiesOfObject:(id)obj 100 | { 101 | NSError *jsonError = nil; 102 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithDictionary:(NSMutableDictionary *)obj] options:0 error:&jsonError]; 103 | 104 | if (jsonError!=nil) 105 | { 106 | return nil; 107 | } 108 | return jsonData; 109 | } 110 | 111 | - (NSData *)dictionaryToJSONData:(NSDictionary *)dict 112 | { 113 | NSError *jsonError = nil; 114 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithDictionary:dict] options:0 error:&jsonError]; 115 | 116 | if (jsonError!=nil) 117 | { 118 | return nil; 119 | } 120 | return jsonData; 121 | } 122 | 123 | - (NSData *)dictionaryWithmembersOfObject:(id)obj formembers:(NSArray *)members 124 | { 125 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 126 | for (NSString *memberkey in members) 127 | { 128 | if(memberkey.length>0) 129 | { 130 | if ([obj valueForKey:memberkey] != nil) 131 | { 132 | [dict setObject:[obj valueForKey:memberkey] forKey:memberkey]; 133 | } 134 | } 135 | } 136 | 137 | NSError *jsonError = nil; 138 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithDictionary:dict] options:0 error:&jsonError]; 139 | 140 | if (jsonError!=nil) 141 | { 142 | return nil; 143 | } 144 | return jsonData; 145 | } 146 | 147 | #pragma mark - Create Request 148 | 149 | - (NSMutableURLRequest *)urlRequestForURL:(NSURL *)url withObjects:(NSData *)objData 150 | withReqCookies:(NSMutableArray *)arrCookies 151 | isObject:(bool)customObj 152 | withParameters :(NSString *) params 153 | reqType :(APIRequestType) requestType 154 | reqHeaders:(NSDictionary *) requestHeaders 155 | { 156 | 157 | NSMutableURLRequest *request = [NSMutableURLRequest 158 | requestWithURL:url 159 | cachePolicy:NSURLRequestUseProtocolCachePolicy 160 | timeoutInterval:DEFAULT_TIMEOUT]; 161 | 162 | if (customObj) { 163 | [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 164 | [request setValue:@"application/json;charset=UTF-8" forHTTPHeaderField:@"content-type"]; 165 | } 166 | else { 167 | [request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 168 | } 169 | 170 | [request addValue:[NSString stringWithFormat:@"%lu", (unsigned long)[objData length]] forHTTPHeaderField:@"Content-Length"]; 171 | [request addValue:@"application/json" forHTTPHeaderField:@"Accept"]; 172 | [request setHTTPMethod:StringFromAPIRequestMethod(requestType)]; 173 | [request setHTTPShouldHandleCookies:YES]; 174 | 175 | 176 | //Add custom Headers 177 | for (NSString *key in [requestHeaders allKeys]) { 178 | [request setValue:[requestHeaders valueForKey:key] forHTTPHeaderField:key]; 179 | } 180 | 181 | //Some Universal Request Headers for all request 182 | [request setValue:@"Pass_Your_Access_Token" forHTTPHeaderField:@"AuthorizationTemp"]; 183 | [request setValue:@"Pass_YourSession_ID" forHTTPHeaderField:@"SessionIdTemp"]; 184 | 185 | //Set Cookie 186 | NSMutableArray *allCookies = [NSMutableArray array]; 187 | 188 | NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; 189 | 190 | for (NSHTTPCookie *cookie in [storage cookies]) { 191 | [allCookies addObject:cookie]; 192 | } 193 | 194 | if ([allCookies count] > 0) { 195 | 196 | NSDictionary *headers = [NSHTTPCookie requestHeaderFieldsWithCookies:allCookies]; 197 | [request setAllHTTPHeaderFields:headers]; 198 | } 199 | 200 | [request setHTTPBody:objData]; 201 | 202 | return request; 203 | } 204 | 205 | #pragma mark - Dictionary to QueryString 206 | 207 | -(NSString *)serializeParams:(NSDictionary *)params { 208 | 209 | /* 210 | 211 | Convert an NSDictionary to a query string 212 | 213 | */ 214 | 215 | NSMutableArray* pairs = [NSMutableArray array]; 216 | for (NSString* key in [params keyEnumerator]) { 217 | id value = [params objectForKey:key]; 218 | if ([value isKindOfClass:[NSDictionary class]]) { 219 | for (NSString *subKey in value) { 220 | NSString* escaped_value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, 221 | (CFStringRef)[value objectForKey:subKey], 222 | NULL, 223 | (CFStringRef)@"!*'();:@&=+$,/?%#[]", 224 | kCFStringEncodingUTF8)); 225 | [pairs addObject:[NSString stringWithFormat:@"%@[%@]=%@", key, subKey, escaped_value]]; 226 | } 227 | } else if ([value isKindOfClass:[NSArray class]]) { 228 | for (NSString *subValue in value) { 229 | NSString* escaped_value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, 230 | (CFStringRef)subValue, 231 | NULL, 232 | (CFStringRef)@"!*'();:@&=+$,/?%#[]", 233 | kCFStringEncodingUTF8)); 234 | [pairs addObject:[NSString stringWithFormat:@"%@[]=%@", key, escaped_value]]; 235 | } 236 | } else { 237 | NSString* escaped_value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, 238 | (CFStringRef)[params objectForKey:key], 239 | NULL, 240 | (CFStringRef)@"!*'();:@&=+$,/?%#[]", 241 | kCFStringEncodingUTF8)); 242 | [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, escaped_value]]; 243 | // [escaped_value release]; 244 | } 245 | } 246 | return [pairs componentsJoinedByString:@"&"]; 247 | } 248 | 249 | #pragma mark - DEVELOPER API DEBUG LOGS 250 | 251 | - (void)saveAPIDetailsToCacheForRequestTitle:(NSString *)apiName //Title of API 252 | andResponse:(NSURLResponse *)response //Response object 253 | andRequest:(NSURLRequest *)request //Request object 254 | responseDictionary:(NSDictionary *)responseDict //Formatted response 255 | responseString:(NSString *)responseString //Raw response 256 | { 257 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 258 | 259 | if (![[AppCacheManagement sharedCacheManager] APILoggingEnabled]) 260 | return; 261 | 262 | APIInfoObject *debugDetail = [APIInfoObject modelObjectWithDetails:apiName request:request response:response responseDictionary:responseDict responseString:responseString]; 263 | 264 | __block NSMutableArray *debugCachedArray; 265 | [[AppCacheManagement sharedCacheManager] getcachedataArrayFor_:kDeveloperDebugAPILog myMethod:^(BOOL status, NSMutableArray *retrivedArray) { 266 | if (retrivedArray != nil) { 267 | debugCachedArray = retrivedArray; 268 | } 269 | }]; 270 | if (debugCachedArray.count == kConstMaxDebugAPICount) { 271 | 272 | [debugCachedArray removeObjectAtIndex:0]; 273 | } 274 | 275 | [debugCachedArray addObject:debugDetail]; 276 | 277 | [[AppCacheManagement sharedCacheManager] setCacheToUserDefaults:debugCachedArray ForKey:kDeveloperDebugAPILog]; 278 | }); 279 | } 280 | 281 | #pragma mark - Run On Main Thread 282 | 283 | void runOnMainQueueWithoutDeadlocking(void (^block)(void)) 284 | { 285 | if ([NSThread isMainThread]) 286 | { 287 | block(); 288 | } 289 | else 290 | { 291 | dispatch_async(dispatch_get_main_queue(), block); 292 | } 293 | } 294 | 295 | #pragma mark - String Request enum 296 | 297 | NSString *StringFromAPIRequestMethod(APIRequestType apiType) 298 | { 299 | switch (apiType) { 300 | case APIRequestMethodGET: return @"GET"; 301 | case APIRequestMethodPOST: return @"POST"; 302 | case APIRequestMethodPUT: return @"PUT"; 303 | case APIRequestMethodDELETE: return @"DELETE"; 304 | default: break; 305 | } 306 | return nil; 307 | } 308 | 309 | @end 310 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/AppMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppMacros.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifndef AppMacros_h 12 | #define AppMacros_h 13 | 14 | #pragma mark - 15 | #pragma mark - App Delegate 16 | 17 | #define APP_CONTEXT ((AppDelegate*)[[UIApplication sharedApplication] delegate]) 18 | 19 | #define IOS_NEWER_OR_EQUAL_TO_X(XX) ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= XX ) 20 | 21 | #pragma mark - 22 | #pragma mark - Network Indicator 23 | 24 | #define ShowNetworkIndicator(BOOL) [UIApplication sharedApplication].networkActivityIndicatorVisible = BOOL 25 | 26 | #pragma mark - 27 | #pragma mark - View 28 | 29 | #define getStoryboard(StoryboardWithName) [UIStoryboard storyboardWithName:[NSString stringWithFormat:@"%@", StoryboardWithName] bundle:NULL] 30 | #define loadViewController(StoryBoardName, VCIdentifer) [getStoryboard(StoryBoardName)instantiateViewControllerWithIdentifier:VCIdentifer] 31 | 32 | #define RGBCOLOR(r, g, b, alp) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:alp] 33 | 34 | #define Screen_Height [UIScreen mainScreen].bounds.size.height 35 | #define Screen_Width [UIScreen mainScreen].bounds.size.width 36 | 37 | #endif /* AppMacros_h */ 38 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/Reachability/Reachability.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Tony Million. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import 29 | #import 30 | 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | 38 | /** 39 | * Does ARC support GCD objects? 40 | * It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ 41 | * 42 | * @see http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h 43 | **/ 44 | #if OS_OBJECT_USE_OBJC 45 | #define NEEDS_DISPATCH_RETAIN_RELEASE 0 46 | #else 47 | #define NEEDS_DISPATCH_RETAIN_RELEASE 1 48 | #endif 49 | 50 | /** 51 | * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X. 52 | * 53 | * @see http://nshipster.com/ns_enum-ns_options/ 54 | **/ 55 | #ifndef NS_ENUM 56 | #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type 57 | #endif 58 | 59 | extern NSString *const kReachabilityChangedNotification; 60 | 61 | typedef NS_ENUM(NSInteger, NetworkStatus) { 62 | // Apple NetworkStatus Compatible Names. 63 | NotReachable = 0, 64 | ReachableViaWiFi = 2, 65 | ReachableViaWWAN = 1 66 | }; 67 | 68 | @class Reachability; 69 | 70 | typedef void (^NetworkReachable)(Reachability * reachability); 71 | typedef void (^NetworkUnreachable)(Reachability * reachability); 72 | 73 | @interface Reachability : NSObject 74 | 75 | @property (nonatomic, copy) NetworkReachable reachableBlock; 76 | @property (nonatomic, copy) NetworkUnreachable unreachableBlock; 77 | 78 | 79 | @property (nonatomic, assign) BOOL reachableOnWWAN; 80 | 81 | +(Reachability*)reachabilityWithHostname:(NSString*)hostname; 82 | // This is identical to the function above, but is here to maintain 83 | //compatibility with Apples original code. (see .m) 84 | +(Reachability*)reachabilityWithHostName:(NSString*)hostname; 85 | +(Reachability*)reachabilityForInternetConnection; 86 | +(Reachability*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress; 87 | +(Reachability*)reachabilityForLocalWiFi; 88 | 89 | -(Reachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; 90 | 91 | -(BOOL)startNotifier; 92 | -(void)stopNotifier; 93 | 94 | -(BOOL)isReachable; 95 | -(BOOL)isReachableViaWWAN; 96 | -(BOOL)isReachableViaWiFi; 97 | 98 | // WWAN may be available, but not active until a connection has been established. 99 | // WiFi may require a connection for VPN on Demand. 100 | -(BOOL)isConnectionRequired; // Identical DDG variant. 101 | -(BOOL)connectionRequired; // Apple's routine. 102 | // Dynamic, on demand connection? 103 | -(BOOL)isConnectionOnDemand; 104 | // Is user intervention required? 105 | -(BOOL)isInterventionRequired; 106 | 107 | -(NetworkStatus)currentReachabilityStatus; 108 | -(SCNetworkReachabilityFlags)reachabilityFlags; 109 | -(NSString*)currentReachabilityString; 110 | -(NSString*)currentReachabilityFlags; 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /iOS_APIParser/ApplicationAPI/Reachability/Reachability.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Tony Million. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #import "Reachability.h" 29 | 30 | 31 | NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification"; 32 | 33 | @interface Reachability () 34 | 35 | @property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; 36 | 37 | 38 | #if NEEDS_DISPATCH_RETAIN_RELEASE 39 | @property (nonatomic, assign) dispatch_queue_t reachabilitySerialQueue; 40 | #else 41 | @property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; 42 | #endif 43 | 44 | 45 | @property (nonatomic, strong) id reachabilityObject; 46 | 47 | -(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; 48 | -(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; 49 | 50 | @end 51 | 52 | static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) 53 | { 54 | return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", 55 | #if TARGET_OS_IPHONE 56 | (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', 57 | #else 58 | 'X', 59 | #endif 60 | (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', 61 | (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', 62 | (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', 63 | (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', 64 | (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', 65 | (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', 66 | (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', 67 | (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; 68 | } 69 | 70 | // Start listening for reachability notifications on the current run loop 71 | static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) 72 | { 73 | #pragma unused (target) 74 | #if __has_feature(objc_arc) 75 | Reachability *reachability = ((__bridge Reachability*)info); 76 | #else 77 | Reachability *reachability = ((Reachability*)info); 78 | #endif 79 | 80 | // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, 81 | // but what the heck eh? 82 | @autoreleasepool 83 | { 84 | [reachability reachabilityChanged:flags]; 85 | } 86 | } 87 | 88 | 89 | @implementation Reachability 90 | 91 | @synthesize reachabilityRef; 92 | @synthesize reachabilitySerialQueue; 93 | 94 | @synthesize reachableOnWWAN; 95 | 96 | @synthesize reachableBlock; 97 | @synthesize unreachableBlock; 98 | 99 | @synthesize reachabilityObject; 100 | 101 | #pragma mark - Class Constructor Methods 102 | 103 | +(Reachability*)reachabilityWithHostName:(NSString*)hostname 104 | { 105 | return [Reachability reachabilityWithHostname:hostname]; 106 | } 107 | 108 | +(Reachability*)reachabilityWithHostname:(NSString*)hostname 109 | { 110 | SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); 111 | if (ref) 112 | { 113 | id reachability = [[self alloc] initWithReachabilityRef:ref]; 114 | 115 | #if __has_feature(objc_arc) 116 | return reachability; 117 | #else 118 | return [reachability autorelease]; 119 | #endif 120 | 121 | } 122 | 123 | return nil; 124 | } 125 | 126 | +(Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress 127 | { 128 | SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); 129 | if (ref) 130 | { 131 | id reachability = [[self alloc] initWithReachabilityRef:ref]; 132 | 133 | #if __has_feature(objc_arc) 134 | return reachability; 135 | #else 136 | return [reachability autorelease]; 137 | #endif 138 | } 139 | 140 | return nil; 141 | } 142 | 143 | +(Reachability *)reachabilityForInternetConnection 144 | { 145 | struct sockaddr_in zeroAddress; 146 | bzero(&zeroAddress, sizeof(zeroAddress)); 147 | zeroAddress.sin_len = sizeof(zeroAddress); 148 | zeroAddress.sin_family = AF_INET; 149 | 150 | return [self reachabilityWithAddress:&zeroAddress]; 151 | } 152 | 153 | +(Reachability*)reachabilityForLocalWiFi 154 | { 155 | struct sockaddr_in localWifiAddress; 156 | bzero(&localWifiAddress, sizeof(localWifiAddress)); 157 | localWifiAddress.sin_len = sizeof(localWifiAddress); 158 | localWifiAddress.sin_family = AF_INET; 159 | // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 160 | localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); 161 | 162 | return [self reachabilityWithAddress:&localWifiAddress]; 163 | } 164 | 165 | 166 | // Initialization methods 167 | 168 | -(Reachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref 169 | { 170 | self = [super init]; 171 | if (self != nil) 172 | { 173 | self.reachableOnWWAN = YES; 174 | self.reachabilityRef = ref; 175 | } 176 | 177 | return self; 178 | } 179 | 180 | -(void)dealloc 181 | { 182 | [self stopNotifier]; 183 | 184 | if(self.reachabilityRef) 185 | { 186 | CFRelease(self.reachabilityRef); 187 | self.reachabilityRef = nil; 188 | } 189 | 190 | self.reachableBlock = nil; 191 | self.unreachableBlock = nil; 192 | 193 | #if !(__has_feature(objc_arc)) 194 | [super dealloc]; 195 | #endif 196 | 197 | 198 | } 199 | 200 | #pragma mark - Notifier Methods 201 | 202 | // Notifier 203 | // NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD 204 | // - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. 205 | // INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) 206 | 207 | -(BOOL)startNotifier 208 | { 209 | SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; 210 | 211 | // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves 212 | // woah 213 | self.reachabilityObject = self; 214 | 215 | 216 | 217 | // First, we need to create a serial queue. 218 | // We allocate this once for the lifetime of the notifier. 219 | self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); 220 | if(!self.reachabilitySerialQueue) 221 | { 222 | return NO; 223 | } 224 | 225 | #if __has_feature(objc_arc) 226 | context.info = (__bridge void *)self; 227 | #else 228 | context.info = (void *)self; 229 | #endif 230 | 231 | if (!SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) 232 | { 233 | #ifdef DEBUG 234 | //////NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); 235 | #endif 236 | 237 | // Clear out the dispatch queue 238 | if(self.reachabilitySerialQueue) 239 | { 240 | #if NEEDS_DISPATCH_RETAIN_RELEASE 241 | dispatch_release(self.reachabilitySerialQueue); 242 | #endif 243 | self.reachabilitySerialQueue = nil; 244 | } 245 | 246 | self.reachabilityObject = nil; 247 | 248 | return NO; 249 | } 250 | 251 | // Set it as our reachability queue, which will retain the queue 252 | if(!SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) 253 | { 254 | #ifdef DEBUG 255 | //////NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); 256 | #endif 257 | 258 | // UH OH - FAILURE! 259 | 260 | // First stop, any callbacks! 261 | SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); 262 | 263 | // Then clear out the dispatch queue. 264 | if(self.reachabilitySerialQueue) 265 | { 266 | #if NEEDS_DISPATCH_RETAIN_RELEASE 267 | dispatch_release(self.reachabilitySerialQueue); 268 | #endif 269 | self.reachabilitySerialQueue = nil; 270 | } 271 | 272 | self.reachabilityObject = nil; 273 | 274 | return NO; 275 | } 276 | 277 | return YES; 278 | } 279 | 280 | -(void)stopNotifier 281 | { 282 | // First stop, any callbacks! 283 | SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); 284 | 285 | // Unregister target from the GCD serial dispatch queue. 286 | SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); 287 | 288 | if(self.reachabilitySerialQueue) 289 | { 290 | #if NEEDS_DISPATCH_RETAIN_RELEASE 291 | dispatch_release(self.reachabilitySerialQueue); 292 | #endif 293 | self.reachabilitySerialQueue = nil; 294 | } 295 | 296 | self.reachabilityObject = nil; 297 | } 298 | 299 | #pragma mark - reachability tests 300 | 301 | // This is for the case where you flick the airplane mode; 302 | // you end up getting something like this: 303 | //Reachability: WR ct----- 304 | //Reachability: -- ------- 305 | //Reachability: WR ct----- 306 | //Reachability: -- ------- 307 | // We treat this as 4 UNREACHABLE triggers - really apple should do better than this 308 | 309 | #define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) 310 | 311 | -(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags 312 | { 313 | BOOL connectionUP = YES; 314 | 315 | if(!(flags & kSCNetworkReachabilityFlagsReachable)) 316 | connectionUP = NO; 317 | 318 | if( (flags & testcase) == testcase ) 319 | connectionUP = NO; 320 | 321 | #if TARGET_OS_IPHONE 322 | if(flags & kSCNetworkReachabilityFlagsIsWWAN) 323 | { 324 | // We're on 3G. 325 | if(!self.reachableOnWWAN) 326 | { 327 | // We don't want to connect when on 3G. 328 | connectionUP = NO; 329 | } 330 | } 331 | #endif 332 | 333 | return connectionUP; 334 | } 335 | 336 | -(BOOL)isReachable 337 | { 338 | SCNetworkReachabilityFlags flags; 339 | 340 | if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) 341 | return NO; 342 | 343 | return [self isReachableWithFlags:flags]; 344 | } 345 | 346 | -(BOOL)isReachableViaWWAN 347 | { 348 | #if TARGET_OS_IPHONE 349 | 350 | SCNetworkReachabilityFlags flags = 0; 351 | 352 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 353 | { 354 | // Check we're REACHABLE 355 | if(flags & kSCNetworkReachabilityFlagsReachable) 356 | { 357 | // Now, check we're on WWAN 358 | if(flags & kSCNetworkReachabilityFlagsIsWWAN) 359 | { 360 | return YES; 361 | } 362 | } 363 | } 364 | #endif 365 | 366 | return NO; 367 | } 368 | 369 | -(BOOL)isReachableViaWiFi 370 | { 371 | SCNetworkReachabilityFlags flags = 0; 372 | 373 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 374 | { 375 | // Check we're reachable 376 | if((flags & kSCNetworkReachabilityFlagsReachable)) 377 | { 378 | #if TARGET_OS_IPHONE 379 | // Check we're NOT on WWAN 380 | if((flags & kSCNetworkReachabilityFlagsIsWWAN)) 381 | { 382 | return NO; 383 | } 384 | #endif 385 | return YES; 386 | } 387 | } 388 | 389 | return NO; 390 | } 391 | 392 | 393 | // WWAN may be available, but not active until a connection has been established. 394 | // WiFi may require a connection for VPN on Demand. 395 | -(BOOL)isConnectionRequired 396 | { 397 | return [self connectionRequired]; 398 | } 399 | 400 | -(BOOL)connectionRequired 401 | { 402 | SCNetworkReachabilityFlags flags; 403 | 404 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 405 | { 406 | return (flags & kSCNetworkReachabilityFlagsConnectionRequired); 407 | } 408 | 409 | return NO; 410 | } 411 | 412 | // Dynamic, on demand connection? 413 | -(BOOL)isConnectionOnDemand 414 | { 415 | SCNetworkReachabilityFlags flags; 416 | 417 | if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 418 | { 419 | return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && 420 | (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); 421 | } 422 | 423 | return NO; 424 | } 425 | 426 | // Is user intervention required? 427 | -(BOOL)isInterventionRequired 428 | { 429 | SCNetworkReachabilityFlags flags; 430 | 431 | if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 432 | { 433 | return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && 434 | (flags & kSCNetworkReachabilityFlagsInterventionRequired)); 435 | } 436 | 437 | return NO; 438 | } 439 | 440 | 441 | #pragma mark - reachability status stuff 442 | 443 | -(NetworkStatus)currentReachabilityStatus 444 | { 445 | if([self isReachable]) 446 | { 447 | if([self isReachableViaWiFi]) 448 | return ReachableViaWiFi; 449 | 450 | #if TARGET_OS_IPHONE 451 | return ReachableViaWWAN; 452 | #endif 453 | } 454 | 455 | return NotReachable; 456 | } 457 | 458 | -(SCNetworkReachabilityFlags)reachabilityFlags 459 | { 460 | SCNetworkReachabilityFlags flags = 0; 461 | 462 | if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 463 | { 464 | return flags; 465 | } 466 | 467 | return 0; 468 | } 469 | 470 | -(NSString*)currentReachabilityString 471 | { 472 | NetworkStatus temp = [self currentReachabilityStatus]; 473 | 474 | if(temp == reachableOnWWAN) 475 | { 476 | // Updated for the fact that we have CDMA phones now! 477 | return NSLocalizedString(@"Cellular", @""); 478 | } 479 | if (temp == ReachableViaWiFi) 480 | { 481 | return NSLocalizedString(@"WiFi", @""); 482 | } 483 | 484 | return NSLocalizedString(@"No Connection", @""); 485 | } 486 | 487 | -(NSString*)currentReachabilityFlags 488 | { 489 | return reachabilityFlags([self reachabilityFlags]); 490 | } 491 | 492 | #pragma mark - Callback function calls this method 493 | 494 | -(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags 495 | { 496 | if([self isReachableWithFlags:flags]) 497 | { 498 | if(self.reachableBlock) 499 | { 500 | self.reachableBlock(self); 501 | } 502 | } 503 | else 504 | { 505 | if(self.unreachableBlock) 506 | { 507 | self.unreachableBlock(self); 508 | } 509 | } 510 | 511 | // this makes sure the change notification happens on the MAIN THREAD 512 | dispatch_async(dispatch_get_main_queue(), ^{ 513 | [[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification 514 | object:self]; 515 | }); 516 | } 517 | 518 | #pragma mark - Debug Description 519 | 520 | - (NSString *) description 521 | { 522 | NSString *description = [NSString stringWithFormat:@"<%@: %#x>", 523 | NSStringFromClass([self class]), (unsigned int) self]; 524 | return description; 525 | } 526 | 527 | @end 528 | -------------------------------------------------------------------------------- /iOS_APIParser/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /iOS_APIParser/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /iOS_APIParser/Assets.xcassets/internet_reachability.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "no-internet-connection-sign-of-phone-interface.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /iOS_APIParser/Assets.xcassets/internet_reachability.imageset/no-internet-connection-sign-of-phone-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dhruvik13/iOS-Webservice/1b5d2f0a8152760e9f0b67be17cc8bcf81ef8648/iOS_APIParser/Assets.xcassets/internet_reachability.imageset/no-internet-connection-sign-of-phone-interface.png -------------------------------------------------------------------------------- /iOS_APIParser/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iOS_APIParser/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 68 | 77 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /iOS_APIParser/CategoryClasses/NSString+ContainString.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ContainString.m 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 17/10/15. 6 | // Copyright © 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 13 | 14 | @interface NSString (PSPDFModernizer) 15 | 16 | // Added in iOS 8, retrofitted for iOS 7 17 | - (BOOL)containsString:(NSString *)aString; 18 | 19 | @end 20 | 21 | #endif 22 | 23 | #import 24 | 25 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 26 | 27 | @implementation NSString (PSPDFModernizerCreator) 28 | 29 | + (void)load { 30 | @autoreleasepool { 31 | [self pspdf_modernizeSelector:NSSelectorFromString(@"containsString:") withSelector:@selector(pspdf_containsString:)]; 32 | } 33 | } 34 | 35 | + (void)pspdf_modernizeSelector:(SEL)originalSelector withSelector:(SEL)newSelector { 36 | if (![NSString instancesRespondToSelector:originalSelector]) { 37 | Method newMethod = class_getInstanceMethod(self, newSelector); 38 | class_addMethod(self, originalSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)); 39 | } 40 | } 41 | 42 | // containsString: has been added in iOS 8. We dynamically add this if we run on iOS 7. 43 | - (BOOL)pspdf_containsString:(NSString *)aString { 44 | return [self rangeOfString:aString].location != NSNotFound; 45 | } 46 | 47 | @end 48 | 49 | #endif -------------------------------------------------------------------------------- /iOS_APIParser/CustomCell/OrderSummaryCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // OrderSummaryCell.h 3 | // FastTicket 4 | // 5 | // Created by Manan Sheth on 9/9/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OrderSummaryCell : UITableViewCell 12 | 13 | @property (strong, nonatomic) UILabel *lblKey; 14 | @property (strong, nonatomic) UILabel *lblValue; 15 | 16 | - (id)initWithStyle:(UITableViewCellStyle)style 17 | reuseIdentifier:(NSString *)reuseIdentifier 18 | forCurrentObjectKey:(NSString*) key 19 | forCurrentObjectValue:(NSString*) value 20 | forParentFrame : (CGRect) frame ; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /iOS_APIParser/CustomCell/OrderSummaryCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // OrderSummaryCell.m 3 | // FastTicket 4 | // 5 | // Created by Manan Sheth on 9/9/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import "OrderSummaryCell.h" 10 | 11 | @implementation OrderSummaryCell 12 | 13 | @synthesize lblKey; 14 | @synthesize lblValue; 15 | 16 | 17 | - (id)initWithStyle:(UITableViewCellStyle)style 18 | reuseIdentifier:(NSString *)reuseIdentifier 19 | forCurrentObjectKey:(NSString*) key 20 | forCurrentObjectValue:(NSString*) value 21 | forParentFrame : (CGRect) frame 22 | { 23 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 24 | if (self) { 25 | 26 | int ParentWidth = CGRectGetWidth(frame); 27 | 28 | //Key 29 | lblKey = [UILabel new]; 30 | lblKey.frame = CGRectMake(10, 8, (ParentWidth / 2) - 20, 20); 31 | 32 | CGRect textRectKey = [key boundingRectWithSize:CGSizeMake((ParentWidth / 2) - 20, 9999) 33 | options:NSStringDrawingUsesLineFragmentOrigin 34 | attributes:@{NSFontAttributeName:THEME_FONT_REGULAR(14.0)} 35 | context:nil]; 36 | lblKey.frame = CGRectMake(10, 8, (ParentWidth / 2) - 20, textRectKey.size.height); 37 | 38 | lblKey.textColor = RGBCOLOR(131, 131, 131, 1); 39 | lblKey.textAlignment = NSTextAlignmentLeft; 40 | lblKey.font = THEME_FONT_REGULAR(14.0); 41 | lblKey.numberOfLines = 0; 42 | lblKey.text = key; 43 | [lblKey setBackgroundColor:[UIColor clearColor]]; 44 | [self addSubview:lblKey]; 45 | 46 | //Seperator 47 | UILabel *lblColumn = [UILabel new]; 48 | lblColumn.frame = CGRectMake(CGRectGetMaxX(lblKey.frame) , lblKey.frame.origin.y - 4, 7, 24); 49 | [lblColumn setText:@" : "]; 50 | lblColumn.numberOfLines = 0; 51 | lblColumn.font = THEME_FONT_REGULAR(14.0); 52 | lblColumn.textColor = RGBCOLOR(131, 131, 131, 1); 53 | lblColumn.textAlignment = NSTextAlignmentLeft; 54 | lblColumn.numberOfLines = 0; 55 | [lblColumn setBackgroundColor:[UIColor clearColor]]; 56 | [self addSubview:lblColumn]; 57 | 58 | //Value 59 | lblValue = [UILabel new]; 60 | lblValue.frame = CGRectMake(CGRectGetMaxX(lblColumn.frame) + 4 , 8, ParentWidth - (CGRectGetMaxX(lblColumn.frame) + 10), 24); 61 | 62 | CGRect textRectValue = [value boundingRectWithSize:CGSizeMake(ParentWidth - (CGRectGetMaxX(lblColumn.frame) + 10), 9999) 63 | options:NSStringDrawingUsesLineFragmentOrigin 64 | attributes:@{NSFontAttributeName:THEME_FONT_REGULAR(14.0)} 65 | context:nil]; 66 | 67 | lblValue.frame = CGRectMake(CGRectGetMaxX(lblColumn.frame) + 4 , 8, (ParentWidth - (CGRectGetMaxX(lblColumn.frame) + 10)), textRectValue.size.height); 68 | 69 | lblValue.textColor = RGBCOLOR(131, 131, 131, 1); 70 | lblValue.textAlignment = NSTextAlignmentLeft; 71 | lblValue.font = THEME_FONT_REGULAR(14.0); 72 | lblValue.numberOfLines = 0; 73 | lblValue.text = value; 74 | [lblValue setBackgroundColor:[UIColor clearColor]]; 75 | [self addSubview:lblValue]; 76 | 77 | self.backgroundColor = [UIColor whiteColor]; 78 | } 79 | 80 | return self; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /iOS_APIParser/CustomCell/OrderSummaryVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // OrderSummaryVC.h 3 | // FastTicket 4 | // 5 | // Created by Manan Sheth on 9/9/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol OrderSummaryViewDelegate 12 | 13 | @optional 14 | 15 | - (void)clickForDismissView; 16 | 17 | @end 18 | 19 | @interface OrderSummaryVC : UIViewController 20 | 21 | @property (strong, nonatomic) id orderSummaryDelegate; 22 | 23 | @end -------------------------------------------------------------------------------- /iOS_APIParser/CustomCell/OrderSummaryVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // OrderSummaryVC.m 3 | // FastTicket 4 | // 5 | // Created by Manan Sheth on 9/9/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import "OrderSummaryVC.h" 10 | #import "OrderSummaryCell.h" 11 | 12 | @interface OrderSummaryVC () 13 | { 14 | __weak IBOutlet UITableView *tblOrder; 15 | 16 | IBOutlet UILabel *lblHeader; 17 | IBOutlet UIButton *btnClose; 18 | } 19 | 20 | - (IBAction)clickToClose:(id)sender; 21 | 22 | @end 23 | 24 | @implementation OrderSummaryVC 25 | 26 | #pragma mark - Class Methods 27 | 28 | - (void)viewDidLoad { 29 | 30 | [super viewDidLoad]; 31 | 32 | [lblHeader setFont:THEME_FONT_BOLD(15.0)]; 33 | btnClose.titleLabel.font =THEME_FONT_BOLD(15.0); 34 | 35 | if (iPadDevice) 36 | [self.view setFrame:CGRectMake(100, 140, SCREEN_WIDTH - 200, SCREEN_HEIGHT - 280)]; 37 | // else 38 | // [self.view setFrame:CGRectMake(10, 40, SCREEN_WIDTH - 20, SCREEN_HEIGHT - 80)]; 39 | 40 | [tblOrder setSeparatorStyle:UITableViewCellSeparatorStyleNone]; 41 | 42 | tblOrder.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; 43 | 44 | [tblOrder setBackgroundColor:[UIColor whiteColor]]; 45 | 46 | [tblOrder reloadData]; 47 | } 48 | 49 | - (void)didReceiveMemoryWarning { 50 | 51 | [super didReceiveMemoryWarning]; 52 | } 53 | 54 | #pragma mark - Table view data source 55 | 56 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 57 | { 58 | return 1; 59 | } 60 | 61 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 62 | { 63 | return 10; 64 | } 65 | 66 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 67 | { 68 | return [self getHeightForTransactionCellCellAtIndexPath:indexPath]; 69 | } 70 | 71 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 72 | { 73 | return [self getOrderSummaryCellForRowAtIndexPath:indexPath]; 74 | } 75 | 76 | - (CGFloat)getHeightForTransactionCellCellAtIndexPath:(NSIndexPath *)indexPath 77 | { 78 | return ((UITableViewCell*)[self getOrderSummaryCellForRowAtIndexPath:indexPath]).contentView.frame.size.height; 79 | } 80 | 81 | - (UITableViewCell*)getOrderSummaryCellForRowAtIndexPath:(NSIndexPath*)indexPath 82 | { 83 | OrderSummaryCell *cell; 84 | 85 | NSString *reuseID = [NSString stringWithFormat:@"OrderSummaryCell%d", (int) indexPath.row]; 86 | 87 | if (!cell) 88 | { 89 | cell = [[OrderSummaryCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseID forCurrentObjectKey:[[PaymentSession currentPaymentSession].summaryDetailKeyArray objectAtIndex:indexPath.row] forCurrentObjectValue:[[PaymentSession currentPaymentSession].summaryDetailValueArray objectAtIndex:indexPath.row] forParentFrame:tblOrder.frame]; 90 | 91 | float height = ((CGRectGetMaxY(cell.lblKey.frame) > CGRectGetMaxY(cell.lblValue.frame)) ? CGRectGetMaxY(cell.lblKey.frame) + 16 : CGRectGetMaxY(cell.lblValue.frame) + 16); 92 | 93 | cell.contentView.frame = CGRectMake(0, 0, SCREEN_WIDTH - 20, height); 94 | 95 | [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 96 | } 97 | 98 | return cell; 99 | } 100 | 101 | #pragma mark - Close View 102 | 103 | - (IBAction)clickToClose:(id)sender 104 | { 105 | [_orderSummaryDelegate clickForDismissView]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /iOS_APIParser/Helper/UIViewController+Helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Helper.h 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, ShakeDirection) { 12 | /** Shake left and right */ 13 | ShakeDirectionHorizontal, 14 | /** Shake up and down */ 15 | ShakeDirectionVertical 16 | }; 17 | 18 | @interface UIViewController (Helper) 19 | 20 | //Shake Animation 21 | - (void)_shake:(int)times direction:(int)direction currentTimes:(int)current withDelta:(CGFloat)delta speed:(NSTimeInterval)interval shakeDirection:(ShakeDirection)shakeDirection forView:(UIView*)view completion:(void (^)(void))completionHandler ; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /iOS_APIParser/Helper/UIViewController+Helper.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Helper.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 9/7/18. 6 | // Copyright © 2018 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+Helper.h" 10 | 11 | @implementation UIViewController (Helper) 12 | 13 | #pragma mark - Shake Animation 14 | 15 | - (void)_shake:(int)times direction:(int)direction currentTimes:(int)current withDelta:(CGFloat)delta speed:(NSTimeInterval)interval shakeDirection:(ShakeDirection)shakeDirection forView:(UIView*)view completion:(void (^)(void))completionHandler { 16 | 17 | __weak UIViewController *weakSelf = self; 18 | 19 | [UIView animateWithDuration:interval animations:^{ 20 | view.layer.affineTransform = (shakeDirection == ShakeDirectionHorizontal) ? CGAffineTransformMakeTranslation(delta * direction, 0) : CGAffineTransformMakeTranslation(0, delta * direction); 21 | } completion:^(BOOL finished) { 22 | if(current >= times) { 23 | [UIView animateWithDuration:interval animations:^{ 24 | view.layer.affineTransform = CGAffineTransformIdentity; 25 | } completion:^(BOOL finished){ 26 | if (completionHandler != nil) { 27 | completionHandler(); 28 | } 29 | }]; 30 | return; 31 | } 32 | [weakSelf _shake:(times - 1) 33 | direction:direction * -1 34 | currentTimes:current + 1 35 | withDelta:delta 36 | speed:interval 37 | shakeDirection:shakeDirection 38 | forView:view 39 | completion:completionHandler]; 40 | }]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /iOS_APIParser/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | NSAppTransportSecurity 34 | 35 | NSAllowsArbitraryLoads 36 | 37 | NSExceptionDomains 38 | 39 | akamaihd.net 40 | 41 | NSIncludesSubdomains 42 | 43 | NSThirdPartyExceptionRequiresForwardSecrecy 44 | 45 | 46 | facebook.com 47 | 48 | NSIncludesSubdomains 49 | 50 | NSThirdPartyExceptionRequiresForwardSecrecy 51 | 52 | 53 | fbcdn.net 54 | 55 | NSIncludesSubdomains 56 | 57 | NSThirdPartyExceptionRequiresForwardSecrecy 58 | 59 | 60 | 61 | 62 | UISupportedInterfaceOrientations 63 | 64 | UIInterfaceOrientationPortrait 65 | UIInterfaceOrientationLandscapeLeft 66 | UIInterfaceOrientationLandscapeRight 67 | 68 | UISupportedInterfaceOrientations~ipad 69 | 70 | UIInterfaceOrientationPortrait 71 | UIInterfaceOrientationPortraitUpsideDown 72 | UIInterfaceOrientationLandscapeLeft 73 | UIInterfaceOrientationLandscapeRight 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /iOS_APIParser/Objects/RechargePlanCommonObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // RechargePlanCommonObject.h 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 05/06/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RechargePlanCommonObject : NSObject 12 | 13 | @property (nonatomic, assign) double talktime; 14 | @property (nonatomic, strong) NSString *detail; 15 | @property (nonatomic, strong) NSString *validity; 16 | @property (nonatomic, assign) double price; 17 | 18 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 19 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 20 | - (NSDictionary *)dictionaryRepresentation; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /iOS_APIParser/Objects/RechargePlanCommonObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // RechargePlanCommonObject.m 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 05/06/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import "RechargePlanCommonObject.h" 10 | 11 | NSString *const kRechargeCommonTalktime = @"talktime"; 12 | NSString *const kRechargeCommonDetail = @"detail"; 13 | NSString *const kRechargeCommonValidity = @"validity"; 14 | NSString *const kRechargeCommonPrice = @"price"; 15 | 16 | @interface RechargePlanCommonObject () 17 | 18 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 19 | 20 | @end 21 | 22 | @implementation RechargePlanCommonObject 23 | 24 | @synthesize talktime = _talktime; 25 | @synthesize detail = _detail; 26 | @synthesize validity = _validity; 27 | @synthesize price = _price; 28 | 29 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict 30 | { 31 | return [[self alloc] initWithDictionary:dict]; 32 | } 33 | 34 | - (instancetype)initWithDictionary:(NSDictionary *)dict 35 | { 36 | self = [super init]; 37 | 38 | // This check serves to make sure that a non-NSDictionary object 39 | // passed into the model class doesn't break the parsing. 40 | if(self && [dict isKindOfClass:[NSDictionary class]]) { 41 | self.talktime = [[self objectOrNilForKey:kRechargeCommonTalktime fromDictionary:dict] doubleValue]; 42 | self.detail = [self objectOrNilForKey:kRechargeCommonDetail fromDictionary:dict]; 43 | self.validity = [self objectOrNilForKey:kRechargeCommonValidity fromDictionary:dict]; 44 | self.price = [[self objectOrNilForKey:kRechargeCommonPrice fromDictionary:dict] doubleValue]; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (NSDictionary *)dictionaryRepresentation 51 | { 52 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 53 | [mutableDict setValue:[NSNumber numberWithDouble:self.talktime] forKey:kRechargeCommonTalktime]; 54 | [mutableDict setValue:self.detail forKey:kRechargeCommonDetail]; 55 | [mutableDict setValue:self.validity forKey:kRechargeCommonValidity]; 56 | [mutableDict setValue:[NSNumber numberWithDouble:self.price] forKey:kRechargeCommonPrice]; 57 | 58 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 59 | } 60 | 61 | - (NSString *)description 62 | { 63 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 64 | } 65 | 66 | #pragma mark - Helper Method 67 | 68 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict 69 | { 70 | id object = [dict objectForKey:aKey]; 71 | return [object isEqual:[NSNull null]] ? nil : object; 72 | } 73 | 74 | #pragma mark - NSCoding Methods 75 | 76 | - (id)initWithCoder:(NSCoder *)aDecoder 77 | { 78 | self = [super init]; 79 | 80 | self.talktime = [aDecoder decodeDoubleForKey:kRechargeCommonTalktime]; 81 | self.detail = [aDecoder decodeObjectForKey:kRechargeCommonDetail]; 82 | self.validity = [aDecoder decodeObjectForKey:kRechargeCommonValidity]; 83 | self.price = [aDecoder decodeDoubleForKey:kRechargeCommonPrice]; 84 | return self; 85 | } 86 | 87 | - (void)encodeWithCoder:(NSCoder *)aCoder 88 | { 89 | [aCoder encodeDouble:_talktime forKey:kRechargeCommonTalktime]; 90 | [aCoder encodeObject:_detail forKey:kRechargeCommonDetail]; 91 | [aCoder encodeObject:_validity forKey:kRechargeCommonValidity]; 92 | [aCoder encodeDouble:_price forKey:kRechargeCommonPrice]; 93 | } 94 | 95 | - (id)copyWithZone:(NSZone *)zone 96 | { 97 | RechargePlanCommonObject *copy = [[RechargePlanCommonObject alloc] init]; 98 | 99 | if (copy) { 100 | 101 | copy.talktime = self.talktime; 102 | copy.detail = [self.detail copyWithZone:zone]; 103 | copy.validity = [self.validity copyWithZone:zone]; 104 | copy.price = self.price; 105 | } 106 | 107 | return copy; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /iOS_APIParser/Objects/RechargePlansMainObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // RechargePlansMainObject.h 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 29/05/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RechargePlansMainObject : NSObject 12 | 13 | @property (nonatomic, strong) NSString *imageUrl; 14 | @property (nonatomic, strong) NSString *service; 15 | @property (nonatomic, strong) NSString *circle; 16 | 17 | @property (nonatomic, strong) NSString *rechargePlanTypeName; 18 | @property (nonatomic, strong) NSArray *planObjects; 19 | 20 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 21 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 22 | - (NSDictionary *)dictionaryRepresentation; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /iOS_APIParser/Objects/RechargePlansMainObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // RechargePlansMainObject.m 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 29/05/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import "RechargePlansMainObject.h" 10 | 11 | NSString *const kDATAPlan = @"plan"; 12 | NSString *const kDATAImageUrl = @"imageUrl"; 13 | NSString *const kDATAService = @"service"; 14 | NSString *const kDATACircle = @"circle"; 15 | 16 | NSString *const kDATARechargePlanTypeName = @"planname"; 17 | NSString *const kDATAPlanObjects = @"planobjects"; 18 | 19 | 20 | @interface RechargePlansMainObject () 21 | 22 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 23 | 24 | @end 25 | 26 | @implementation RechargePlansMainObject 27 | 28 | @synthesize imageUrl = _imageUrl; 29 | @synthesize service = _service; 30 | @synthesize circle = _circle; 31 | 32 | 33 | @synthesize rechargePlanTypeName = _rechargePlanTypeName; 34 | @synthesize planObjects = _planObjects; 35 | 36 | 37 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict 38 | { 39 | return [[self alloc] initWithDictionary:dict]; 40 | } 41 | 42 | - (instancetype)initWithDictionary:(NSDictionary *)dict 43 | { 44 | self = [super init]; 45 | 46 | // This check serves to make sure that a non-NSDictionary object 47 | // passed into the model class doesn't break the parsing. 48 | if(self && [dict isKindOfClass:[NSDictionary class]]) { 49 | self.imageUrl = [self objectOrNilForKey:kDATAImageUrl fromDictionary:dict]; 50 | self.service = [self objectOrNilForKey:kDATAService fromDictionary:dict]; 51 | self.circle = [self objectOrNilForKey:kDATACircle fromDictionary:dict]; 52 | } 53 | 54 | return self; 55 | } 56 | 57 | - (NSDictionary *)dictionaryRepresentation 58 | { 59 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 60 | [mutableDict setValue:self.imageUrl forKey:kDATAImageUrl]; 61 | [mutableDict setValue:self.service forKey:kDATAService]; 62 | [mutableDict setValue:self.circle forKey:kDATACircle]; 63 | [mutableDict setValue:self.rechargePlanTypeName forKey:kDATARechargePlanTypeName]; 64 | [mutableDict setValue:self.planObjects forKey:kDATAPlanObjects]; 65 | 66 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 67 | } 68 | 69 | - (NSString *)description 70 | { 71 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 72 | } 73 | 74 | #pragma mark - Helper Method 75 | 76 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict 77 | { 78 | id object = [dict objectForKey:aKey]; 79 | return [object isEqual:[NSNull null]] ? nil : object; 80 | } 81 | 82 | #pragma mark - NSCoding Methods 83 | 84 | - (id)initWithCoder:(NSCoder *)aDecoder 85 | { 86 | self = [super init]; 87 | 88 | self.imageUrl = [aDecoder decodeObjectForKey:kDATAImageUrl]; 89 | self.service = [aDecoder decodeObjectForKey:kDATAService]; 90 | self.circle = [aDecoder decodeObjectForKey:kDATACircle]; 91 | self.rechargePlanTypeName = [aDecoder decodeObjectForKey:kDATARechargePlanTypeName]; 92 | self.planObjects = [aDecoder decodeObjectForKey:kDATAPlanObjects]; 93 | 94 | return self; 95 | } 96 | 97 | - (void)encodeWithCoder:(NSCoder *)aCoder 98 | { 99 | [aCoder encodeObject:_imageUrl forKey:kDATAImageUrl]; 100 | [aCoder encodeObject:_service forKey:kDATAService]; 101 | [aCoder encodeObject:_circle forKey:kDATACircle]; 102 | 103 | [aCoder encodeObject:_rechargePlanTypeName forKey:kDATARechargePlanTypeName]; 104 | 105 | [aCoder encodeObject:_planObjects forKey:kDATAPlanObjects]; 106 | } 107 | 108 | - (id)copyWithZone:(NSZone *)zone 109 | { 110 | RechargePlansMainObject *copy = [[RechargePlansMainObject alloc] init]; 111 | 112 | if (copy) { 113 | 114 | copy.imageUrl = [self.imageUrl copyWithZone:zone]; 115 | copy.service = [self.service copyWithZone:zone]; 116 | copy.circle = [self.circle copyWithZone:zone]; 117 | copy.rechargePlanTypeName = [self.rechargePlanTypeName copyWithZone:zone]; 118 | copy.planObjects = [self.planObjects copyWithZone:zone]; 119 | } 120 | 121 | return copy; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /iOS_APIParser/Objects/RechargeTurboObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // RechargeTurboObject.h 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 07/08/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CircleObject.h" 11 | 12 | //Service 13 | @interface Service : NSObject 14 | 15 | @property (nonatomic, assign) double serviceIdentifier; 16 | @property (nonatomic, strong) NSString *name; 17 | 18 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 19 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 20 | - (NSDictionary *)dictionaryRepresentation; 21 | 22 | @end 23 | 24 | 25 | 26 | //Recharge 27 | @interface Recharge : NSObject 28 | 29 | @property (nonatomic, assign) double rechargeIdentifier; 30 | @property (nonatomic, assign) double amount; 31 | @property (nonatomic, assign) BOOL topUp; 32 | 33 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 34 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 35 | - (NSDictionary *)dictionaryRepresentation; 36 | 37 | @end 38 | 39 | 40 | 41 | //Company 42 | @interface Company : NSObject 43 | 44 | @property (nonatomic, strong) Service *service; 45 | @property (nonatomic, assign) double companyIdentifier; 46 | @property (nonatomic, strong) NSString *imageUrl; 47 | @property (nonatomic, strong) NSString *smsCode; 48 | @property (nonatomic, assign) BOOL rechargeTypeRequired; 49 | @property (nonatomic, strong) NSString *label; 50 | @property (nonatomic, strong) NSString *updatedOn; 51 | @property (nonatomic, strong) NSString *name; 52 | @property (nonatomic, assign) BOOL showRechargeType; 53 | 54 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 55 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 56 | - (NSDictionary *)dictionaryRepresentation; 57 | 58 | @end 59 | 60 | 61 | 62 | 63 | //Turbo Main Object 64 | 65 | @interface RechargeTurboObject : NSObject 66 | 67 | @property (nonatomic, strong) NSString *mobile; 68 | @property (nonatomic, assign) double userId; 69 | @property (nonatomic, strong) CircleObject *circle; 70 | @property (nonatomic, strong) NSArray *recharge; 71 | @property (nonatomic, strong) Company *company; 72 | @property (nonatomic, strong) NSString *circleId; 73 | @property (nonatomic, strong) NSString *companyId; 74 | 75 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict; 76 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 77 | - (NSDictionary *)dictionaryRepresentation; 78 | 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /iOS_APIParser/Objects/RechargeTurboObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // RechargeTurboObject.m 3 | // FastTicket 4 | // 5 | // Created by Dhruvik Rao on 07/08/15. 6 | // Copyright (c) 2015 Sujav Group. All rights reserved. 7 | // 8 | 9 | #import "RechargeTurboObject.h" 10 | 11 | 12 | //Service 13 | NSString *const kServiceId = @"id"; 14 | NSString *const kServiceName = @"name"; 15 | 16 | 17 | @interface Service () 18 | 19 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 20 | 21 | @end 22 | 23 | @implementation Service 24 | 25 | @synthesize serviceIdentifier = _serviceIdentifier; 26 | @synthesize name = _name; 27 | 28 | 29 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict 30 | { 31 | return [[self alloc] initWithDictionary:dict]; 32 | } 33 | 34 | - (instancetype)initWithDictionary:(NSDictionary *)dict 35 | { 36 | self = [super init]; 37 | 38 | // This check serves to make sure that a non-NSDictionary object 39 | // passed into the model class doesn't break the parsing. 40 | if(self && [dict isKindOfClass:[NSDictionary class]]) { 41 | self.serviceIdentifier = [[self objectOrNilForKey:kServiceId fromDictionary:dict] doubleValue]; 42 | self.name = [self objectOrNilForKey:kServiceName fromDictionary:dict]; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | - (NSDictionary *)dictionaryRepresentation 49 | { 50 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 51 | [mutableDict setValue:[NSNumber numberWithDouble:self.serviceIdentifier] forKey:kServiceId]; 52 | [mutableDict setValue:self.name forKey:kServiceName]; 53 | 54 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 55 | } 56 | 57 | - (NSString *)description 58 | { 59 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 60 | } 61 | 62 | #pragma mark - Helper Method 63 | 64 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict 65 | { 66 | id object = [dict objectForKey:aKey]; 67 | return [object isEqual:[NSNull null]] ? nil : object; 68 | } 69 | 70 | #pragma mark - NSCoding Methods 71 | 72 | - (id)initWithCoder:(NSCoder *)aDecoder 73 | { 74 | self = [super init]; 75 | 76 | self.serviceIdentifier = [aDecoder decodeDoubleForKey:kServiceId]; 77 | self.name = [aDecoder decodeObjectForKey:kServiceName]; 78 | return self; 79 | } 80 | 81 | - (void)encodeWithCoder:(NSCoder *)aCoder 82 | { 83 | 84 | [aCoder encodeDouble:_serviceIdentifier forKey:kServiceId]; 85 | [aCoder encodeObject:_name forKey:kServiceName]; 86 | } 87 | 88 | - (id)copyWithZone:(NSZone *)zone 89 | { 90 | Service *copy = [[Service alloc] init]; 91 | 92 | if (copy) { 93 | 94 | copy.serviceIdentifier = self.serviceIdentifier; 95 | copy.name = [self.name copyWithZone:zone]; 96 | } 97 | 98 | return copy; 99 | } 100 | 101 | 102 | @end 103 | 104 | 105 | 106 | //Company 107 | NSString *const kCompanyService = @"service"; 108 | NSString *const kCompanyId = @"id"; 109 | NSString *const kCompanyImageUrl = @"imageUrl"; 110 | NSString *const kCompanySmsCode = @"smsCode"; 111 | NSString *const kCompanyRechargeTypeRequired = @"rechargeTypeRequired"; 112 | NSString *const kCompanyLabel = @"label"; 113 | NSString *const kCompanyUpdatedOn = @"updatedOn"; 114 | NSString *const kCompanyName = @"name"; 115 | NSString *const kShowRechargeType = @"showRechargeType"; 116 | 117 | @interface Company () 118 | 119 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 120 | 121 | @end 122 | 123 | @implementation Company 124 | 125 | @synthesize service = _service; 126 | @synthesize companyIdentifier = _companyIdentifier; 127 | @synthesize imageUrl = _imageUrl; 128 | @synthesize smsCode = _smsCode; 129 | @synthesize rechargeTypeRequired = _rechargeTypeRequired; 130 | @synthesize label = _label; 131 | @synthesize updatedOn = _updatedOn; 132 | @synthesize name = _name; 133 | @synthesize showRechargeType = _showRechargeType; 134 | 135 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict 136 | { 137 | return [[self alloc] initWithDictionary:dict]; 138 | } 139 | 140 | - (instancetype)initWithDictionary:(NSDictionary *)dict 141 | { 142 | self = [super init]; 143 | 144 | // This check serves to make sure that a non-NSDictionary object 145 | // passed into the model class doesn't break the parsing. 146 | if(self && [dict isKindOfClass:[NSDictionary class]]) { 147 | self.service = [Service modelObjectWithDictionary:[dict objectForKey:kCompanyService]]; 148 | self.companyIdentifier = [[self objectOrNilForKey:kCompanyId fromDictionary:dict] doubleValue]; 149 | self.imageUrl = [self objectOrNilForKey:kCompanyImageUrl fromDictionary:dict]; 150 | self.smsCode = [self objectOrNilForKey:kCompanySmsCode fromDictionary:dict]; 151 | self.rechargeTypeRequired = [[self objectOrNilForKey:kCompanyRechargeTypeRequired fromDictionary:dict] boolValue]; 152 | self.showRechargeType = [[self objectOrNilForKey:kShowRechargeType fromDictionary:dict] boolValue]; 153 | self.label = [self objectOrNilForKey:kCompanyLabel fromDictionary:dict]; 154 | self.updatedOn = [self objectOrNilForKey:kCompanyUpdatedOn fromDictionary:dict]; 155 | self.name = [self objectOrNilForKey:kCompanyName fromDictionary:dict]; 156 | } 157 | 158 | return self; 159 | } 160 | 161 | - (NSDictionary *)dictionaryRepresentation 162 | { 163 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 164 | [mutableDict setValue:[self.service dictionaryRepresentation] forKey:kCompanyService]; 165 | [mutableDict setValue:[NSNumber numberWithDouble:self.companyIdentifier] forKey:kCompanyId]; 166 | [mutableDict setValue:self.imageUrl forKey:kCompanyImageUrl]; 167 | [mutableDict setValue:self.smsCode forKey:kCompanySmsCode]; 168 | [mutableDict setValue:[NSNumber numberWithBool:self.rechargeTypeRequired] forKey:kCompanyRechargeTypeRequired]; 169 | [mutableDict setValue:[NSNumber numberWithBool:self.showRechargeType] forKey:kShowRechargeType]; 170 | [mutableDict setValue:self.label forKey:kCompanyLabel]; 171 | [mutableDict setValue:self.updatedOn forKey:kCompanyUpdatedOn]; 172 | [mutableDict setValue:self.name forKey:kCompanyName]; 173 | 174 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 175 | } 176 | 177 | - (NSString *)description 178 | { 179 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 180 | } 181 | 182 | #pragma mark - Helper Method 183 | 184 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict 185 | { 186 | id object = [dict objectForKey:aKey]; 187 | return [object isEqual:[NSNull null]] ? nil : object; 188 | } 189 | 190 | #pragma mark - NSCoding Methods 191 | 192 | - (id)initWithCoder:(NSCoder *)aDecoder 193 | { 194 | self = [super init]; 195 | 196 | self.service = [aDecoder decodeObjectForKey:kCompanyService]; 197 | self.companyIdentifier = [aDecoder decodeDoubleForKey:kCompanyId]; 198 | self.imageUrl = [aDecoder decodeObjectForKey:kCompanyImageUrl]; 199 | self.smsCode = [aDecoder decodeObjectForKey:kCompanySmsCode]; 200 | self.rechargeTypeRequired = [aDecoder decodeBoolForKey:kCompanyRechargeTypeRequired]; 201 | self.showRechargeType = [aDecoder decodeBoolForKey:kShowRechargeType]; 202 | self.label = [aDecoder decodeObjectForKey:kCompanyLabel]; 203 | self.updatedOn = [aDecoder decodeObjectForKey:kCompanyUpdatedOn]; 204 | self.name = [aDecoder decodeObjectForKey:kCompanyName]; 205 | return self; 206 | } 207 | 208 | - (void)encodeWithCoder:(NSCoder *)aCoder 209 | { 210 | [aCoder encodeObject:_service forKey:kCompanyService]; 211 | [aCoder encodeDouble:_companyIdentifier forKey:kCompanyId]; 212 | [aCoder encodeObject:_imageUrl forKey:kCompanyImageUrl]; 213 | [aCoder encodeObject:_smsCode forKey:kCompanySmsCode]; 214 | [aCoder encodeBool:_rechargeTypeRequired forKey:kCompanyRechargeTypeRequired]; 215 | [aCoder encodeBool:_showRechargeType forKey:kShowRechargeType]; 216 | [aCoder encodeObject:_label forKey:kCompanyLabel]; 217 | [aCoder encodeObject:_updatedOn forKey:kCompanyUpdatedOn]; 218 | [aCoder encodeObject:_name forKey:kCompanyName]; 219 | } 220 | 221 | - (id)copyWithZone:(NSZone *)zone 222 | { 223 | Company *copy = [[Company alloc] init]; 224 | 225 | if (copy) { 226 | 227 | copy.service = [self.service copyWithZone:zone]; 228 | copy.companyIdentifier = self.companyIdentifier; 229 | copy.imageUrl = [self.imageUrl copyWithZone:zone]; 230 | copy.smsCode = [self.smsCode copyWithZone:zone]; 231 | copy.rechargeTypeRequired = self.rechargeTypeRequired; 232 | copy.showRechargeType = self.showRechargeType; 233 | copy.label = [self.label copyWithZone:zone]; 234 | copy.updatedOn = [self.updatedOn copyWithZone:zone]; 235 | copy.name = [self.name copyWithZone:zone]; 236 | } 237 | 238 | return copy; 239 | } 240 | 241 | 242 | @end 243 | 244 | 245 | 246 | //Recharge 247 | 248 | NSString *const kRechargeId = @"id"; 249 | NSString *const kRechargeAmount = @"amount"; 250 | NSString *const kRechargeTopUp = @"topUp"; 251 | 252 | 253 | @interface Recharge () 254 | 255 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 256 | 257 | @end 258 | 259 | @implementation Recharge 260 | 261 | @synthesize rechargeIdentifier = _rechargeIdentifier; 262 | @synthesize amount = _amount; 263 | @synthesize topUp = _topUp; 264 | 265 | 266 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict 267 | { 268 | return [[self alloc] initWithDictionary:dict]; 269 | } 270 | 271 | - (instancetype)initWithDictionary:(NSDictionary *)dict 272 | { 273 | self = [super init]; 274 | 275 | // This check serves to make sure that a non-NSDictionary object 276 | // passed into the model class doesn't break the parsing. 277 | if(self && [dict isKindOfClass:[NSDictionary class]]) { 278 | self.rechargeIdentifier = [[self objectOrNilForKey:kRechargeId fromDictionary:dict] doubleValue]; 279 | self.amount = [[self objectOrNilForKey:kRechargeAmount fromDictionary:dict] doubleValue]; 280 | self.topUp = [[self objectOrNilForKey:kRechargeTopUp fromDictionary:dict] boolValue]; 281 | } 282 | 283 | return self; 284 | } 285 | 286 | - (NSDictionary *)dictionaryRepresentation 287 | { 288 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 289 | [mutableDict setValue:[NSNumber numberWithDouble:self.rechargeIdentifier] forKey:kRechargeId]; 290 | [mutableDict setValue:[NSNumber numberWithDouble:self.amount] forKey:kRechargeAmount]; 291 | [mutableDict setValue:[NSNumber numberWithBool:self.topUp] forKey:kRechargeTopUp]; 292 | 293 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 294 | } 295 | 296 | - (NSString *)description 297 | { 298 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 299 | } 300 | 301 | #pragma mark - Helper Method 302 | 303 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict 304 | { 305 | id object = [dict objectForKey:aKey]; 306 | return [object isEqual:[NSNull null]] ? nil : object; 307 | } 308 | 309 | #pragma mark - NSCoding Methods 310 | 311 | - (id)initWithCoder:(NSCoder *)aDecoder 312 | { 313 | self = [super init]; 314 | 315 | self.rechargeIdentifier = [aDecoder decodeDoubleForKey:kRechargeId]; 316 | self.amount = [aDecoder decodeDoubleForKey:kRechargeAmount]; 317 | self.topUp = [aDecoder decodeBoolForKey:kRechargeTopUp]; 318 | return self; 319 | } 320 | 321 | - (void)encodeWithCoder:(NSCoder *)aCoder 322 | { 323 | 324 | [aCoder encodeDouble:_rechargeIdentifier forKey:kRechargeId]; 325 | [aCoder encodeDouble:_amount forKey:kRechargeAmount]; 326 | [aCoder encodeBool:_topUp forKey:kRechargeTopUp]; 327 | } 328 | 329 | - (id)copyWithZone:(NSZone *)zone 330 | { 331 | Recharge *copy = [[Recharge alloc] init]; 332 | 333 | if (copy) { 334 | 335 | copy.rechargeIdentifier = self.rechargeIdentifier; 336 | copy.amount = self.amount; 337 | copy.topUp = self.topUp; 338 | } 339 | 340 | return copy; 341 | } 342 | 343 | 344 | @end 345 | 346 | 347 | 348 | //RechargeTurbo Main Object 349 | 350 | NSString *const kRechargeTurboMobile = @"mobile"; 351 | NSString *const kRechargeTurboUserId = @"userId"; 352 | NSString *const kRechargeTurboCircle = @"circle"; 353 | NSString *const kRechargeTurboRecharge = @"recharge"; 354 | NSString *const kRechargeTurboCompany = @"company"; 355 | NSString *const kRechargeTurboCircleId = @"circleId"; 356 | NSString *const kRechargeTurboCompanyId = @"companyId"; 357 | 358 | @interface RechargeTurboObject () 359 | 360 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict; 361 | 362 | @end 363 | 364 | @implementation RechargeTurboObject 365 | 366 | 367 | @synthesize mobile = _mobile; 368 | @synthesize userId = _userId; 369 | @synthesize circle = _circle; 370 | @synthesize recharge = _recharge; 371 | @synthesize company = _company; 372 | @synthesize circleId = _circleId; 373 | @synthesize companyId = _companyId; 374 | 375 | 376 | + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict 377 | { 378 | return [[self alloc] initWithDictionary:dict]; 379 | } 380 | 381 | - (instancetype)initWithDictionary:(NSDictionary *)dict 382 | { 383 | self = [super init]; 384 | 385 | // This check serves to make sure that a non-NSDictionary object 386 | // passed into the model class doesn't break the parsing. 387 | if(self && [dict isKindOfClass:[NSDictionary class]]) { 388 | self.mobile = [self objectOrNilForKey:kRechargeTurboMobile fromDictionary:dict]; 389 | self.userId = [[self objectOrNilForKey:kRechargeTurboUserId fromDictionary:dict] doubleValue]; 390 | self.circle = [CircleObject modelObjectWithDictionary:[dict objectForKey:kRechargeTurboCircle]]; 391 | 392 | NSObject *receivedRecharge = [dict objectForKey:kRechargeTurboRecharge]; 393 | NSMutableArray *parsedRecharge = [NSMutableArray array]; 394 | if ([receivedRecharge isKindOfClass:[NSArray class]]) { 395 | for (NSDictionary *item in (NSArray *)receivedRecharge) { 396 | if ([item isKindOfClass:[NSDictionary class]]) { 397 | [parsedRecharge addObject:[Recharge modelObjectWithDictionary:item]]; 398 | } 399 | } 400 | } else if ([receivedRecharge isKindOfClass:[NSDictionary class]]) { 401 | [parsedRecharge addObject:[Recharge modelObjectWithDictionary:(NSDictionary *)receivedRecharge]]; 402 | } 403 | 404 | self.recharge = [NSArray arrayWithArray:parsedRecharge]; 405 | self.company = [Company modelObjectWithDictionary:[dict objectForKey:kRechargeTurboCompany]]; 406 | self.circleId = [self objectOrNilForKey:kRechargeTurboCircleId fromDictionary:dict]; 407 | self.companyId = [self objectOrNilForKey:kRechargeTurboCompanyId fromDictionary:dict]; 408 | } 409 | 410 | return self; 411 | } 412 | 413 | - (NSDictionary *)dictionaryRepresentation 414 | { 415 | NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 416 | [mutableDict setValue:self.mobile forKey:kRechargeTurboMobile]; 417 | [mutableDict setValue:[NSNumber numberWithDouble:self.userId] forKey:kRechargeTurboUserId]; 418 | [mutableDict setValue:[self.circle dictionaryRepresentation] forKey:kRechargeTurboCircle]; 419 | 420 | NSMutableArray *tempArrayForRecharge = [NSMutableArray array]; 421 | for (NSObject *subArrayObject in self.recharge) { 422 | if([subArrayObject respondsToSelector:@selector(dictionaryRepresentation)]) { 423 | // This class is a model object 424 | [tempArrayForRecharge addObject:[subArrayObject performSelector:@selector(dictionaryRepresentation)]]; 425 | } else { 426 | // Generic object 427 | [tempArrayForRecharge addObject:subArrayObject]; 428 | } 429 | } 430 | [mutableDict setValue:[NSArray arrayWithArray:tempArrayForRecharge] forKey:kRechargeTurboRecharge]; 431 | [mutableDict setValue:[self.company dictionaryRepresentation] forKey:kRechargeTurboCompany]; 432 | [mutableDict setValue:self.circleId forKey:kRechargeTurboCircleId]; 433 | [mutableDict setValue:self.companyId forKey:kRechargeTurboCompanyId]; 434 | 435 | return [NSDictionary dictionaryWithDictionary:mutableDict]; 436 | } 437 | 438 | - (NSString *)description 439 | { 440 | return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]]; 441 | } 442 | 443 | #pragma mark - Helper Method 444 | 445 | - (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict 446 | { 447 | id object = [dict objectForKey:aKey]; 448 | return [object isEqual:[NSNull null]] ? nil : object; 449 | } 450 | 451 | #pragma mark - NSCoding Methods 452 | 453 | - (id)initWithCoder:(NSCoder *)aDecoder 454 | { 455 | self = [super init]; 456 | 457 | self.mobile = [aDecoder decodeObjectForKey:kRechargeTurboMobile]; 458 | self.userId = [aDecoder decodeDoubleForKey:kRechargeTurboUserId]; 459 | self.circle = [aDecoder decodeObjectForKey:kRechargeTurboCircle]; 460 | self.recharge = [aDecoder decodeObjectForKey:kRechargeTurboRecharge]; 461 | self.company = [aDecoder decodeObjectForKey:kRechargeTurboCompany]; 462 | self.circleId = [aDecoder decodeObjectForKey:kRechargeTurboCircleId]; 463 | self.companyId = [aDecoder decodeObjectForKey:kRechargeTurboCompanyId]; 464 | return self; 465 | } 466 | 467 | - (void)encodeWithCoder:(NSCoder *)aCoder 468 | { 469 | [aCoder encodeObject:_mobile forKey:kRechargeTurboMobile]; 470 | [aCoder encodeDouble:_userId forKey:kRechargeTurboUserId]; 471 | [aCoder encodeObject:_circle forKey:kRechargeTurboCircle]; 472 | [aCoder encodeObject:_recharge forKey:kRechargeTurboRecharge]; 473 | [aCoder encodeObject:_company forKey:kRechargeTurboCompany]; 474 | [aCoder encodeObject:_circleId forKey:kRechargeTurboCircleId]; 475 | [aCoder encodeObject:_companyId forKey:kRechargeTurboCompanyId]; 476 | } 477 | 478 | - (id)copyWithZone:(NSZone *)zone 479 | { 480 | RechargeTurboObject *copy = [[RechargeTurboObject alloc] init]; 481 | 482 | if (copy) { 483 | 484 | copy.mobile = [self.mobile copyWithZone:zone]; 485 | copy.userId = self.userId; 486 | copy.circle = [self.circle copyWithZone:zone]; 487 | copy.recharge = [self.recharge copyWithZone:zone]; 488 | copy.company = [self.company copyWithZone:zone]; 489 | copy.circleId = [self.circleId copyWithZone:zone]; 490 | copy.companyId = [self.companyId copyWithZone:zone]; 491 | } 492 | 493 | return copy; 494 | } 495 | 496 | @end 497 | -------------------------------------------------------------------------------- /iOS_APIParser/iOS_APIParser-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // iOS_APIParser-Prefix.pch 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #ifndef iOS_APIParser_Prefix_pch 10 | #define iOS_APIParser_Prefix_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 | 15 | #import "AppDelegate.h" 16 | #import "AppMacros.h" 17 | #import "APIParser.h" 18 | 19 | #endif /* iOS_APIParser_Prefix_pch */ 20 | -------------------------------------------------------------------------------- /iOS_APIParser/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOS_APIParser 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. 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 | -------------------------------------------------------------------------------- /iOS_APIParserTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOS_APIParserTests/iOS_APIParserTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iOS_APIParserTests.m 3 | // iOS_APIParserTests 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iOS_APIParserTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation iOS_APIParserTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /iOS_APIParserUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOS_APIParserUITests/iOS_APIParserUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iOS_APIParserUITests.m 3 | // iOS_APIParserUITests 4 | // 5 | // Created by Dhruvik Rao on 16/11/15. 6 | // Copyright © 2015 Dhruvik Rao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iOS_APIParserUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation iOS_APIParserUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------