Commit 961db158 authored by Marius Rackwitz's avatar Marius Rackwitz

[Examples] Add Example of Alamofire

parent 9b6813f5
Pod::Spec.new do |s|
s.name = 'Alamofire'
s.version = '0.0.1'
s.license = 'MIT'
s.summary = 'Elegant HTTP Networking in Swift'
s.homepage = 'https://github.com/Alamofire/Alamofire'
s.social_media_url = 'http://twitter.com/mattt'
s.authors = { 'Mattt Thompson' => 'm@mattt.me' }
s.source = { :git => 'https://github.com/Alamofire/Alamofire.git', :branch => 'master' }
s.requires_arc = true
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10'
s.source_files = 'Source/*.swift'
end
// AppDelegate.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
// MARK: - UIApplicationDelegate
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
let splitViewController = self.window!.rootViewController as UISplitViewController
let navigationController = splitViewController.viewControllers.last as UINavigationController
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
// MARK: - UISplitViewControllerDelegate
func splitViewController(splitViewController: UISplitViewController!, collapseSecondaryViewController secondaryViewController:UIViewController!, ontoPrimaryViewController primaryViewController:UIViewController!) -> Bool {
if let secondaryAsNavController = secondaryViewController as? UINavigationController {
if let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController {
return topAsDetailController.request == nil
}
}
return false
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6245" systemVersion="13E28" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="H1p-Uh-vWS">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
</dependencies>
<scenes>
<!--Master-->
<scene sceneID="pY4-Hu-kfo">
<objects>
<navigationController title="Master" id="RMx-3f-FxP" sceneMemberID="viewController">
<navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="Pmd-2v-anx">
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="7bK-jq-Zjz" kind="relationship" relationship="rootViewController" id="tsl-Nk-0bq"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8fS-aE-onr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-38" y="-630"/>
</scene>
<!--Split View Controller-->
<scene sceneID="Nki-YV-4Qg">
<objects>
<splitViewController id="H1p-Uh-vWS" sceneMemberID="viewController">
<toolbarItems/>
<connections>
<segue destination="RMx-3f-FxP" kind="relationship" relationship="masterViewController" id="BlO-5A-QYV"/>
<segue destination="vC3-pB-5Vb" kind="relationship" relationship="detailViewController" id="Tll-UG-LXB"/>
</connections>
</splitViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="cZU-Oi-B1e" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-687" y="-322"/>
</scene>
<!--Master-->
<scene sceneID="smW-Zh-WAh">
<objects>
<tableViewController title="Master" clearsSelectionOnViewWillAppear="NO" id="7bK-jq-Zjz" customClass="MasterViewController" customModule="iOS_Example" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="r7i-6Z-zg0">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection headerTitle="Data" id="8cQ-ii-Dz7">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Arm-wq-HPj" style="IBUITableViewCellStyleDefault" id="WCw-Qf-5nD">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WCw-Qf-5nD" id="37f-cq-3Eg">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="GET Request" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Arm-wq-HPj">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<segue destination="vC3-pB-5Vb" kind="showDetail" identifier="GET" id="1CM-sC-jmU"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="kv2-3k-J9w" style="IBUITableViewCellStyleDefault" id="Bba-qf-fdr">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Bba-qf-fdr" id="U5U-eQ-rXg">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="POST Request" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="kv2-3k-J9w">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<segue destination="vC3-pB-5Vb" kind="showDetail" identifier="POST" id="qtJ-N8-1Yf"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="gGF-bI-vhg" style="IBUITableViewCellStyleDefault" id="QdK-ID-hbj">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="QdK-ID-hbj" id="JxT-sx-VDC">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="PUT Request" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="gGF-bI-vhg">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<segue destination="vC3-pB-5Vb" kind="showDetail" identifier="PUT" id="ATO-2Y-gmc"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="jsW-Zp-fZf" style="IBUITableViewCellStyleDefault" id="Mmy-5X-lLC">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Mmy-5X-lLC" id="0eC-Qc-fq1">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="DELETE Request" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jsW-Zp-fZf">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<segue destination="vC3-pB-5Vb" kind="showDetail" identifier="DELETE" id="FoU-a6-nga"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Upload" id="HR4-nh-1dM">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="tFv-wn-QTG" style="IBUITableViewCellStyleDefault" id="cNY-Vx-8u5">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="cNY-Vx-8u5" id="yYR-YT-Fse">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Upload Data" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tFv-wn-QTG">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Ii5-Vh-zHX" style="IBUITableViewCellStyleDefault" id="xgg-BT-6Gr">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="xgg-BT-6Gr" id="2eT-D2-puB">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Upload File" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Ii5-Vh-zHX">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="gzG-92-x5R" style="IBUITableViewCellStyleDefault" id="jNV-fh-84v">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jNV-fh-84v" id="52u-Fk-l5Q">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Upload Stream" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="gzG-92-x5R">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Download" id="7nc-cQ-nUY">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Gr3-i1-tdE" style="IBUITableViewCellStyleDefault" id="khw-Sk-LOc">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="khw-Sk-LOc" id="HO7-NM-pbP">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Download Request" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Gr3-i1-tdE">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="fmT-qD-bf2" style="IBUITableViewCellStyleDefault" id="8hK-B8-VMy">
<rect key="frame" x="0.0" y="86" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8hK-B8-VMy" id="bfY-jx-lTE">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Download Resume Data" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="fmT-qD-bf2">
<rect key="frame" x="15" y="0.0" width="290" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="7bK-jq-Zjz" id="Gho-Na-rnu"/>
<outlet property="delegate" destination="7bK-jq-Zjz" id="RA6-mI-bju"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="Zdf-7t-Un8"/>
<connections>
<outlet property="titleImageView" destination="9c8-WZ-jVF" id="jvG-Sa-nSG"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Rux-fX-hf1" sceneMemberID="firstResponder"/>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Logo" id="9c8-WZ-jVF">
<rect key="frame" x="0.0" y="0.0" width="250" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
</objects>
<point key="canvasLocation" x="604" y="-630"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="r7l-gg-dq7">
<objects>
<navigationController id="vC3-pB-5Vb" sceneMemberID="viewController">
<navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="DjV-YW-jjY">
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="hay-0o-6iw" kind="relationship" relationship="rootViewController" id="bmM-Kc-6qk"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="SLD-UC-DBI" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-38" y="30"/>
</scene>
<!--Detail View Controller-->
<scene sceneID="Vi6-fp-rZb">
<objects>
<tableViewController id="hay-0o-6iw" customClass="DetailViewController" customModule="iOS_Example" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" allowsSelection="NO" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="uo9-Sd-Gpr">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Header" textLabel="CVi-D2-cds" detailTextLabel="Umi-gS-7r0" style="IBUITableViewCellStyleValue1" id="tsM-dO-McZ">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tsM-dO-McZ" id="LQw-cm-GmU">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Accept" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="CVi-D2-cds">
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="&quot;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&quot;" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Umi-gS-7r0">
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Body" textLabel="m1f-qP-FlJ" rowHeight="119" style="IBUITableViewCellStyleDefault" id="N0t-UM-UX3">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="N0t-UM-UX3" id="AxK-Aj-qDS">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="m1f-qP-FlJ">
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<fontDescription key="fontDescription" name="Courier" family="Courier" pointSize="12"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="hay-0o-6iw" id="U5L-JB-xfD"/>
<outlet property="delegate" destination="hay-0o-6iw" id="N4n-xl-uSD"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="ovN-S0-oAU"/>
<refreshControl key="refreshControl" opaque="NO" multipleTouchEnabled="YES" contentMode="center" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="e6J-W5-mRs">
<autoresizingMask key="autoresizingMask"/>
</refreshControl>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="vwc-ms-sMM" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="604" y="30"/>
</scene>
</scenes>
<resources>
<image name="Logo" width="250" height="40"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="FoU-a6-nga"/>
</inferredMetricsTieBreakers>
<color key="tintColor" red="0.84313732385635376" green="0.25882354378700256" blue="0.11372549831867218" alpha="1" colorSpace="deviceRGB"/>
</document>
// DetailViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import Alamofire
class DetailViewController: UITableViewController {
enum Sections: Int {
case Headers, Body
}
var request: Alamofire.Request? {
didSet {
oldValue?.cancel()
self.title = self.request?.description
self.refreshControl?.endRefreshing()
self.headers.removeAll()
self.body = nil
self.elapsedTime = nil
}
}
var headers: [String: String] = [:]
var body: String?
var elapsedTime: NSTimeInterval?
override func awakeFromNib() {
super.awakeFromNib()
self.refreshControl?.addTarget(self, action: "refresh", forControlEvents: .ValueChanged)
}
// MARK: - UIViewController
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.refresh()
}
// MARK: - IBAction
@IBAction func refresh() {
if self.request == nil {
return
}
self.refreshControl?.beginRefreshing()
let start = CACurrentMediaTime()
self.request?.responseString { (request, response, body, error) in
let end = CACurrentMediaTime()
self.elapsedTime = end - start
for (field, value) in response!.allHeaderFields {
self.headers["\(field)"] = "\(value)"
}
self.body = body
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch Sections(rawValue: section)! {
case .Headers:
return self.headers.count
case .Body:
return self.body == nil ? 0 : 1
default:
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch Sections(rawValue: indexPath.section)! {
case .Headers:
let cell = self.tableView.dequeueReusableCellWithIdentifier("Header") as UITableViewCell
let field = self.headers.keys.array.sorted(<)[indexPath.row]
let value = self.headers[field]
cell.textLabel.text = field
cell.detailTextLabel!.text = value
return cell
case .Body:
let cell = self.tableView.dequeueReusableCellWithIdentifier("Body") as UITableViewCell
cell.textLabel.text = self.body
return cell
}
}
// MARK: UITableViewDelegate
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
if self.tableView(tableView, numberOfRowsInSection: section) == 0 {
return ""
}
switch Sections(rawValue: section)! {
case .Headers:
return "Headers"
case .Body:
return "Body"
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
switch Sections(rawValue: indexPath.section)! {
case .Body:
return 300
default:
return tableView.rowHeight
}
}
override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String {
if Sections(rawValue: section)! == .Body && self.elapsedTime != nil {
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
return "Elapsed Time: \(numberFormatter.stringFromNumber(self.elapsedTime!)) sec"
}
return ""
}
}
// MasterViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
import Alamofire
enum HTTPBinRoute: URLStringConvertible {
case Method(Alamofire.Method)
case BasicAuth(String, String)
var URLString: String {
let baseURLString = "http://httpbin.org/"
let path: String = {
switch self {
case .Method(let method):
return "/\(method.rawValue.lowercaseString)"
case .BasicAuth(let user, let password):
return "/basic-auth/\(user)/\(password)"
}
}()
return NSURL(string: path, relativeToURL: NSURL(string: baseURLString))!.absoluteString!
}
}
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Logo.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Logo@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.alamofire.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Alamofire</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
// MasterViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import Alamofire
class MasterViewController: UITableViewController {
@IBOutlet weak var titleImageView: UIImageView!
var detailViewController: DetailViewController? = nil
var objects = NSMutableArray()
override func awakeFromNib() {
super.awakeFromNib()
self.navigationItem.titleView = self.titleImageView
}
// MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = controllers.last?.topViewController as? DetailViewController
}
}
// MARK: - UIStoryboardSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let detailViewController = segue.destinationViewController.topViewController as? DetailViewController {
func requestForSegue(segue: UIStoryboardSegue) -> Request? {
switch segue.identifier as String! {
case "GET":
return Alamofire.request(.GET, "http://httpbin.org/get")
case "POST":
return Alamofire.request(.POST, "http://httpbin.org/post")
case "PUT":
return Alamofire.request(.PUT, "http://httpbin.org/put")
case "DELETE":
return Alamofire.request(.DELETE, "http://httpbin.org/delete")
default:
return nil
}
}
if let request = requestForSegue(segue) {
detailViewController.request = request
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:iOS Example.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
Copyright (c) 2014 Alamofire (http://alamofire.org/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
source 'https://github.com/CocoaPods/Specs.git'
workspace 'Examples.xcworkspace'
target 'iOS Example' do
xcodeproj 'iOS Example.xcodeproj'
platform :ios, '8.0'
pod 'Alamofire', :path => '.'
end
// Alamofire.h
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT double AlamofireVersionNumber;
FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
// Alamofire.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
/// Alamofire errors
public let AlamofireErrorDomain = "com.alamofire.error"
/**
HTTP method definitions.
See http://tools.ietf.org/html/rfc7231#section-4.3
*/
public enum Method: String {
case OPTIONS = "OPTIONS"
case GET = "GET"
case HEAD = "HEAD"
case POST = "POST"
case PUT = "PUT"
case PATCH = "PATCH"
case DELETE = "DELETE"
case TRACE = "TRACE"
case CONNECT = "CONNECT"
}
/**
Used to specify the way in which a set of parameters are applied to a URL request.
*/
public enum ParameterEncoding {
/**
A query string to be set as or appended to any existing URL query for `GET`, `HEAD`, and `DELETE` requests, or set as the body for requests with any other HTTP method. The `Content-Type` HTTP header field of an encoded request with HTTP body is set to `application/x-www-form-urlencoded`. Since there is no published specification for how to encode collection types, the convention of appending `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for nested dictionary values (`foo[bar]=baz`).
*/
case URL
/**
Uses `NSJSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
*/
case JSON
/**
Uses `NSPropertyListSerialization` to create a plist representation of the parameters object, according to the associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header field of an encoded request is set to `application/x-plist`.
*/
case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions)
/**
Uses the associated closure value to construct a new request given an existing request and parameters.
*/
case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSURLRequest, NSError?))
/**
Creates a URL request by encoding parameters and applying them onto an existing request.
:param: URLRequest The request to have parameters applied
:param: parameters The parameters to apply
:returns: A tuple containing the constructed request and the error that occurred during parameter encoding, if any.
*/
public func encode(URLRequest: URLRequestConvertible, parameters: [String: AnyObject]?) -> (NSURLRequest, NSError?) {
if parameters == nil {
return (URLRequest.URLRequest, nil)
}
var mutableURLRequest: NSMutableURLRequest! = URLRequest.URLRequest.mutableCopy() as NSMutableURLRequest
var error: NSError? = nil
switch self {
case .URL:
func query(parameters: [String: AnyObject]) -> String {
var components: [(String, String)] = []
for key in sorted(Array(parameters.keys), <) {
let value: AnyObject! = parameters[key]
components += queryComponents(key, value)
}
return join("&", components.map{"\($0)=\($1)"} as [String])
}
func encodesParametersInURL(method: Method) -> Bool {
switch method {
case .GET, .HEAD, .DELETE:
return true
default:
return false
}
}
let method = Method(rawValue: mutableURLRequest.HTTPMethod)
if method != nil && encodesParametersInURL(method!) {
if let URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false) {
URLComponents.percentEncodedQuery = (URLComponents.query != nil ? URLComponents.query! + "&" : "") + query(parameters!)
mutableURLRequest.URL = URLComponents.URL
}
} else {
if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
mutableURLRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
}
mutableURLRequest.HTTPBody = query(parameters!).dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
}
case .JSON:
let options = NSJSONWritingOptions.allZeros
if let data = NSJSONSerialization.dataWithJSONObject(parameters!, options: options, error: &error) {
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
mutableURLRequest.HTTPBody = data
}
case .PropertyList(let (format, options)):
if let data = NSPropertyListSerialization.dataWithPropertyList(parameters!, format: format, options: options, error: &error) {
mutableURLRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
mutableURLRequest.HTTPBody = data
}
case .Custom(let closure):
return closure(mutableURLRequest, parameters)
}
return (mutableURLRequest, error)
}
func queryComponents(key: String, _ value: AnyObject) -> [(String, String)] {
var components: [(String, String)] = []
if let dictionary = value as? [String: AnyObject] {
for (nestedKey, value) in dictionary {
components += queryComponents("\(key)[\(nestedKey)]", value)
}
} else if let array = value as? [AnyObject] {
for value in array {
components += queryComponents("\(key)[]", value)
}
} else {
components.extend([(escape(key), escape("\(value)"))])
}
return components
}
func escape(string: String) -> String {
let allowedCharacters = NSCharacterSet(charactersInString:" =\"#%/<>?@\\^`{}[]|&+").invertedSet
return string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacters) ?? string
}
}
// MARK: - URLStringConvertible
/**
Types adopting the `URLStringConvertible` protocol can be used to construct URL strings, which are then used to construct URL requests.
*/
public protocol URLStringConvertible {
/// The URL string.
var URLString: String { get }
}
extension String: URLStringConvertible {
public var URLString: String {
return self
}
}
extension NSURL: URLStringConvertible {
public var URLString: String {
return absoluteString!
}
}
extension NSURLComponents: URLStringConvertible {
public var URLString: String {
return URL!.URLString
}
}
extension NSURLRequest: URLStringConvertible {
public var URLString: String {
return URL.URLString
}
}
// MARK: - URLRequestConvertible
/**
Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests.
*/
public protocol URLRequestConvertible {
/// The URL request.
var URLRequest: NSURLRequest { get }
}
extension NSURLRequest: URLRequestConvertible {
public var URLRequest: NSURLRequest {
return self
}
}
// MARK: -
/**
Responsible for creating and managing `Request` objects, as well as their underlying `NSURLSession`.
*/
public class Manager {
/**
A shared instance of `Manager`, used by top-level Alamofire request methods, and suitable for use directly for any ad hoc requests.
*/
public class var sharedInstance: Manager {
struct Singleton {
static var configuration: NSURLSessionConfiguration = {
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = {
// Accept-Encoding HTTP Header; see http://tools.ietf.org/html/rfc7230#section-4.2.3
let acceptEncoding: String = "gzip;q=1.0,compress;q=0.5"
// Accept-Language HTTP Header; see http://tools.ietf.org/html/rfc7231#section-5.3.5
let acceptLanguage: String = {
var components: [String] = []
for (index, languageCode) in enumerate(NSLocale.preferredLanguages() as [String]) {
let q = 1.0 - (Double(index) * 0.1)
components.append("\(languageCode);q=\(q)")
if q <= 0.5 {
break
}
}
return join(",", components)
}()
// User-Agent Header; see http://tools.ietf.org/html/rfc7231#section-5.5.3
let userAgent: String = {
if let info = NSBundle.mainBundle().infoDictionary {
let executable: AnyObject = info[kCFBundleExecutableKey] ?? "Unknown"
let bundle: AnyObject = info[kCFBundleIdentifierKey] ?? "Unknown"
let version: AnyObject = info[kCFBundleVersionKey] ?? "Unknown"
let os: AnyObject = NSProcessInfo.processInfo().operatingSystemVersionString ?? "Unknown"
var mutableUserAgent = NSMutableString(string: "\(executable)/\(bundle) (\(version); OS \(os))") as CFMutableString
let transform = NSString(string: "Any-Latin; Latin-ASCII; [:^ASCII:] Remove") as CFString
if CFStringTransform(mutableUserAgent, nil, transform, 0) == 1 {
return mutableUserAgent as NSString
}
}
return "Alamofire"
}()
return ["Accept-Encoding": acceptEncoding,
"Accept-Language": acceptLanguage,
"User-Agent": userAgent]
}()
return configuration
}()
static let instance = Manager(configuration: configuration)
}
return Singleton.instance
}
private let delegate: SessionDelegate
private let queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL)
/// The underlying session.
public let session: NSURLSession
/// Whether to start requests immediately after being constructed. `true` by default.
public var startRequestsImmediately: Bool = true
/**
:param: configuration The configuration used to construct the managed session.
*/
required public init(configuration: NSURLSessionConfiguration? = nil) {
self.delegate = SessionDelegate()
self.session = NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
}
deinit {
self.session.invalidateAndCancel()
}
// MARK: -
/**
Creates a request for the specified method, URL string, parameters, and parameter encoding.
:param: method The HTTP method.
:param: URLString The URL string.
:param: parameters The parameters. `nil` by default.
:param: encoding The parameter encoding. `.URL` by default.
:returns: The created request.
*/
public func request(method: Method, _ URLString: URLStringConvertible, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL) -> Request {
return request(encoding.encode(URLRequest(method, URLString), parameters: parameters).0)
}
/**
Creates a request for the specified URL request.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: URLRequest The URL request
:returns: The created request.
*/
public func request(URLRequest: URLRequestConvertible) -> Request {
var dataTask: NSURLSessionDataTask?
dispatch_sync(queue) {
dataTask = self.session.dataTaskWithRequest(URLRequest.URLRequest)
}
let request = Request(session: session, task: dataTask!)
delegate[request.delegate.task] = request.delegate
if startRequestsImmediately {
request.resume()
}
return request
}
class SessionDelegate: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate {
private var subdelegates: [Int: Request.TaskDelegate]
private let subdelegateQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT)
private subscript(task: NSURLSessionTask) -> Request.TaskDelegate? {
get {
var subdelegate: Request.TaskDelegate?
dispatch_sync(subdelegateQueue) {
subdelegate = self.subdelegates[task.taskIdentifier]
}
return subdelegate
}
set {
dispatch_barrier_async(subdelegateQueue) {
self.subdelegates[task.taskIdentifier] = newValue
}
}
}
var sessionDidBecomeInvalidWithError: ((NSURLSession!, NSError!) -> Void)?
var sessionDidFinishEventsForBackgroundURLSession: ((NSURLSession!) -> Void)?
var sessionDidReceiveChallenge: ((NSURLSession!, NSURLAuthenticationChallenge) -> (NSURLSessionAuthChallengeDisposition, NSURLCredential!))?
var taskWillPerformHTTPRedirection: ((NSURLSession!, NSURLSessionTask!, NSHTTPURLResponse!, NSURLRequest!) -> (NSURLRequest!))?
var taskDidReceiveChallenge: ((NSURLSession!, NSURLSessionTask!, NSURLAuthenticationChallenge) -> (NSURLSessionAuthChallengeDisposition, NSURLCredential?))?
var taskDidSendBodyData: ((NSURLSession!, NSURLSessionTask!, Int64, Int64, Int64) -> Void)?
var taskNeedNewBodyStream: ((NSURLSession!, NSURLSessionTask!) -> (NSInputStream!))?
var dataTaskDidReceiveResponse: ((NSURLSession!, NSURLSessionDataTask!, NSURLResponse!) -> (NSURLSessionResponseDisposition))?
var dataTaskDidBecomeDownloadTask: ((NSURLSession!, NSURLSessionDataTask!) -> Void)?
var dataTaskDidReceiveData: ((NSURLSession!, NSURLSessionDataTask!, NSData!) -> Void)?
var dataTaskWillCacheResponse: ((NSURLSession!, NSURLSessionDataTask!, NSCachedURLResponse!) -> (NSCachedURLResponse))?
var downloadTaskDidFinishDownloadingToURL: ((NSURLSession!, NSURLSessionDownloadTask!, NSURL) -> (NSURL))?
var downloadTaskDidWriteData: ((NSURLSession!, NSURLSessionDownloadTask!, Int64, Int64, Int64) -> Void)?
var downloadTaskDidResumeAtOffset: ((NSURLSession!, NSURLSessionDownloadTask!, Int64, Int64) -> Void)?
required override init() {
self.subdelegates = Dictionary()
super.init()
}
// MARK: NSURLSessionDelegate
func URLSession(session: NSURLSession!, didBecomeInvalidWithError error: NSError!) {
sessionDidBecomeInvalidWithError?(session, error)
}
func URLSession(session: NSURLSession!, didReceiveChallenge challenge: NSURLAuthenticationChallenge!, completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void)!) {
if sessionDidReceiveChallenge != nil {
completionHandler(sessionDidReceiveChallenge!(session, challenge))
} else {
completionHandler(.PerformDefaultHandling, nil)
}
}
func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession!) {
sessionDidFinishEventsForBackgroundURLSession?(session)
}
// MARK: NSURLSessionTaskDelegate
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, willPerformHTTPRedirection response: NSHTTPURLResponse!, newRequest request: NSURLRequest!, completionHandler: ((NSURLRequest!) -> Void)!) {
var redirectRequest = request
if taskWillPerformHTTPRedirection != nil {
redirectRequest = taskWillPerformHTTPRedirection!(session, task, response, request)
}
completionHandler(redirectRequest)
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didReceiveChallenge challenge: NSURLAuthenticationChallenge!, completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void)!) {
if let delegate = self[task] {
delegate.URLSession(session, task: task, didReceiveChallenge: challenge, completionHandler: completionHandler)
} else {
URLSession(session, didReceiveChallenge: challenge, completionHandler: completionHandler)
}
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, needNewBodyStream completionHandler: ((NSInputStream!) -> Void)!) {
if let delegate = self[task] {
delegate.URLSession(session, task: task, needNewBodyStream: completionHandler)
}
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
if let delegate = self[task] as? Request.UploadTaskDelegate {
delegate.URLSession(session, task: task, didSendBodyData: bytesSent, totalBytesSent: totalBytesSent, totalBytesExpectedToSend: totalBytesExpectedToSend)
}
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didCompleteWithError error: NSError!) {
if let delegate = self[task] {
delegate.URLSession(session, task: task, didCompleteWithError: error)
self[task] = nil
}
}
// MARK: NSURLSessionDataDelegate
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, didReceiveResponse response: NSURLResponse!, completionHandler: ((NSURLSessionResponseDisposition) -> Void)!) {
var disposition: NSURLSessionResponseDisposition = .Allow
if dataTaskDidReceiveResponse != nil {
disposition = dataTaskDidReceiveResponse!(session, dataTask, response)
}
completionHandler(disposition)
}
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, didBecomeDownloadTask downloadTask: NSURLSessionDownloadTask!) {
let downloadDelegate = Request.DownloadTaskDelegate(task: downloadTask)
self[downloadTask] = downloadDelegate
}
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, didReceiveData data: NSData!) {
if let delegate = self[dataTask] as? Request.DataTaskDelegate {
delegate.URLSession(session, dataTask: dataTask, didReceiveData: data)
}
dataTaskDidReceiveData?(session, dataTask, data)
}
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, willCacheResponse proposedResponse: NSCachedURLResponse!, completionHandler: ((NSCachedURLResponse!) -> Void)!) {
var cachedResponse = proposedResponse
if dataTaskWillCacheResponse != nil {
cachedResponse = dataTaskWillCacheResponse!(session, dataTask, proposedResponse)
}
completionHandler(cachedResponse)
}
// MARK: NSURLSessionDownloadDelegate
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
if let delegate = self[downloadTask] as? Request.DownloadTaskDelegate {
delegate.URLSession(session, downloadTask: downloadTask, didFinishDownloadingToURL: location)
}
downloadTaskDidFinishDownloadingToURL?(session, downloadTask, location)
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if let delegate = self[downloadTask] as? Request.DownloadTaskDelegate {
delegate.URLSession(session, downloadTask: downloadTask, didWriteData: bytesWritten, totalBytesWritten: totalBytesWritten, totalBytesExpectedToWrite: totalBytesExpectedToWrite)
}
downloadTaskDidWriteData?(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
if let delegate = self[downloadTask] as? Request.DownloadTaskDelegate {
delegate.URLSession(session, downloadTask: downloadTask, didResumeAtOffset: fileOffset, expectedTotalBytes: expectedTotalBytes)
}
downloadTaskDidResumeAtOffset?(session, downloadTask, fileOffset, expectedTotalBytes)
}
// MARK: NSObject
override func respondsToSelector(selector: Selector) -> Bool {
switch selector {
case "URLSession:didBecomeInvalidWithError:":
return (sessionDidBecomeInvalidWithError != nil)
case "URLSession:didReceiveChallenge:completionHandler:":
return (sessionDidReceiveChallenge != nil)
case "URLSessionDidFinishEventsForBackgroundURLSession:":
return (sessionDidFinishEventsForBackgroundURLSession != nil)
case "URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:":
return (taskWillPerformHTTPRedirection != nil)
case "URLSession:dataTask:didReceiveResponse:completionHandler:":
return (dataTaskDidReceiveResponse != nil)
case "URLSession:dataTask:willCacheResponse:completionHandler:":
return (dataTaskWillCacheResponse != nil)
default:
return self.dynamicType.instancesRespondToSelector(selector)
}
}
}
}
// MARK: -
/**
Responsible for sending a request and receiving the response and associated data from the server, as well as managing its underlying `NSURLSessionTask`.
*/
public class Request {
private let delegate: TaskDelegate
/// The underlying task.
public var task: NSURLSessionTask { return delegate.task }
/// The session belonging to the underlying task.
public let session: NSURLSession
/// The request sent or to be sent to the server.
public var request: NSURLRequest { return task.originalRequest }
/// The response received from the server, if any.
public var response: NSHTTPURLResponse? { return task.response as? NSHTTPURLResponse }
/// The progress of the request lifecycle.
public var progress: NSProgress? { return delegate.progress }
private init(session: NSURLSession, task: NSURLSessionTask) {
self.session = session
switch task {
case is NSURLSessionUploadTask:
self.delegate = UploadTaskDelegate(task: task)
case is NSURLSessionDataTask:
self.delegate = DataTaskDelegate(task: task)
case is NSURLSessionDownloadTask:
self.delegate = DownloadTaskDelegate(task: task)
default:
self.delegate = TaskDelegate(task: task)
}
}
// MARK: Authentication
/**
Associates an HTTP Basic credential with the request.
:param: user The user.
:param: password The password.
:returns: The request.
*/
public func authenticate(#user: String, password: String) -> Self {
let credential = NSURLCredential(user: user, password: password, persistence: .ForSession)
return authenticate(usingCredential: credential)
}
/**
Associates a specified credential with the request.
:param: credential The credential.
:returns: The request.
*/
public func authenticate(usingCredential credential: NSURLCredential) -> Self {
delegate.credential = credential
return self
}
// MARK: Progress
/**
Sets a closure to be called periodically during the lifecycle of the request as data is written to or read from the server.
- For uploads, the progress closure returns the bytes written, total bytes written, and total bytes expected to write.
- For downloads, the progress closure returns the bytes read, total bytes read, and total bytes expected to write.
:param: closure The code to be executed periodically during the lifecycle of the request.
:returns: The request.
*/
public func progress(closure: ((Int64, Int64, Int64) -> Void)? = nil) -> Self {
if let uploadDelegate = delegate as? UploadTaskDelegate {
uploadDelegate.uploadProgress = closure
} else if let dataDelegate = delegate as? DataTaskDelegate {
dataDelegate.dataProgress = closure
} else if let downloadDelegate = delegate as? DownloadTaskDelegate {
downloadDelegate.downloadProgress = closure
}
return self
}
// MARK: Response
/**
A closure used by response handlers that takes a request, response, and data and returns a serialized object and any error that occured in the process.
*/
public typealias Serializer = (NSURLRequest, NSHTTPURLResponse?, NSData?) -> (AnyObject?, NSError?)
/**
Creates a response serializer that returns the associated data as-is.
:returns: A data response serializer.
*/
public class func responseDataSerializer() -> Serializer {
return { (request, response, data) in
return (data, nil)
}
}
/**
Adds a handler to be called once the request has finished.
:param: completionHandler The code to be executed once the request has finished.
:returns: The request.
*/
public func response(completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(Request.responseDataSerializer(), completionHandler: completionHandler)
}
/**
Adds a handler to be called once the request has finished.
:param: queue The queue on which the completion handler is dispatched.
:param: serializer The closure responsible for serializing the request, response, and data.
:param: completionHandler The code to be executed once the request has finished.
:returns: The request.
*/
public func response(queue: dispatch_queue_t? = nil, serializer: Serializer, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
dispatch_async(delegate.queue) {
let (responseObject: AnyObject?, serializationError: NSError?) = serializer(self.request, self.response, self.delegate.data)
dispatch_async(queue ?? dispatch_get_main_queue()) {
completionHandler(self.request, self.response, responseObject, self.delegate.error ?? serializationError)
}
}
return self
}
/**
Suspends the request.
*/
public func suspend() {
task.suspend()
}
/**
Resumes the request.
*/
public func resume() {
task.resume()
}
/**
Cancels the request.
*/
public func cancel() {
if let downloadDelegate = delegate as? DownloadTaskDelegate {
downloadDelegate.downloadTask.cancelByProducingResumeData { (data) in
downloadDelegate.resumeData = data
}
} else {
task.cancel()
}
}
class TaskDelegate: NSObject, NSURLSessionTaskDelegate {
let task: NSURLSessionTask
let queue: dispatch_queue_t
let progress: NSProgress
var data: NSData? { return nil }
private(set) var error: NSError?
var credential: NSURLCredential?
var taskWillPerformHTTPRedirection: ((NSURLSession!, NSURLSessionTask!, NSHTTPURLResponse!, NSURLRequest!) -> (NSURLRequest!))?
var taskDidReceiveChallenge: ((NSURLSession!, NSURLSessionTask!, NSURLAuthenticationChallenge) -> (NSURLSessionAuthChallengeDisposition, NSURLCredential?))?
var taskDidSendBodyData: ((NSURLSession!, NSURLSessionTask!, Int64, Int64, Int64) -> Void)?
var taskNeedNewBodyStream: ((NSURLSession!, NSURLSessionTask!) -> (NSInputStream!))?
init(task: NSURLSessionTask) {
self.task = task
self.progress = NSProgress(totalUnitCount: 0)
self.queue = {
let label: String = "com.alamofire.task-\(task.taskIdentifier)"
let queue = dispatch_queue_create((label as NSString).UTF8String, DISPATCH_QUEUE_SERIAL)
dispatch_suspend(queue)
return queue
}()
}
// MARK: NSURLSessionTaskDelegate
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, willPerformHTTPRedirection response: NSHTTPURLResponse!, newRequest request: NSURLRequest!, completionHandler: ((NSURLRequest!) -> Void)!) {
var redirectRequest = request
if taskWillPerformHTTPRedirection != nil {
redirectRequest = taskWillPerformHTTPRedirection!(session, task, response, request)
}
completionHandler(redirectRequest)
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didReceiveChallenge challenge: NSURLAuthenticationChallenge!, completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void)!) {
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if taskDidReceiveChallenge != nil {
(disposition, credential) = taskDidReceiveChallenge!(session, task, challenge)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
// TODO: Incorporate Trust Evaluation & TLS Chain Validation
switch challenge.protectionSpace.authenticationMethod! {
case NSURLAuthenticationMethodServerTrust:
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
default:
credential = self.credential ?? session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
}
if credential != nil {
disposition = .UseCredential
}
}
}
completionHandler(disposition, credential)
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, needNewBodyStream completionHandler: ((NSInputStream!) -> Void)!) {
var bodyStream: NSInputStream?
if taskNeedNewBodyStream != nil {
bodyStream = taskNeedNewBodyStream!(session, task)
}
completionHandler(bodyStream)
}
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didCompleteWithError error: NSError!) {
if error != nil {
self.error = error
}
dispatch_resume(queue)
}
}
class DataTaskDelegate: TaskDelegate, NSURLSessionDataDelegate {
var dataTask: NSURLSessionDataTask! { return task as NSURLSessionDataTask }
private var mutableData: NSMutableData
override var data: NSData? {
return mutableData
}
private var expectedContentLength: Int64?
var dataTaskDidReceiveResponse: ((NSURLSession!, NSURLSessionDataTask!, NSURLResponse!) -> (NSURLSessionResponseDisposition))?
var dataTaskDidBecomeDownloadTask: ((NSURLSession!, NSURLSessionDataTask!) -> Void)?
var dataTaskDidReceiveData: ((NSURLSession!, NSURLSessionDataTask!, NSData!) -> Void)?
var dataTaskWillCacheResponse: ((NSURLSession!, NSURLSessionDataTask!, NSCachedURLResponse!) -> (NSCachedURLResponse))?
var dataProgress: ((bytesReceived: Int64, totalBytesReceived: Int64, totalBytesExpectedToReceive: Int64) -> Void)?
override init(task: NSURLSessionTask) {
self.mutableData = NSMutableData()
super.init(task: task)
}
// MARK: NSURLSessionDataDelegate
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, didReceiveResponse response: NSURLResponse!, completionHandler: ((NSURLSessionResponseDisposition) -> Void)!) {
var disposition: NSURLSessionResponseDisposition = .Allow
expectedContentLength = response.expectedContentLength
if dataTaskDidReceiveResponse != nil {
disposition = dataTaskDidReceiveResponse!(session, dataTask, response)
}
completionHandler(disposition)
}
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, didBecomeDownloadTask downloadTask: NSURLSessionDownloadTask!) {
dataTaskDidBecomeDownloadTask?(session, dataTask)
}
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, didReceiveData data: NSData!) {
dataTaskDidReceiveData?(session, dataTask, data)
mutableData.appendData(data)
if let expectedContentLength = dataTask?.response?.expectedContentLength {
dataProgress?(bytesReceived: Int64(data.length), totalBytesReceived: Int64(mutableData.length), totalBytesExpectedToReceive: expectedContentLength)
}
}
func URLSession(session: NSURLSession!, dataTask: NSURLSessionDataTask!, willCacheResponse proposedResponse: NSCachedURLResponse!, completionHandler: ((NSCachedURLResponse!) -> Void)!) {
var cachedResponse = proposedResponse
if dataTaskWillCacheResponse != nil {
cachedResponse = dataTaskWillCacheResponse!(session, dataTask, proposedResponse)
}
completionHandler(cachedResponse)
}
}
}
// MARK: - Validation
extension Request {
/**
A closure used to validate a request that takes a URL request and URL response, and returns whether the request was valid.
*/
public typealias Validation = (NSURLRequest, NSHTTPURLResponse) -> (Bool)
/**
Validates the request, using the specified closure.
If validation fails, subsequent calls to response handlers will have an associated error.
:param: validation A closure to validate the request.
:returns: The request.
*/
public func validate(validation: Validation) -> Self {
dispatch_async(delegate.queue) {
if self.response != nil && self.delegate.error == nil {
if !validation(self.request, self.response!) {
self.delegate.error = NSError(domain: AlamofireErrorDomain, code: -1, userInfo: nil)
}
}
}
return self
}
// MARK: Status Code
private class func response(response: NSHTTPURLResponse, hasAcceptableStatusCode statusCodes: [Int]) -> Bool {
return contains(statusCodes, response.statusCode)
}
/**
Validates that the response has a status code in the specified range.
If validation fails, subsequent calls to response handlers will have an associated error.
:param: range The range of acceptable status codes.
:returns: The request.
*/
public func validate(statusCode range: Range<Int>) -> Self {
return validate { (_, response) in
return Request.response(response, hasAcceptableStatusCode: range.map({$0}))
}
}
/**
Validates that the response has a status code in the specified array.
If validation fails, subsequent calls to response handlers will have an associated error.
:param: array The acceptable status codes.
:returns: The request.
*/
public func validate(statusCode array: [Int]) -> Self {
return validate { (_, response) in
return Request.response(response, hasAcceptableStatusCode: array)
}
}
// MARK: Content-Type
private struct MIMEType {
let type: String
let subtype: String
init(_ string: String) {
let components = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).substringToIndex(string.rangeOfString(";")?.endIndex ?? string.endIndex).componentsSeparatedByString("/")
self.type = components.first!
self.subtype = components.last!
}
func matches(MIME: MIMEType) -> Bool {
switch (type, subtype) {
case ("*", "*"), ("*", MIME.subtype), (MIME.type, "*"), (MIME.type, MIME.subtype):
return true
default:
return false
}
}
}
private class func response(response: NSHTTPURLResponse, hasAcceptableContentType contentTypes: [String]) -> Bool {
if response.MIMEType != nil {
let responseMIMEType = MIMEType(response.MIMEType!)
for acceptableMIMEType in contentTypes.map({MIMEType($0)}) {
if acceptableMIMEType.matches(responseMIMEType) {
return true
}
}
}
return false
}
/**
Validates that the response has a content type in the specified array.
If validation fails, subsequent calls to response handlers will have an associated error.
:param: contentType The acceptable content types, which may specify wildcard types and/or subtypes.
:returns: The request.
*/
public func validate(contentType array: [String]) -> Self {
return validate {(_, response) in
return Request.response(response, hasAcceptableContentType: array)
}
}
// MARK: Automatic
/**
Validates that the response has a status code in the default acceptable range of 200...299, and that the content type matches any specified in the Accept HTTP header field.
If validation fails, subsequent calls to response handlers will have an associated error.
:returns: The request.
*/
public func validate() -> Self {
let acceptableStatusCodes: Range<Int> = 200..<300
let acceptableContentTypes: [String] = {
if let accept = self.request.valueForHTTPHeaderField("Accept") {
return accept.componentsSeparatedByString(",")
}
return ["*/*"]
}()
return validate(statusCode: acceptableStatusCodes).validate(contentType: acceptableContentTypes)
}
}
// MARK: - Upload
extension Manager {
private enum Uploadable {
case Data(NSURLRequest, NSData)
case File(NSURLRequest, NSURL)
case Stream(NSURLRequest, NSInputStream)
}
private func upload(uploadable: Uploadable) -> Request {
var uploadTask: NSURLSessionUploadTask!
var stream: NSInputStream?
switch uploadable {
case .Data(let request, let data):
uploadTask = session.uploadTaskWithRequest(request, fromData: data)
case .File(let request, let fileURL):
uploadTask = session.uploadTaskWithRequest(request, fromFile: fileURL)
case .Stream(let request, var stream):
uploadTask = session.uploadTaskWithStreamedRequest(request)
}
let request = Request(session: session, task: uploadTask)
if stream != nil {
request.delegate.taskNeedNewBodyStream = { _, _ in
return stream
}
}
delegate[request.delegate.task] = request.delegate
if startRequestsImmediately {
request.resume()
}
return request
}
// MARK: File
/**
Creates a request for uploading a file to the specified URL request.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: URLRequest The URL request
:param: file The file to upload
:returns: The created upload request.
*/
public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request {
return upload(.File(URLRequest.URLRequest, file))
}
// MARK: Data
/**
Creates a request for uploading data to the specified URL request.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: URLRequest The URL request
:param: data The data to upload
:returns: The created upload request.
*/
public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request {
return upload(.Data(URLRequest.URLRequest, data))
}
// MARK: Stream
/**
Creates a request for uploading a stream to the specified URL request.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: URLRequest The URL request
:param: stream The stream to upload
:returns: The created upload request.
*/
public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request {
return upload(.Stream(URLRequest.URLRequest, stream))
}
}
extension Request {
class UploadTaskDelegate: DataTaskDelegate {
var uploadTask: NSURLSessionUploadTask! { return task as NSURLSessionUploadTask }
var uploadProgress: ((Int64, Int64, Int64) -> Void)!
// MARK: NSURLSessionTaskDelegate
func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
if uploadProgress != nil {
uploadProgress(bytesSent, totalBytesSent, totalBytesExpectedToSend)
}
progress.totalUnitCount = totalBytesExpectedToSend
progress.completedUnitCount = totalBytesSent
}
}
}
// MARK: - Download
extension Manager {
private enum Downloadable {
case Request(NSURLRequest)
case ResumeData(NSData)
}
private func download(downloadable: Downloadable, destination: (NSURL, NSHTTPURLResponse) -> (NSURL)) -> Request {
var downloadTask: NSURLSessionDownloadTask!
switch downloadable {
case .Request(let request):
downloadTask = session.downloadTaskWithRequest(request)
case .ResumeData(let resumeData):
downloadTask = session.downloadTaskWithResumeData(resumeData)
}
let request = Request(session: session, task: downloadTask)
if let downloadDelegate = request.delegate as? Request.DownloadTaskDelegate {
downloadDelegate.downloadTaskDidFinishDownloadingToURL = { (session, downloadTask, URL) in
return destination(URL, downloadTask.response as NSHTTPURLResponse)
}
}
delegate[request.delegate.task] = request.delegate
if startRequestsImmediately {
request.resume()
}
return request
}
// MARK: Request
/**
Creates a request for downloading from the specified URL request.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: URLRequest The URL request
:param: destination The closure used to determine the destination of the downloaded file.
:returns: The created download request.
*/
public func download(URLRequest: URLRequestConvertible, destination: (NSURL, NSHTTPURLResponse) -> (NSURL)) -> Request {
return download(.Request(URLRequest.URLRequest), destination: destination)
}
// MARK: Resume Data
/**
Creates a request for downloading from the resume data produced from a previous request cancellation.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: resumeData The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional information.
:param: destination The closure used to determine the destination of the downloaded file.
:returns: The created download request.
*/
public func download(resumeData: NSData, destination: Request.DownloadFileDestination) -> Request {
return download(.ResumeData(resumeData), destination: destination)
}
}
extension Request {
/**
A closure executed once a request has successfully completed in order to determine where to move the temporary file written to during the download process. The closure takes two arguments: the temporary file URL and the URL response, and returns a single argument: the file URL where the temporary file should be moved.
*/
public typealias DownloadFileDestination = (NSURL, NSHTTPURLResponse) -> (NSURL)
/**
Creates a download file destination closure which uses the default file manager to move the temporary file to a file URL in the first available directory with the specified search path directory and search path domain mask.
:param: directory The search path directory. `.DocumentDirectory` by default.
:param: domain The search path domain mask. `.UserDomainMask` by default.
:returns: A download file destination closure.
*/
public class func suggestedDownloadDestination(directory: NSSearchPathDirectory = .DocumentDirectory, domain: NSSearchPathDomainMask = .UserDomainMask) -> DownloadFileDestination {
return { (temporaryURL, response) -> (NSURL) in
if let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {
return directoryURL.URLByAppendingPathComponent(response.suggestedFilename!)
}
return temporaryURL
}
}
class DownloadTaskDelegate: TaskDelegate, NSURLSessionDownloadDelegate {
var downloadTask: NSURLSessionDownloadTask! { return task as NSURLSessionDownloadTask }
var downloadProgress: ((Int64, Int64, Int64) -> Void)?
var resumeData: NSData?
override var data: NSData? { return resumeData }
var downloadTaskDidFinishDownloadingToURL: ((NSURLSession!, NSURLSessionDownloadTask!, NSURL) -> (NSURL))?
var downloadTaskDidWriteData: ((NSURLSession!, NSURLSessionDownloadTask!, Int64, Int64, Int64) -> Void)?
var downloadTaskDidResumeAtOffset: ((NSURLSession!, NSURLSessionDownloadTask!, Int64, Int64) -> Void)?
// MARK: NSURLSessionDownloadDelegate
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
if downloadTaskDidFinishDownloadingToURL != nil {
let destination = downloadTaskDidFinishDownloadingToURL!(session, downloadTask, location)
var fileManagerError: NSError?
NSFileManager.defaultManager().moveItemAtURL(location, toURL: destination, error: &fileManagerError)
if fileManagerError != nil {
error = fileManagerError
}
}
}
func URLSession(session: NSURLSession!, downloadTask: NSURLSessionDownloadTask!, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
downloadTaskDidWriteData?(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
downloadProgress?(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
progress.totalUnitCount = totalBytesExpectedToWrite
progress.completedUnitCount = totalBytesWritten
}
func URLSession(session: NSURLSession!, downloadTask: NSURLSessionDownloadTask!, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
downloadTaskDidResumeAtOffset?(session, downloadTask, fileOffset, expectedTotalBytes)
progress.totalUnitCount = expectedTotalBytes
progress.completedUnitCount = fileOffset
}
}
}
// MARK: - Printable
extension Request: Printable {
/// The textual representation used when written to an `OutputStreamType`, which includes the HTTP method and URL, as well as the response status code if a response has been received.
public var description: String {
var components: [String] = []
if request.HTTPMethod != nil {
components.append(request.HTTPMethod!)
}
components.append(request.URL.absoluteString!)
if response != nil {
components.append("(\(response!.statusCode))")
}
return join(" ", components)
}
}
extension Request: DebugPrintable {
func cURLRepresentation() -> String {
var components: [String] = ["$ curl -i"]
let URL = request.URL
if request.HTTPMethod != nil && request.HTTPMethod != "GET" {
components.append("-X \(request.HTTPMethod!)")
}
if let credentialStorage = self.session.configuration.URLCredentialStorage {
let protectionSpace = NSURLProtectionSpace(host: URL.host!, port: URL.port?.integerValue ?? 0, `protocol`: URL.scheme!, realm: URL.host!, authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
if let credentials = credentialStorage.credentialsForProtectionSpace(protectionSpace)?.values.array {
for credential: NSURLCredential in (credentials as [NSURLCredential]) {
components.append("-u \(credential.user!):\(credential.password!)")
}
} else {
if let credential = delegate.credential {
components.append("-u \(credential.user!):\(credential.password!)")
}
}
}
if let cookieStorage = session.configuration.HTTPCookieStorage {
if let cookies = cookieStorage.cookiesForURL(URL) as? [NSHTTPCookie] {
if !cookies.isEmpty {
let string = cookies.reduce(""){ $0 + "\($1.name)=\($1.value);" }
components.append("-b \"\(string.substringToIndex(string.endIndex.predecessor()))\"")
}
}
}
for (field, value) in request.allHTTPHeaderFields! {
switch field {
case "Cookie":
continue
default:
components.append("-H \"\(field): \(value)\"")
}
}
for (field, value) in session.configuration.HTTPAdditionalHeaders! {
switch field {
case "Cookie":
continue
default:
components.append("-H \"\(field): \(value)\"")
}
}
if let HTTPBody = request.HTTPBody {
if let escapedBody = NSString(data: HTTPBody, encoding: NSUTF8StringEncoding)?.stringByReplacingOccurrencesOfString("\"", withString: "\\\"") {
components.append("-d \"\(escapedBody)\"")
}
}
components.append("\"\(URL.absoluteString!)\"")
return join(" \\\n\t", components)
}
/// The textual representation used when written to an `OutputStreamType`, in the form of a cURL command.
public var debugDescription: String {
return cURLRepresentation()
}
}
// MARK: - Response Serializers
// MARK: String
extension Request {
/**
Creates a response serializer that returns a string initialized from the response data with the specified string encoding.
:param: encoding The string encoding. `NSUTF8StringEncoding` by default.
:returns: A string response serializer.
*/
public class func stringResponseSerializer(encoding: NSStringEncoding = NSUTF8StringEncoding) -> Serializer {
return { (_, _, data) in
let string = NSString(data: data!, encoding: encoding)
return (string, nil)
}
}
/**
Adds a handler to be called once the request has finished.
:param: completionHandler A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the string, if one could be created from the URL response and data, and any error produced while creating the string.
:returns: The request.
*/
public func responseString(completionHandler: (NSURLRequest, NSHTTPURLResponse?, String?, NSError?) -> Void) -> Self {
return responseString(completionHandler: completionHandler)
}
/**
Adds a handler to be called once the request has finished.
:param: encoding The string encoding. `NSUTF8StringEncoding` by default.
:param: completionHandler A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the string, if one could be created from the URL response and data, and any error produced while creating the string.
:returns: The request.
*/
public func responseString(encoding: NSStringEncoding = NSUTF8StringEncoding, completionHandler: (NSURLRequest, NSHTTPURLResponse?, String?, NSError?) -> Void) -> Self {
return response(serializer: Request.stringResponseSerializer(encoding: encoding), completionHandler: { request, response, string, error in
completionHandler(request, response, string as? String, error)
})
}
}
// MARK: JSON
extension Request {
/**
Creates a response serializer that returns a JSON object constructed from the response data using `NSJSONSerialization` with the specified reading options.
:param: options The JSON serialization reading options. `.AllowFragments` by default.
:returns: A JSON object response serializer.
*/
public class func JSONResponseSerializer(options: NSJSONReadingOptions = .AllowFragments) -> Serializer {
return { (request, response, data) in
if data == nil {
return (nil, nil)
}
var serializationError: NSError?
let JSON: AnyObject? = NSJSONSerialization.JSONObjectWithData(data!, options: options, error: &serializationError)
return (JSON, serializationError)
}
}
/**
Adds a handler to be called once the request has finished.
:param: completionHandler A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the JSON object, if one could be created from the URL response and data, and any error produced while creating the JSON object.
:returns: The request.
*/
public func responseJSON(completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return responseJSON(completionHandler: completionHandler)
}
/**
Adds a handler to be called once the request has finished.
:param: options The JSON serialization reading options. `.AllowFragments` by default.
:param: completionHandler A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the JSON object, if one could be created from the URL response and data, and any error produced while creating the JSON object.
:returns: The request.
*/
public func responseJSON(options: NSJSONReadingOptions = .AllowFragments, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(serializer: Request.JSONResponseSerializer(options: options), completionHandler: { (request, response, JSON, error) in
completionHandler(request, response, JSON, error)
})
}
}
// MARK: Property List
extension Request {
/**
Creates a response serializer that returns an object constructed from the response data using `NSPropertyListSerialization` with the specified reading options.
:param: options The property list reading options. `0` by default.
:returns: A property list object response serializer.
*/
public class func propertyListResponseSerializer(options: NSPropertyListReadOptions = 0) -> Serializer {
return { (request, response, data) in
if data == nil {
return (nil, nil)
}
var propertyListSerializationError: NSError?
let plist: AnyObject? = NSPropertyListSerialization.propertyListWithData(data!, options: options, format: nil, error: &propertyListSerializationError)
return (plist, propertyListSerializationError)
}
}
/**
Adds a handler to be called once the request has finished.
:param: completionHandler A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the property list, if one could be created from the URL response and data, and any error produced while creating the property list.
:returns: The request.
*/
public func responsePropertyList(completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return responsePropertyList(completionHandler: completionHandler)
}
/**
Adds a handler to be called once the request has finished.
:param: options The property list reading options. `0` by default.
:param: completionHandler A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the property list, if one could be created from the URL response and data, and any error produced while creating the property list.
:returns: The request.
*/
public func responsePropertyList(options: NSPropertyListReadOptions = 0, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(serializer: Request.propertyListResponseSerializer(options: options), completionHandler: { (request, response, plist, error) in
completionHandler(request, response, plist, error)
})
}
}
// MARK: - Convenience -
private func URLRequest(method: Method, URL: URLStringConvertible) -> NSURLRequest {
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URL.URLString)!)
mutableURLRequest.HTTPMethod = method.rawValue
return mutableURLRequest
}
// MARK: - Request
/**
Creates a request using the shared manager instance for the specified method, URL string, parameters, and parameter encoding.
:param: method The HTTP method.
:param: URLString The URL string.
:param: parameters The parameters. `nil` by default.
:param: encoding The parameter encoding. `.URL` by default.
:returns: The created request.
*/
public func request(method: Method, URLString: URLStringConvertible, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL) -> Request {
return request(encoding.encode(URLRequest(method, URLString), parameters: parameters).0)
}
/**
Creates a request using the shared manager instance for the specified URL request.
If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
:param: URLRequest The URL request
:returns: The created request.
*/
public func request(URLRequest: URLRequestConvertible) -> Request {
return Manager.sharedInstance.request(URLRequest.URLRequest)
}
// MARK: - Upload
// MARK: File
/**
Creates an upload request using the shared manager instance for the specified method, URL string, and file.
:param: method The HTTP method.
:param: URLString The URL string.
:param: file The file to upload.
:returns: The created upload request.
*/
public func upload(method: Method, URLString: URLStringConvertible, file: NSURL) -> Request {
return Manager.sharedInstance.upload(URLRequest(method, URLString), file: file)
}
/**
Creates an upload request using the shared manager instance for the specified URL request and file.
:param: URLRequest The URL request.
:param: file The file to upload.
:returns: The created upload request.
*/
public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request {
return Manager.sharedInstance.upload(URLRequest, file: file)
}
// MARK: Data
/**
Creates an upload request using the shared manager instance for the specified method, URL string, and data.
:param: method The HTTP method.
:param: URLString The URL string.
:param: data The data to upload.
:returns: The created upload request.
*/
public func upload(method: Method, URLString: URLStringConvertible, data: NSData) -> Request {
return Manager.sharedInstance.upload(URLRequest(method, URLString), data: data)
}
/**
Creates an upload request using the shared manager instance for the specified URL request and data.
:param: URLRequest The URL request.
:param: data The data to upload.
:returns: The created upload request.
*/
public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request {
return Manager.sharedInstance.upload(URLRequest, data: data)
}
// MARK: Stream
/**
Creates an upload request using the shared manager instance for the specified method, URL string, and stream.
:param: method The HTTP method.
:param: URLString The URL string.
:param: stream The stream to upload.
:returns: The created upload request.
*/
public func upload(method: Method, URLString: URLStringConvertible, stream: NSInputStream) -> Request {
return Manager.sharedInstance.upload(URLRequest(method, URLString), stream: stream)
}
/**
Creates an upload request using the shared manager instance for the specified URL request and stream.
:param: URLRequest The URL request.
:param: stream The stream to upload.
:returns: The created upload request.
*/
public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request {
return Manager.sharedInstance.upload(URLRequest, stream: stream)
}
// MARK: - Download
// MARK: URL Request
/**
Creates a download request using the shared manager instance for the specified method and URL string.
:param: method The HTTP method.
:param: URLString The URL string.
:param: destination The closure used to determine the destination of the downloaded file.
:returns: The created download request.
*/
public func download(method: Method, URLString: URLStringConvertible, destination: Request.DownloadFileDestination) -> Request {
return Manager.sharedInstance.download(URLRequest(method, URLString), destination: destination)
}
/**
Creates a download request using the shared manager instance for the specified URL request.
:param: URLRequest The URL request.
:param: destination The closure used to determine the destination of the downloaded file.
:returns: The created download request.
*/
public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request {
return Manager.sharedInstance.download(URLRequest, destination: destination)
}
// MARK: Resume Data
/**
Creates a request using the shared manager instance for downloading from the resume data produced from a previous request cancellation.
:param: resumeData The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional information.
:param: destination The closure used to determine the destination of the downloaded file.
:returns: The created download request.
*/
public func download(resumeData data: NSData, destination: Request.DownloadFileDestination) -> Request {
return Manager.sharedInstance.download(data, destination: destination)
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.alamofire.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
951B3FAD58824E9B86E74AD3 /* Pods_iOS_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EEEDE5D19C6F39708A8F116 /* Pods_iOS_Example.framework */; };
F8111E0B19A951050040E7D1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8111E0A19A951050040E7D1 /* AppDelegate.swift */; };
F8111E0D19A951050040E7D1 /* MasterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8111E0C19A951050040E7D1 /* MasterViewController.swift */; };
F8111E0F19A951050040E7D1 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8111E0E19A951050040E7D1 /* DetailViewController.swift */; };
F8111E1219A951050040E7D1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F8111E1019A951050040E7D1 /* Main.storyboard */; };
F8111E1419A951050040E7D1 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F8111E1319A951050040E7D1 /* Images.xcassets */; };
F8E6024019CB3C0700A3E7F1 /* HTTPBin.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E6023F19CB3C0700A3E7F1 /* HTTPBin.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
4EEEDE5D19C6F39708A8F116 /* Pods_iOS_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iOS_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E72AAD1560ED38C6203AE071 /* Pods-iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-iOS Example/Pods-iOS Example.release.xcconfig"; sourceTree = "<group>"; };
F787F2A3625E02D003BE2209 /* Pods-iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-iOS Example/Pods-iOS Example.debug.xcconfig"; sourceTree = "<group>"; };
F8111E0519A951050040E7D1 /* iOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
F8111E0919A951050040E7D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F8111E0A19A951050040E7D1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F8111E0C19A951050040E7D1 /* MasterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterViewController.swift; sourceTree = "<group>"; };
F8111E0E19A951050040E7D1 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
F8111E1119A951050040E7D1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
F8111E1319A951050040E7D1 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
F8E6023F19CB3C0700A3E7F1 /* HTTPBin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPBin.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
F8111E0219A951050040E7D1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
951B3FAD58824E9B86E74AD3 /* Pods_iOS_Example.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2D42BDE636F2C5E26D98A0B6 /* Pods */ = {
isa = PBXGroup;
children = (
F787F2A3625E02D003BE2209 /* Pods-iOS Example.debug.xcconfig */,
E72AAD1560ED38C6203AE071 /* Pods-iOS Example.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
D8ADE35CA568F7C97750679B /* Frameworks */ = {
isa = PBXGroup;
children = (
4EEEDE5D19C6F39708A8F116 /* Pods_iOS_Example.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
F8111DFC19A951050040E7D1 = {
isa = PBXGroup;
children = (
F8111E0719A951050040E7D1 /* Source */,
F8111E0619A951050040E7D1 /* Products */,
2D42BDE636F2C5E26D98A0B6 /* Pods */,
D8ADE35CA568F7C97750679B /* Frameworks */,
);
sourceTree = "<group>";
};
F8111E0619A951050040E7D1 /* Products */ = {
isa = PBXGroup;
children = (
F8111E0519A951050040E7D1 /* iOS Example.app */,
);
name = Products;
sourceTree = "<group>";
};
F8111E0719A951050040E7D1 /* Source */ = {
isa = PBXGroup;
children = (
F8111E0A19A951050040E7D1 /* AppDelegate.swift */,
F8111E0C19A951050040E7D1 /* MasterViewController.swift */,
F8111E0E19A951050040E7D1 /* DetailViewController.swift */,
F8E6023F19CB3C0700A3E7F1 /* HTTPBin.swift */,
F8111E1019A951050040E7D1 /* Main.storyboard */,
F8111E1319A951050040E7D1 /* Images.xcassets */,
F8111E0819A951050040E7D1 /* Supporting Files */,
);
name = Source;
path = Example;
sourceTree = "<group>";
};
F8111E0819A951050040E7D1 /* Supporting Files */ = {
isa = PBXGroup;
children = (
F8111E0919A951050040E7D1 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
F8111E0419A951050040E7D1 /* iOS Example */ = {
isa = PBXNativeTarget;
buildConfigurationList = F8111E2319A951050040E7D1 /* Build configuration list for PBXNativeTarget "iOS Example" */;
buildPhases = (
6540B3CA5F945114F2BD9C7B /* Check Pods Manifest.lock */,
F8111E0119A951050040E7D1 /* Sources */,
F8111E0219A951050040E7D1 /* Frameworks */,
F8111E0319A951050040E7D1 /* Resources */,
232F8168EB8673C9D2405BA7 /* Embed Pods Frameworks */,
B81850C1CB84CCCCFC8FFC52 /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = "iOS Example";
productName = Alamofire;
productReference = F8111E0519A951050040E7D1 /* iOS Example.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
F8111DFD19A951050040E7D1 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0600;
ORGANIZATIONNAME = Alamofire;
TargetAttributes = {
F8111E0419A951050040E7D1 = {
CreatedOnToolsVersion = 6.0;
};
};
};
buildConfigurationList = F8111E0019A951050040E7D1 /* Build configuration list for PBXProject "iOS Example" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = F8111DFC19A951050040E7D1;
productRefGroup = F8111E0619A951050040E7D1 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
F8111E0419A951050040E7D1 /* iOS Example */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
F8111E0319A951050040E7D1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F8111E1219A951050040E7D1 /* Main.storyboard in Resources */,
F8111E1419A951050040E7D1 /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
232F8168EB8673C9D2405BA7 /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-iOS Example/Pods-iOS Example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
6540B3CA5F945114F2BD9C7B /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
B81850C1CB84CCCCFC8FFC52 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-iOS Example/Pods-iOS Example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
F8111E0119A951050040E7D1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F8111E0F19A951050040E7D1 /* DetailViewController.swift in Sources */,
F8E6024019CB3C0700A3E7F1 /* HTTPBin.swift in Sources */,
F8111E0D19A951050040E7D1 /* MasterViewController.swift in Sources */,
F8111E0B19A951050040E7D1 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
F8111E1019A951050040E7D1 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
F8111E1119A951050040E7D1 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
F8111E2119A951050040E7D1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
F8111E2219A951050040E7D1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
F8111E2419A951050040E7D1 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = F787F2A3625E02D003BE2209 /* Pods-iOS Example.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "iOS Example";
};
name = Debug;
};
F8111E2519A951050040E7D1 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E72AAD1560ED38C6203AE071 /* Pods-iOS Example.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "iOS Example";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
F8111E0019A951050040E7D1 /* Build configuration list for PBXProject "iOS Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F8111E2119A951050040E7D1 /* Debug */,
F8111E2219A951050040E7D1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F8111E2319A951050040E7D1 /* Build configuration list for PBXNativeTarget "iOS Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F8111E2419A951050040E7D1 /* Debug */,
F8111E2519A951050040E7D1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = F8111DFD19A951050040E7D1 /* Project object */;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment