Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
592 changes: 427 additions & 165 deletions ADVOperation.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions Demo/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
49 changes: 49 additions & 0 deletions Demo/Base.lproj/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8076" systemVersion="14D121" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8063"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2015 Advanced Operation. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
<rect key="frame" x="20" y="559" width="560" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Demo" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
<rect key="frame" x="20" y="180" width="560" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
<constraint firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
<constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
62 changes: 62 additions & 0 deletions Demo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8121.20" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="QAj-Jn-gO0">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8101.16"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="A4x-ux-wzS">
<objects>
<tableViewController id="djY-HX-be3" customClass="ViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="rcX-Sx-qcZ">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="PXE-i2-Ei8">
<rect key="frame" x="0.0" y="86" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="PXE-i2-Ei8" id="0ko-qR-sHG">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="djY-HX-be3" id="A5D-GP-zL5"/>
<outlet property="delegate" destination="djY-HX-be3" id="qmE-g0-P8r"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="ppX-J8-DRL">
<barButtonItem key="rightBarButtonItem" title="Start" id="vvd-et-5dp">
<connections>
<action selector="startAction:" destination="djY-HX-be3" id="Jyu-La-aOJ"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ddn-se-DqH" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1187" y="334"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="v3F-Zp-V2C">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="QAj-Jn-gO0" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wJY-4v-RgA">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="djY-HX-be3" kind="relationship" relationship="rootViewController" id="wSH-6y-0Iv"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="AGj-78-lev" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="375" y="334"/>
</scene>
</scenes>
</document>
22 changes: 22 additions & 0 deletions Demo/Classes/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// AppDelegate.swift
// Demo
//
// Created by Phillipp (LMIS) on 07/07/15.
// Copyright © 2015 Advanced Operation. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject:AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}

}

113 changes: 113 additions & 0 deletions Demo/Classes/Operations/HTTPBinNetworkOperation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// Created by Phillipp (LMIS) on 07/07/15.
// Copyright (c) 2015 Advanced Operation. All rights reserved.
//

import Foundation
import ADVOperation


final class HTTPBinNetworkOperation: GroupOperation {

let cacheFile:NSURL

init(cacheFile:NSURL) {

self.cacheFile = cacheFile

super.init(operations: [])
self.name = "HTTPBin Operation"

let url = NSURL(string: "http://httpbin.org/image/png")!
let session = NSURLSession.sharedSession()

let task = session.downloadTaskWithURL(url) {
url, response, error in
self.downloadFinished(url, response: response as? NSHTTPURLResponse, error: error)
}

if let task = task {
let taskOperation = URLSessionTaskOperation(task: task)

let reachabilityCondition = ReachabilityCondition(host: url)
taskOperation.addCondition(reachabilityCondition)

let networkObserver = NetworkObserver()
taskOperation.addObserver(networkObserver)

addOperation(taskOperation)
}

}

private func downloadFinished(url: NSURL?, response: NSHTTPURLResponse?, error: NSError?) {

if let error = error {
print("download failed \(error)")
} else {
print("download succeeded")
}

if let localURL = url {
do {
/*
If we already have a file at this location, just delete it.
Also, swallow the error, because we don't really care about it.
*/
try NSFileManager.defaultManager().removeItemAtURL(cacheFile)
}
catch {
}

do {
try NSFileManager.defaultManager().moveItemAtURL(localURL, toURL: cacheFile)
print("data successfully moved to \(cacheFile.absoluteString)")
}
catch let error as NSError {
aggregateError(error)
}

} else if let error = error {
aggregateError(error)
} else {
// Do nothing, and the operation will automatically finish.
}


}

override func finished(errors: [NSError]) {
guard let firstError = errors.first where userInitiated else { return }

/*
We failed to load the model on a user initiated operation try and present
an error.
*/

let alert = AlertOperation()

alert.title = "Unable to load download image"

alert.message = "An error occurred while downloading image. \(firstError.localizedDescription). Please try again later."

// No custom action for this button.
alert.addAction("Retry Later", style: .Cancel)

/*
For this operation, the `loadHandler` is only ever invoked if there are
no errors, so if we get to this point we know that it was not executed.
This means that we can offer to the user to try loading the model again,
simply by creating a new copy of the operation and giving it the same
loadHandler.
*/
alert.addAction("Retry Now") { alertOperation in
let retryOperation = HTTPBinNetworkOperation(cacheFile:self.cacheFile)
retryOperation.userInitiated = true
alertOperation.produceOperation(retryOperation)
}

produceOperation(alert)
}


}
76 changes: 76 additions & 0 deletions Demo/Classes/ViewControllers/ViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// ViewController.swift
// Demo
//
// Created by Phillipp on 07/07/15.
// Copyright © 2015 Advanced Operation. All rights reserved.
//

import UIKit
import ADVOperation

class ViewController: UITableViewController, OperationQueueDelegate {

let operationQueue = OperationQueue()

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

// self.operationQueue.delegate = self
}

// MARK: Actions

@IBAction func startAction(sender: UIBarButtonItem) {

do {
let cachesFolder = try NSFileManager.defaultManager().URLForDirectory(.CachesDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let cacheFile = cachesFolder.URLByAppendingPathComponent("image.png")

let networkOperation = HTTPBinNetworkOperation(cacheFile: cacheFile)
networkOperation.userInitiated = true
self.operationQueue.addOperation(networkOperation)

} catch let error as NSError {
print("error getting caches folder \(error)")
}

}


// MARK: UITableViewDataSource

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.operationQueue.operationCount
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath)
let operation = self.operationQueue.operations[indexPath.item]
let operationName = operation.name ?? "no name"
cell.textLabel?.text = "Name: \(operationName) - State: \(operation.ready)"

return cell
}

// MARK: OperationQueue Delegate

func operationQueue(operationQueue: OperationQueue, willAddOperation operation: NSOperation) {
print("OperationCount: \(operationQueue.operationCount)")
NSOperationQueue.mainQueue().addOperationWithBlock {
self.tableView.reloadData()
}
}

func operationQueue(operationQueue: OperationQueue, operationDidFinish operation: NSOperation, withErrors errors: [NSError]) {
print("OperationCount: \(operationQueue.operationCount)")
NSOperationQueue.mainQueue().addOperationWithBlock {
self.tableView.reloadData()
}
}



}

Loading