StateViewController 0.8.0

StateViewController 0.8.0

TestsTested
LangLanguage Obj-CObjective C
License MIT
ReleasedLast Release Feb 2021

Maintained by Pavol Kmet, Pavol Kmeť.



StateViewController

Version License Platform

A view controller category which presents UIViews for loading, error and empty states.

Requirements

  • iOS 8.0+
  • Xcode 7.0+
  • Objective-C

It's also compatible with Swift.

Installation

CocoaPods

StateViewController is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'StateViewController'

Then just run pod install.

Manually

Just drag and drop all files from folder Source in the StateViewController into your project and select Copy items if needed.

Overview

State View Controller allows you to easily manager four most common states:

  • Loading state: View controller loads data from network. Loading view is presented.
  • Error state: An error occurred while loading data from network. Error view is presented.
  • Empty state: Data has been retrieved, but content is not available. Empty view is presented.
  • Content state: Content is available and it's presented.

Usage

First make sure that you have imported category.

CocoaPods

#import <StateViewController/UIViewController+StateViewController.h>

Manually

#import "UIViewController+StateViewController.h"

Then make sure that your UIViewController or UITableViewController or UICollectionViewController adopts protocol StateViewController.

@interface ViewController () <StateViewController>
 // Code
@end

Then, configure the loadingView, emptyView and errorView properties in viewDidLoad.

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.loadingView = // Custom loading view type of UIView
    self.errorView = // Custom error view type of UIView
    self.emptyView = // Custom empty view type of UIView
}

After that in viewWillAppear: method you must call setupInitialState method which setup as method name says initial state of view controller.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    [self setupInitialState];
}

After that, simply tell the view controller whenever content is loading and StateViewController will take care of showing and hiding the correct loading, error and empty view for you.

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // After setting loading, error, empty views
    [self fetchData];
}

- (void)fetchData
{
    [self startLoadingAnimated:YES completion:nil];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
        //
        [self endLoadingAnimated:YES error:error completion:nil];
    }];
    [task resume];
}

Life cycle

StateViewController calls the hasContent method to check if there is any content to display. If you do not implement this method in your own UIViewController, StateViewController will always assume that there is no content to display.

But if your view controller is kind of class UITableViewController or UICollectionViewController, StateViewController in default implementation check if numberOfSections > 0.

- (BOOL)hasContent
{
    return self.people.count > 0;
}

Also you might also be interested to respond to an error even if content is already shown. StateViewController will not show an errorView in this case, because there is already content that can be shown.

To e.g. show a custom alert or other error message, use handleErrorWhenContentsAvailable: to manually present the error to the user.

- (void)handleErrorWhenContentsAvailable:(NSError *)error
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error" message:error.localizedDescription preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
    
    [self presentViewController:alert animated:YES completion:nil];
}

Configuration

If your view (loading, error, empty) should have insets you can implement in you view controller method with name insetForStateView: which is called every time before the view is presented.

- (UIEdgeInsets)insetForStateView:(UIView *)stateView
{
    return UIEdgeInsetsZero;
}

You can also customize your views (empty view, error view) before each view is added to view hierarchy.

Empty view

- (UIView *)configureEmptyView:(UIView *)view
{
    return view;
}

Default implementation does nothing.

Error view

- (UIView *)configureErrorView:(UIView *)view withError:(NSError *)error
{
    return view;
}

Default implementation does nothing.

Author

Pavol Kmet

Inspiration

This pod takes inspiration from Swift version of StatefulViewController by Alexander Schuch with some minor differences.

License

StateViewController is available under the MIT license. See the LICENSE file for more info.