According to the specifics of the work, I have to conduct several (5-10) projects at the same time, and often return to project coding after a significant pause, a month or more. This feature requires the organization of code that allows you to quickly recall the architecture of the project.
Also, to save time and resources, I use common classes for MacOS and iOS versions of my application.
For those to whom features of my experience are interesting - I ask under kat.
In many projects that I studied in the process, I saw excessive complications in the organization of classes. Unnecessary file splitting causes confusion in understanding the global code structure. The passion for class division complicates the understanding of the functional parts of the code.
As a result, I dwelt on the following principles of project organization:
1. I abandoned the subclasses in the project, besides the required ones - UIViewController, UITableViewCell
2. All interaction with the external server is rendered into a separate class (I will tell you how to organize it in the second part, I have this multiplatform class)
3. All subclasses of UIViewControllers are named with the correct names (MyViewConfroller1 is the wrong name, MessagesViewController associated with the Messages button is the correct name)
4. All subclasses of TableViewCells are located next to the ViewControllers and are named correctly (MyTableViewCell is incorrect, MessagesTableViewCell is correct)
5. In the resources I create folders with all the pictures and place these folders next to the class file (MessagesImages folder).
')
This organization helps to quickly get to the desired file and as a result of the code from the left side of Xcode.
Combining the code in one project for MacOS and IOS provides a significant gain in speed of development / refinement. The change (correction) in the general classes is applied immediately for both systems. It is possible to use the same pictures for both projects. However, such an organization has its own characteristics:
1. When creating a target, immediately provide AppDelegate prefix. Ideal - IOSAppDelegate MacOSAppDelegate
2. Xcode has a bug with displaying code in divided panels, so it’s not desirable to call the same names the UIViewController and NSViewController subclasses in both projects. MessagesIOSViewController and MessagesMacOSViewController respectively are good names.
General classes are placed in the top project in a separate directory with a good name ServerIteractionClasses for example.
Since all interaction with the server often implies a decent wait, any interaction with the server from the view controllers is as follows:
1. Creating a class instance
ClientController *clientController = [[ClientController alloc] init]; clientController.sender = self;
where is sender it
@property (strong) id sender;
Start the necessary function
[clientController startPasswordRecoveryForEmail:email];
Where
-(void) updateUIwithMessage:(NSString *)message andProgressPercent:(NSNumber *)percent; { if (self.sender && [self.sender respondsToSelector:@selector(updateUIWithData:)]) { [sender performSelector:@selector(updateUIWithData:) withObject:[NSArray arrayWithObjects:message,percent,nil]]; } } -(void) startPasswordRecoveryForEmail:(NSString *)email; { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^(void) {
Further, all changes in the interface are made only by the callbacks in the corresponding view controller (do not forget to go to main thread for interface changes):
#pragma mark - ClientControllerDelegate -(void)updateUIWithData:(NSArray *)data; { //NSLog(@"ClientControllerDelegate:>>>>>>>%@",data); NSString *message = [data objectAtIndex:0]; NSNumber *progressNumber = nil; if (data.count == 2) progressNumber = [data objectAtIndex:1]; if ([message isEqualToString:@"didSendBodyData"] || [message isEqualToString:@"didSendBodyData"] || [message isEqualToString:@"didReceiveData"]) { dispatch_async(dispatch_get_main_queue(), ^(void) { self.progressDownloading.progress = progressNumber.floatValue; self.progressDownloading.hidden = NO; }); } else { dispatch_async(dispatch_get_main_queue(), ^(void) { self.progressDownloading.hidden = YES; }); } BOOL isDidFailWithError = ([message rangeOfString:@"didFailWithError"].location != NSNotFound); if (isDidFailWithError) { NSArray *allBlocks = [message componentsSeparatedByString:@":"]; NSString *errorMessageReceived = @""; if (allBlocks.count > 1) errorMessageReceived = [allBlocks objectAtIndex:1]; dispatch_async(dispatch_get_main_queue(), ^(void) { [self showErrorMessage:errorMessageReceived]; }); }
The technique allows you to transfer data in a callback, separated by a colon.
This option allows you to very quickly transfer the necessary code to macos from iOS (do not forget to name the interface elements equally in iOS and macos versions).
If you like the article, I will continue the organization of the northern part.