• Stars
    star
    384
  • Rank 111,726 (Top 3 %)
  • Language
    Objective-C
  • License
    Apache License 2.0
  • Created over 12 years ago
  • Updated over 9 years ago

Reviews

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

Repository Details

foursquare iOS networking library

FSNetworking

foursquare's iOS networking library

FSN is a small library for HTTP networking on iOS. It comprises a single class, FSNConnection, and several small Cocoa Foundation categories. FSNConnection uses NSConnection, blocks, and NSConnection's operation queue delegate or GCD.

Features

FSNConnection offers the following:

  • Asynchronous HTTP and HTTPS requests.
  • GET and POST (urlencoded and form data); easily extended for other HTTP methods.
  • Response parsing in a background thread, followed by a completion block on the main thread.
  • Convenient, safe object retention sementics and life cycle management, enabling fire-and-forget requests.
  • Support for iOS background tasks.
  • Useful utilities for creating and debugging form data, parsing JSON, error checking, etc.
  • Clean, straightforward implementation; no class hierarchies to grok. Easily trace and understand the life cycle of your connection!

Examples

GET

NSURL *url                = ...; // required
NSDictionary *headers     = ...; // optional
NSDictionary *parameters  = ...; // optional

FSNConnection *connection =
[FSNConnection withUrl:url
                method:FSNRequestMethodGET
               headers:headers
            parameters:parameters
            parseBlock:^id(FSNConnection *c, NSError **error) {
                return [c.responseData dictionaryFromJSONWithError:error];
            }
       completionBlock:^(FSNConnection *c) {
           NSLog(@"complete: %@\n  error: %@\n  parseResult: %@\n", c, c.error, c.parseResult);
       }
         progressBlock:^(FSNConnection *c) {
             NSLog(@"progress: %@: %.2f/%.2f", c, c.uploadProgress, c.downloadProgress);
         }];

[connection start];

The most important aspects of this pattern are:

  • The value returned from the parse block is assigned to the connection's parseResult property.
  • Similarly, if any error is set by the parse block, that is assigned to the connection's error property.
  • You can write simple wrappers around this method to accommodate all the endpoints in a web API:
    • Compose a URL for each endpoint.
    • Send standard headers such as User-Agent and Accept-Language.
    • Send standard parameters such as OAuth token, client version, etc.
    • Combine standard and custom handling for parse and completion steps by calling small custom blocks inside of wrapper blocks that perform uniform error-checking, parsing, etc.

For example, the foursquare app defines a category on FSNConnection that looks like this:

@implementation FSNConnection (FS)


// convenience accessor property that casts parseResult to our custom, API-specific type.
- (ApiResult *)apiResult {
    return self.parseResult;
}


- (ApiResult *)makeApiResultWithError:(NSError **)error {    
    // parse the foursquare API result JSON.
    // then check self.response.statusCode, as well as the foursquare API result 'meta' JSON dict for errors.
    // if everything is OK, then return the an ApiResult instance, which contains api-specific properties.
    // otherwise, set *error and return nil.
    ...
}


// wrap an arbitrary completionBlock with standard handling behavior.
- (void)finishWithBlock:(FSNCompletionBlock)completionBlock displayError:(BOOL)displayError {
    ASSERT_MAIN_THREAD;
    
    if (self.error) {
        // debug-build only error reporting.
        FSLog(@"request error: %@ -- %@ -- %@ -- %@",
              self.error, self.apiResult.errorDetail, self.apiResult.errorMessage, self.apiResult.errorType);
    }
    
    // perform custom block
    if (completionBlock) {
        completionBlock(self);
    }
    
    if (self.error && displayError) {
        // display standard error UI.
        ...
    }
    
    // send standard notifications last.
    ...
}


// most foursquare API requests are constructed with this method.
// it standardizes some elements of request construction, and passes through custom parameters.
// note how we wrap the custom completionBlock with standard behavior by virtue of an intermediate method;
// this allows us to precisely control when the custom callback happens.
+ (id)withEndpoint:(NSString *)endpoint
            method:(FSNRequestMethod)method
        parameters:(NSDictionary *)parameters
      displayError:(BOOL)displayError
        parseBlock:(FSNParseBlock)parseBlock
   completionBlock:(FSNCompletionBlock)completionBlock {
    
    // note: FSAPI is a singleton defining API-related properties, defined elsewhere.
    return [self withUrl:[[FSAPI shared] urlForEndpoint:endpoint]
                  method:method
                 headers:[FSAPI shared].standardRequestHeaders // headers are the same for every request
              parameters:[[FSAPI shared] completeParameters:parameters] // add standard parameters like OAuth token
              parseBlock:parseBlock
         completionBlock:^(FSNConnection *c) {
             [c finishWithBlock:completionBlock displayError:displayError];
         }
           progressBlock:nil];
}


