• Stars
    star
    350
  • Rank 121,229 (Top 3 %)
  • Language
    Objective-C
  • License
    MIT License
  • Created over 9 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Runtime configurable local server for iOS apps.

MMBarricade

Platform Version Build Status

Why Barricade?

MMBarricade is a framework for setting up a run-time configurable local server in iOS apps. This works by creating a NSURLProtocol "barricade" that blocks outgoing network traffic and redirects it to a custom, local response, without requiring any changes to existing networking code.

NSURLSession, NSURLConnection, AFNetworking, and all other networking that utilizes Foundation's URL Loading System are supported.

Most other local server implementations only support a single response per request, but Barricade supports multiple responses per request. This allows us to present the user with an interface for modifying which response will be returned for a request at runtime.

Example App

When to use

During development barricade is useful for easily exercising all edge cases of a feature while you are building it without needing to frequently adjust the live server state.

For unit tests and integration tests barricade allows you to easily toggle through each predefined response for a request so tests can cover edge cases thoroughly.

Similarly, UI tests, such as KIF, can programmatically update selected responses as well, which allows your test suite to cover failure cases as well as the "happy path".

Take a look at the unit tests in MMBarricadeTests.m of DevelopmentApp/Barricade.xcworkspace for several examples of how unit tests can be implemented utilizing Barricade.

##Installing MMBarricade
The easiest way to install MMBarricade is with CocoaPods:

pod 'MMBarricade', '~> 1.0.0'

Overview

Barricade's functionality is based around four primary classes: MMBarricade, MMBarricadeResponse, MMBarricadeResponseSet and <MMBarricadeResponseStore>.

MMBarricade

MMBarricade is a NSURLProtocol subclass and is the primary class to use when interacting with barricade.

MMBarricadeResponse

An instance of MMBarricadeResponse defines a single response to an HTTP request. For example, a response might consist of an HTTP status code of 200, a content-type of "application/json" and a JSON object for the response data.

MMBarricadeResponseSet

An instance of MMBarricadeResponseSet represents a collection of possible responses for a single request. For example, a response set for the /login API endpoint might be a set of three responses representing Success, Invalid Credentials and Server Error.

MMBarricadeResponseStore

A response store conforms to <MMBarricadeResponseStore> and is responsible for managing the selection of which response should be returned for a network request out of the set of possible responses. This selection can be modified programmatically, or through the Tweaks UI (as seen in the gif above).

Quick Start

First, import the library header file. If using Tweaks to manage user selections, import the Tweaks category to get access to the convenience initializer.

#import "MMBarricade.h"

Next, give the barricade a response store and enable it. Once enabled, the barricade will begin responding to network requests.

// Setup the barricade. This only needs to be done once.
[MMBarricade setupWithInMemoryResponseStore];
[MMBarricade enable];

In this example, we'll setup the barricade to be able to respond to the /login API endpoint with one of three possible responses. The "name" parameters for the response set and each individual response are user-facing strings used to identify the request and responses to the developer. They are displayed in the Tweaks UI, and can be used to programmatically udpate the selected response as well.

In this example, the response files are JSON-formatted text files stored on disk in a subdirectory of the app bundle named "LocalServer". There are no naming conventions that must be followed for file names.

// Create a response set for each API call that should be barricaded.
MMBarricadeResponseSet *responseSet = [MMBarricadeResponseSet responseSetForRequestName:@"Login" respondsToRequest:^BOOL(NSURLRequest *request, NSURLComponents *components) {
   return [components.path hasSuffix:@"/login"];
}];
    
// Add Successful response
[responseSet addResponseWithName:@"Success"
                           file:MMPathForFileInMainBundleDirectory(@"login.success.json", @"LocalServer")
                     statusCode:200
                    contentType:@"application/json"];
    
// Add Invalid Credentials response
[responseSet addResponseWithName:@"Invalid Credentials"
                           file:MMPathForFileInMainBundleDirectory(@"login.invalid.json", @"LocalServer")
                     statusCode:401
                    contentType:@"application/json"];

// Add No Network Connection response
[responseSet addResponseWithName:@"Offline"
                          error:[NSError errorWithDomain:NSURLErrorDomain
                                                    code:NSURLErrorNotConnectedToInternet
                                                userInfo:nil]];
    
