Tag: Objective C

  • iOS – How to remove “Back” text from the back button

    The best solution is to create base classes for UIViewController and UITableViewController and override their init methods. This will allow you to add ViewControllers to the NavigationController programmatically after a rootViewController. If you put this code in the ViewDidLoad method, it will not be called in this case and the next controller will be pushed with a back text.

    BaseViewController in Objective C:

    #import "BaseViewController.h"
    
    @interface BaseViewController ()
    
    @end
    
    @implementation BaseViewController
    
    - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
     if (self) {
     self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
     }
     return self;
    }
    
    @end
    

    BaseTableViewController:

    #import "BaseTableViewController.h"
    
    @interface BaseTableViewController ()
    
    @end
    
    @implementation BaseTableViewController
    
    - (instancetype)initWithStyle:(UITableViewStyle)style
    {
     self = [super initWithStyle:style];
     if (self) {
     self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
     }
     return self;
    }
    
    @end
    
  • Using RACCommand and creating custom RACSignals in Objective C

    To bind some action to the button click one can use just a custom RACSignal. But then you have to add three more things in every case:
    1. Disable button, while action is performing;
    2. Show, that action is in progress;
    3. Disable button, if input is incorrect and button should not be able to be tapped.

    Instead, if you use RACCommand, you get all these things in a box.

    Let’s say, we want to bind RACCommand verifyPhoneCommand to a button. We can create a command in a lazy property in a ViewModel:

    - (RACCommand *)verifyPhoneCommand
    {
        if (! _verifyPhoneCommand) {
            _verifyPhoneCommand = [[RACCommand alloc] initWithEnabled:self.phoneValidSignal
                                                          signalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
                                                              return [self verifyPhone];
                                                          }];
        }
        return _verifyPhoneCommand;
    }
    

    Here phoneValidSignal is this signal, that is formed by observing a phone variable:

    - (RACSignal *)phoneValidSignal
    {
        if (!_phoneValidSignal) {
            _phoneValidSignal = [RACObserve(self, phone) map:^id(NSString *phone) {
                return @(phone.length > 0);
            }];
        }
        return _phoneValidSignal;
    }
    

    We pass a RACSignal verifyPhone to the RACCommand to do a job:

    - (RACSignal *)verifyPhone
    {
        return [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
    
            [[PhoneManager sharedManager]
             requestVerifyPhone:self.phone
             success:^{
    
                 [subscriber sendNext:@(YES)];
                 [subscriber sendCompleted];
                 
             } failure:^(NSError *error) {
                 
                 [subscriber sendError:error];
                 
             }];
            
            return nil;
        }];
    }
    

    This is how we bind a RACCommand to a button:

    self.smsRequestButton.rac_command = self.viewModel.verifyPhoneCommand;
    

    To track execution of a RACCommand and show an activity indicator we can use executing property:

    [self.viewModel.verifyPhoneCommand.executing subscribeNext:^(NSNumber*  _Nullable x) {
            if (x.boolValue) {
                [self.spinnerView startAnimating];
            }
            else {
                [self.spinnerView stopAnimating];
            }
        }];
    

    If errors happen during RACCommand execution we can process those errors:

    [self.viewModel.verifyPhoneCommand.errors subscribeNext:^(NSError * _Nullable error) {
            [ErrorUtil showError:error from:self onRepeat:^{
                
            }];
        }];