// a second wrapper constructor standardizes parseBlock implementa
// most requests are constructed with this method.
+ (id)withEndpoint:(NSString*)endpoint
            method:(FSNRequestMethod)method
        parameters:(NSDictionary*)parameters
      displayError:(BOOL)displayError
   completionBlock:(FSNCompletionBlock)completionBlock {
    
    return [self withEndpoint:endpoint
                       method:method
                   parameters:parameters
                 displayError:displayError
                   parseBlock:^(FSNConnection *c, NSError **error) {
                       return [c makeApiResultWithError:error];
                   }
              completionBlock:completionBlock];
}

@end

POST

POST requests are made using the same class and calls as GET. This uniformity is one of the most satisfying aspects of the library. POST parameter values can be any of three types: NSString, NSNumber, and FSNData.

  • If the POST consists of only NSString and NSNumber values, then it will have the content-type "application/x-www-form-urlencoded".
  • If any parameter is an FSNData object, then the request will have the content-type "multipart/form-data".

This design allows us to rapidly adjust to changing web API requirements with minimal code changes, and eases form request implementation.

As an example, a photo upload might look like this:

UIImage *originalImage = ...;

// form file name and parameter name would be determined by the web API
NSDictionary *parameters =
[NSDictionary dictionaryWithObjectsAndKeys:
 [FSNData withImage:originalImage jpegQuality:.75 fileName:@"fileName"],  @"paramName",
 nil];

FSNConnection *connection =
[FSNConnection withUrl:url
                method:FSNRequestMethodPOST
               headers:headers
            parameters:parameters
            parseBlock:nil
       completionBlock:nil
         progressBlock:nil];

The FSNData class has several other constructors for sending raw NSData; please see the header for more details. MIME types are represented as an enumeration to encourage standards-compliance and reduce the risk of typos in string literals. Currently, only two MIME types are enumerated, but more can be added easily; just define additional enumerations and their corresponding strings in FSNData.h and FSNData.m.

Other HTTP Methods.

Other HTTP methods like HEAD and PUT are not yet supported, but adding them should not be hard. Patches are welcome; feel free to get in touch if you would like to discuss the implementation.

Demos

FSNDemo-iOS shows how to set up a single connection to the foursquare API.

  • As is, the connection will fail with an OAuth error, demonstrating the error handling conventions.
  • To see the connection succeed, sign up for an OAuth token at http://developer.foursquare.com, or else just request some static html page.

FSNDemo-mac shows how to make the exact same connection, but from the command line.

  • Running an asynchronous connection requires the program to run the main runloop manually.

License

FSN is released under the Apache License, Version 2.0; see license.txt. More information can be found here:

Releases

The current release is 1.0. This code has been in production in the foursquare app for many moons.

Known Issues

Delegate Queues

Support for NSURLConnection's setDelegateQueue exists but is disabled by default because it causes iOS 5 applications to deadlock. Instead, FSN uses the main thread for connection callbacks and GCD to perform parsing on a background thread. Define FSN_QUEUED_CONNECTIONS to 1 (typically in your prefix header) to use delegate queues.

Since delegate queues appear to work in Lion, the Mac demo does use delegate queues. However, this has been tested only minimally. If you enable this and find bugs, please submit patches!

See also:

Recursive Lock

An NSRecursiveLock is used to guard the parseBlock against cancellation/deallocation while in concurrent usage. We would prefer a lock-free implementation for the sake of simplicity, and we welcome any scrutiny or suggestions for a better solution.

Dependencies

FSNetworking depends only on Cocoa's Foundation framework; convenience methods using UIKit are guarded appropriately. We currently build against iOS 5.0 with the latest public release of the Xcode toolset. The Mac demo builds against OS X 10.7.

Maintainers

FSNConnection was initially developed by Foursquare Labs as a replacement for ASIHTTPRequest in our iOS application. We now use it for all HTTP networking in the foursquare iOS app.

The current maintainer is:

Feedback, bug reports, and code contributions are all welcome!

More Repositories

1

rogue

MOVED - The project is still under development but this page is deprecated.
Scala
489
star
2

twofishes

MOVED - The project is still under development but this page is deprecated.
Scala
433
star
3

fsqio

A monorepo that holds all of Foursquare's opensource projects
Scala
254
star
4

quattroshapes

Makefile
231
star
5

FSQCollectionViewAlignedLayout

FSQCollectionViewAlignedLayout is a generic collection view layout designed to be very flexible and configurable. It's goal is to save its users from having to write their own custom layout classes every time UICollectionViewFlowLayout is not appropriate for their view.
Objective-C
176
star
6

fongo

faked out in-memory mongo for java
Java
150
star
7

foursquare-android-oauth

Foursquare native authentication makes it easier for your app's users to connect with Foursquare. Unlike web-based OAuth, native authentication re-uses the Foursquare app's user credentials, saving users the hassle of re-logging in to Foursquare within your app.
Java
134
star
8

foursquare-palmpre

A webOS app (Mojo Framework)
JavaScript
105
star
9

foursquare-ios-oauth

Foursquare native authentication makes it easier for your app's users to connect with Foursquare. Unlike web-based OAuth, native authentication re-uses the Foursquare app's user credentials, saving users the hassle of re-logging in to Foursquare within your app.
Objective-C
104
star
10

slashem