// Register the response set
[MMBarricade registerResponseSet:responseSet];

By default, the first response added to a response set will be used to respond to the request. However, the selected response can be modified through the Tweaks interface or programmatically. In either case, the "name" parameters specified when creating the responses are used to identify the desired response.

[MMBarricade selectResponseForRequest:@"Login" withName:@"Offline"];

Selection Interface

Barricade comes with an in-app interface that can be presented to allow selection of network responses at runtime.

Example App

There are two approaches you can take for presenting the selection UI:

  • Automatically present the interface when the device is shaken. To do this, just replace your UIWindow with an instance of an MMBarricadeShakeWindow. If you're using storyboards, override - window in your app delegate:
- (UIWindow *)window {
    if (!_window) {
        _window = [[MMBarricadeShakeWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    }    
    return _window;
}

Note: By default the shake window is presented for Debug builds only. You can override the MMBARRICADE_SHAKE_ENABLED macro to adjust this behavior.

  • Manually present a MMBarricadeViewController at any time in your app, just be sure to limit the presetation to debug builds if you don't want it to ship to the App Store.

Tweaks

If you are using Facebook Tweaks in your app, you can use the Tweaks subspec of Barricade to integrate the in-app selection interface inside of Tweaks.

pod 'MMBarricade/Tweaks', '~> 1.0.0'

The only other change you need to make is to setup the barricade using a tweaks response store rather than the in-memory response store:

#import "MMBarricade+Tweaks.h"
...
[MMBarricade setupWithTweaksResponseStore];
[MMBarricade enable];

App Store Submission

MMBarricade is safe to include with App Store builds (and could be used to support things like a demo mode for your app), but most of the time you will probably want to ensure that the barricade is disabled for App Store builds. Here are a couple of approaches:

Conditionally enable

In your app, you can wrap the creation of the barricade inside a macro to limit the code execution to particular build configurations. For example:

#if DEBUG
[MMBarricade enable];
#endif

Disable through CocoaPods

When installing through CocoaPods, you can specify particular build configurations to limit the installation of the library. For example:

pod 'MMBarricade', '~> 1.0.0', :configurations => ['Debug']

Or, if you are only utilizing the library for unit tests, you may want to link the library with only your testing target:

target 'Tests', :exclusive => true do
  pod 'MMBarricade', '~> 1.0.0'
end

Advanced Configuration

Configuration consists of two steps:

  1. Setup a response store
  2. Enable the barricade

The barricade must be configured with an instance of an <MMBarricadeResponseStore> before it can be used. To use one of the included response stores, you can:

[MMBarricade setupWithTweaksResponseStore];
-or-
[MMBarricade setupWithInMemoryResponseStore];

Once the backing store for the barricade is setup, it should be enabled. Because the barricade works as a NSURLProtocol subclass, the way to enable it differs depending on how you will be making network requests in your app.

NSURLConnection

For networking based on the older networking style of NSURLConnection-based requests, simply calling [MMBarricade enable] will register the NSURLProtocol for you.

NSURLSession

For networking based on the newer NSURLSession-based APIs, you have two options:

If you are using [NSURLSession sharedSession], then you can enable with [MMBarricade enable].

If you are creating a custom session, for example [NSURLSession sessionWithConfiguration:configuration], then you should enable the barricade with your custom session configuration before creating the session.

NSURLSessionConfiguration *configuration = [self myCustomSessionConfiguration];
[MMBarricade enableForSessionConfiguration:configuration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
...

Changing the response

The response that will be returned by the barricade when a request is made is the "current response" that has been selected in the MMBarricadeResponseSet for the request. In addition to updating the current response through the tweaks UI, the response can also be updated programmatically:

[MMBarricade selectResponseForRequest:@"login" withName:@"offline"];

Requirements

MMBarricade requires iOS 7.0 or higher.

Credits

MMBarricade was created by John McIntosh at Mutual Mobile.

Credit also to Justin Kolb for pioneering the concept of run-time adjustable network responses and Conrad Stoll for feedback.

License

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

More Repositories

1

MMDrawerController

A lightweight, easy to use, Side Drawer Navigation Controller
Objective-C
6,760
star
2

MMWormhole

Message passing between iOS apps and extensions.
Objective-C
3,926
star
3

MMProgressHUD

An easy-to-use HUD interface with personality.
Objective-C
705
star
4

MMRecord

Seamless Web Service Integration and Core Data Model Population
Objective-C
691
star
5

VIPER-SWIFT

An example Todo list app written in Swift using the VIPER architecture.
Swift
502
star
6

CardStackUI

An iOS Healthbook-like highly customisable stack of cards implementation for Android
Kotlin
465
star
7

Praxis

Example Android project using MVVM, DaggerAndroid, Jetpack Compose, Retrofit, Coroutines and Multi module architecture ✌🏽
Kotlin
353
star
8

Counter

A simple example of the VIPER architecture for iOS apps
Objective-C
351
star
9

ComposeSensors

Access sensor data for any Android device easily using Jetpack Compose 🌡️ 🧲 🧭
Kotlin
207
star
10

compose-animation-examples

Compose Animation Examples. Useful Jetpack Compose animations including Loading/progress, Looping, On-off, Enter, Exit, Fade, Spin and Background animations that you can take inspiration from.
Kotlin
203
star
11

MMSpreadsheetView

Objective-C
193
star
12

lavaca

A modern framework for client-side MVC web applications
JavaScript
105
star
13

AFHARchiver

An AFNetworking extension to automatically generate HTTP Archive files of all of your network requests!
Objective-C
102
star
14

gradle-dexinfo-plugin

Java
71
star
15

VIPER-TODO

Example project architected using VIPER
Objective-C
70
star
16

PraxisKMP

A Kotlin multiplatform base project
Kotlin
49
star
17

HarvestTimeKMP

A Kotlin multiplatform playground project for getharvest time logger clone.
Kotlin
44
star
18

Barricade

⛔️ DEPRECATED (Click on the link below to check out Barricade2) - Runtime configurable local server for Android apps.
Java
42
star
19

SeatLayout

A seat selection library for Android with an example for selecting seats for flights, sports venue, theatres, etc
Java
39
star
20

lavaca-starter

A starter app for lavaca
CSS
34
star
21

PraxisFlutter

Example Flutter Project using Clean Architecture
Dart
29
star
22

FitWatchCompose

Kotlin
21
star
23

MMKeystore

A Keystore library for Android apps that allows you to encrypt sensitive information, The encryption uses the Android KeyStore to generate RSA and AES keys for encryption operations.
Kotlin
13
star
24

UberBookingClone

Kotlin
13
star
25

cordova-bluetoothle

Cordova Bluetooth Low Energy plugin for iOS and Android
Objective-C
12
star
26

Barricade2

Runtime configurable local server for Android apps.
Kotlin
9
star
27

flutter_animations_example

Flutter Animation Examples. Useful Flutter animations including Loading/progress, Looping, On-off, Enter, Exit, Fade, Spin and Background animations that you can take inspiration from.
Dart
8
star
28

react-native-barricade

A local server configurable at runtime to develop, test, and prototype your React Native app.
TypeScript
8
star
29

HolidayCard

Build a Holiday Card for Hour of Code in Swift!
Swift
8
star
30

Brazos

A React web React Native starter with tooling for large scale projects
JavaScript
7
star
31

MM-Dribbble

A fun app to use at Dribbble meetups across the world!
4
star
32

clover-reporting

A reporting tool using the Clover REST API
HTML
3
star
33

dust_compiler

A simple Node command line tool that watches and compiles dust templates recursively from one directory to another
JavaScript
3
star
34

XcodeSortInstaller

A simple gem to install a new build phase on your Xcode project file to (on modification) sort itself on build.
Ruby
2
star
35

Google-Analytics

Storing Google Analytics Source Code for Cocoa Pods
Objective-C
2
star
36

SwiftUIAnimations

Playground for swiftui animations
Swift
2
star
37

Library

Library App that holds a shelf of books, and a detail view of each book that shows information about it like the book's Author, Publisher, Book ID/ISBN number and so on.
Objective-C
2
star
38

HarvestAPISpring

Kotlin
1
star
39

ReactFirebaseAuthComponent

Reusable code for simple authentication and integration with Firebase
JavaScript
1
star
40

ZomatoClone

Kotlin
1
star
41

clover.mutualmobile.com

CSS
1
star
42

seven68

Seven68 is a Objective-C library for iPad developers.
1
star