A rogue-like DSL for querying SOLR
Scala
103
star
11

FSQLocationBroker

A centralized location manager for your app.
Objective-C
94
star
12

oozie-web

A more pretty, more usable web dashboard for Apache Oozie, written in Scala.
JavaScript
74
star
13

foursquare-fhttp

MOVED - The project is still under development but this page is deprecated.
Scala
44
star
14

FSQCellManifest

A UITableView and UICollectionView delegate and datasource that provides a simpler unified interface for describing your sections and cells.
Objective-C
43
star
15

quiver

An HFile-backed Key-Value Server
Go
42
star
16

hackathon

foursquare hackathonsâ„¢
40
star
17

spindle

MOVED - The project is still under development but this page is deprecated.
Scala
39
star
18

mongo-hdfs-export

Scala
31
star
19

foursquare-app-framework

Framework for building Connected Apps
Python
31
star
20

react-foursquare

Foursquare Library for React
JavaScript
25
star
21

es-scorer-plugin

Plugin to do our scoring in ES
Scala
24
star
22

sites-to-markdown

convert google sites html to markdown
Java
23
star
23

FSQRoutes

URL routing framework for iOS
Objective-C
21
star
24

fsq-studio-sdk-examples

Foursquare Studio is a platform to visualize, unify, enrich, and analyze spatial data on a planetary scale.
Jupyter Notebook
19
star
25

qgis-plugin

Foursquare Studio plugin for QGIS
Python
19
star
26

datasource-plugin-clouderamanager

Cloudera Manager datasource for Grafana 3.x
JavaScript
19
star
27

twitter-util-async

scala-async support for twitter util library
Scala
15
star
28

Place-API-Postman-Collection

Postman collection that contains almost all the sample Foursquare Places API calls.
14
star
29

foursquair

An Adobe AIR desktop client for foursquare
ActionScript
14
star
30

placepicker-sdk-sample

An SDK to help developers add a place picker to their app and also quickly access the Foursquare place that their user is at.
Java
11
star
31

wait

wait gem: executes a block until there's a result
Ruby
10
star
32

hoursparser.js

dumb but useful hours extractor from free-text entry
JavaScript
9
star
33

h3-presto

Presto bindings for H3, a hierarchical hexagonal geospatial indexing system
Java
8
star
34

gitshed

git versioning of large binary files outside the repo.
Python
8
star
35

shapefile-geo

Java
8
star
36

pilgrim-sdk-react-native

React native wrapper for the Pilgrim SDK
Java
7
star
37

fsgo

Reusable libraries for building Go services
Go
7
star
38

FSQMessageForwarder

An Obj-C message forwarder class, for when you don't have access to the source of the sending object.
Objective-C
6
star
39

merchant-app

JavaScript
5
star
40

source_code_analysis

Utilities to analyze, lint and rewrite source code in various languages.
Python
5
star
41

gohfile

5
star
42

exceptionator

MOVED - The project is still under development but this page is deprecated.
JavaScript
5
star
43

foursquare-places

framework agnostic wrapper for foursquare's APIs
JavaScript
5
star
44

android-map-utils

A collection of 3rd party map utility classes
4
star
45

cc-shapefiles

Scala
3
star
46

pilgrim-unity-package

Unity package which enables easy integration with Pilgrim SDK
Objective-C
3
star
47

foursquareapi-csharp

C#
3
star
48

foursquare.github.io

Foursquare open source portal
HTML
2
star
49

movementsdk-ios-spm

Movement SDK for iOS - Swift Package Manager
Swift
2
star
50

foursquare-places-api-samples

Developer Examples for using Foursquare products
HTML
2
star
51

simple-macros

MOVED - The project is still under development but this page is deprecated.
Scala
2
star
52

FSQComponents

Objective-C
2
star
53

RNPilgrimSample

Pilgrim sample app using React Native
Java
2
star
54

json-traverser

Scala
1
star
55

hackmidwest

This repo contains everything developers need to get started at Hack Midwest!
1
star
56

MovementSdk-CocoaPods-Beta

Private CocoaPods Spec repo for the Movement SDK
Ruby
1
star
57

finagle-dual

Support thrift and HTTP on same port with Finagle
Scala
1
star
58

movement-sdk-react-native

React native wrapper for the Movement SDK
Objective-C
1
star
59

pilgrimsdk-adobe-extension

The pilgrim adobe extension
Kotlin
1
star
60

public-model-resources

Jupyter Notebook
1
star
61

mobbing-interview-python

Used by the Security & Quality Team for interviews
1
star
62

RNMovementSample

Movement SDK sample app using React Native
Java
1
star
63

Pilgrim-CocoaPods-Beta

Public cocoapods spec repo for Pilgrim SDK beta builds
Ruby
1
star
64

pilgrim-ios-spm

Pilgrim SDK for iOS - Swift Package Manager
Swift
1
star
65

alertmon

Foursquare's homegrown production alerting platform
Python
1
star
66

commons-old

Temporary duplicate of foursquare/commons (a fork of twitter/commons) while we restructure things.
Java
1
star