Repository: agelessman/MCDownloadManager
Branch: master
Commit: 16abea6dfcc3
Files: 46
Total size: 133.2 KB
Directory structure:
gitextract_f5m8txjr/
├── LICENSE
├── MCDownloadManager/
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets/
│ │ └── AppIcon.appiconset/
│ │ └── Contents.json
│ ├── Base.lproj/
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── MCDownloadManager/
│ │ ├── MCDefine.h
│ │ ├── MCDownloadManager.h
│ │ └── MCDownloadManager.m
│ ├── MCDownloadManager.entitlements
│ ├── Networking/
│ │ ├── MCURLRequest.h
│ │ ├── MCURLRequest.m
│ │ ├── MCURLRequestCenter.h
│ │ ├── MCURLRequestCenter.m
│ │ ├── MCURLResponse.h
│ │ ├── MCURLResponse.m
│ │ ├── MCURLSessionConfiguration.h
│ │ ├── MCURLSessionConfiguration.m
│ │ ├── MCWiFiManager.h
│ │ └── MCWiFiManager.m
│ ├── QKYDelayButton.h
│ ├── QKYDelayButton.m
│ ├── TableViewCell.h
│ ├── TableViewCell.m
│ ├── TestViewController.h
│ ├── TestViewController.m
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
├── MCDownloadManager.podspec
├── MCDownloadManager.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata/
│ │ ├── M.C.xcuserdatad/
│ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── machao.xcuserdatad/
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── test.xcuserdatad/
│ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata/
│ ├── M.C.xcuserdatad/
│ │ ├── xcdebugger/
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes/
│ │ ├── MCDownloadManager.xcscheme
│ │ └── xcschememanagement.plist
│ ├── machao.xcuserdatad/
│ │ ├── xcdebugger/
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes/
│ │ ├── MCDownloadManager.xcscheme
│ │ └── xcschememanagement.plist
│ └── test.xcuserdatad/
│ ├── xcdebugger/
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes/
│ ├── MCDownloadManager.xcscheme
│ └── xcschememanagement.plist
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENSE
================================================
Copyright (c) 2014-2016 Alamofire Software Foundation (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.
================================================
FILE: MCDownloadManager/AppDelegate.h
================================================
//
// AppDelegate.h
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: MCDownloadManager/AppDelegate.m
================================================
//
// AppDelegate.m
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
================================================
FILE: MCDownloadManager/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"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"
}
}
================================================
FILE: MCDownloadManager/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
</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"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</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>
================================================
FILE: MCDownloadManager/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="15G1212" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="XBH-d4-pjl">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Navigation Controller-->
<scene sceneID="xXd-Ok-nvl">
<objects>
<navigationController id="XBH-d4-pjl" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="EFd-Sx-eSk">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="DCV-lv-mg4" kind="relationship" relationship="rootViewController" id="OLh-JF-V4q"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="U6U-NF-iMW" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-1306" y="65"/>
</scene>
<!--Title-->
<scene sceneID="mT5-iq-vsu">
<objects>
<tableViewController id="DCV-lv-mg4" customClass="ViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="100" sectionHeaderHeight="28" sectionFooterHeight="28" id="gU9-Ju-GJy">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="cell" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" rowHeight="100" id="nfC-Nz-jA2" customClass="TableViewCell">
<rect key="frame" x="0.0" y="28" width="375" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nfC-Nz-jA2" id="N2j-3F-jn1">
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="onP-Sp-BKl">
<rect key="frame" x="8" y="8" width="584" height="10"/>
<constraints>
<constraint firstAttribute="height" constant="10" id="cg5-ac-4tP"/>
</constraints>
</progressView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8XZ-N6-uuX">
<rect key="frame" x="8" y="48" width="150" height="20"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="ZMO-ae-wpX"/>
<constraint firstAttribute="width" constant="150" id="fjh-Bz-FWY"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Cx6-u4-a8j" customClass="QKYDelayButton">
<rect key="frame" x="285" y="42.5" width="80" height="47"/>
<constraints>
<constraint firstAttribute="height" constant="47" id="LnF-HM-gpd"/>
<constraint firstAttribute="width" constant="80" id="Rch-SF-Ybl"/>
</constraints>
<connections>
<action selector="buttonAction:" destination="nfC-Nz-jA2" eventType="touchUpInside" id="w57-kz-86h"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SSQ-qo-aWm">
<rect key="frame" x="165" y="60.5" width="100" height="21"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="1eo-Yw-uG0"/>
<constraint firstAttribute="width" constant="100" id="Fq1-6B-REw"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="P5Q-hN-O01">
<rect key="frame" x="190" y="40" width="87" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="onP-Sp-BKl" firstAttribute="top" secondItem="N2j-3F-jn1" secondAttribute="topMargin" id="20v-GF-XBu"/>
<constraint firstAttribute="bottom" secondItem="Cx6-u4-a8j" secondAttribute="bottom" constant="10" id="FBB-ZA-9Wp"/>
<constraint firstAttribute="trailing" secondItem="Cx6-u4-a8j" secondAttribute="trailing" constant="10" id="R44-Yz-iIa"/>
<constraint firstAttribute="bottomMargin" secondItem="SSQ-qo-aWm" secondAttribute="bottom" constant="10" id="XOY-5y-o64"/>
<constraint firstItem="onP-Sp-BKl" firstAttribute="leading" secondItem="N2j-3F-jn1" secondAttribute="leadingMargin" id="jHA-vd-WGL"/>
<constraint firstAttribute="trailingMargin" secondItem="onP-Sp-BKl" secondAttribute="trailing" id="msF-1M-XCf"/>
<constraint firstItem="Cx6-u4-a8j" firstAttribute="leading" secondItem="SSQ-qo-aWm" secondAttribute="trailing" constant="20" id="olu-zH-2t6"/>
<constraint firstItem="8XZ-N6-uuX" firstAttribute="top" secondItem="onP-Sp-BKl" secondAttribute="bottom" constant="30" id="rb7-hH-38B"/>
<constraint firstItem="8XZ-N6-uuX" firstAttribute="leading" secondItem="N2j-3F-jn1" secondAttribute="leadingMargin" id="xVp-HN-Fia"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" red="0.0" green="0.59999999999999998" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<outlet property="button" destination="Cx6-u4-a8j" id="xd2-yN-sUM"/>
<outlet property="bytesLable" destination="SSQ-qo-aWm" id="gO0-ew-W9U"/>
<outlet property="nameLabel" destination="8XZ-N6-uuX" id="Hel-QO-2ba"/>
<outlet property="progressView" destination="onP-Sp-BKl" id="Cbo-FG-bqf"/>
<outlet property="speedLable" destination="P5Q-hN-O01" id="TKd-IQ-qZu"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="DCV-lv-mg4" id="HSJ-Dh-1ns"/>
<outlet property="delegate" destination="DCV-lv-mg4" id="pln-za-6KH"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Title" id="X4T-5i-kQK">
<barButtonItem key="rightBarButtonItem" title="next" id="Fs3-Ne-iPa">
<connections>
<action selector="nextAction:" destination="DCV-lv-mg4" id="kRB-K3-crW"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Xeo-Ys-Jau" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-756" y="20.239880059970016"/>
</scene>
</scenes>
</document>
================================================
FILE: MCDownloadManager/Info.plist
================================================
<?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>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</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>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string></string>
<key>NSContactsUsageDescription</key>
<string></string>
<key>NSLocationAlwaysUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string></string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
</dict>
</plist>
================================================
FILE: MCDownloadManager/MCDownloadManager/MCDefine.h
================================================
//
// MCDefine.h
// JZGChryslerForPad
//
// Created by test on 16/12/6.
// Copyright © 2016年 Beijing JingZhenGu Information Technology Co.Ltd. All rights reserved.
//
#ifndef MCDefine_h
#define MCDefine_h
// Use dispatch_main_async_safe instead of dispatch_async(dispatch_get_main_queue(), block)
#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block)\
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
#endif
#endif /* MCDefine_h */
================================================
FILE: MCDownloadManager/MCDownloadManager/MCDownloadManager.h
================================================
//
// MCDownloadManager.h
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXPORT NSString * const MCDownloadCacheFolderName;
@class MCDownloadReceipt;
/** The download state */
typedef NS_ENUM(NSUInteger, MCDownloadState) {
MCDownloadStateNone, /** default */
MCDownloadStateWillResume, /** waiting */
MCDownloadStateDownloading, /** downloading */
MCDownloadStateSuspened, /** suspened */
MCDownloadStateCompleted, /** download completed */
MCDownloadStateFailed /** download failed */
};
/** The download prioritization */
typedef NS_ENUM(NSInteger, MCDownloadPrioritization) {
MCDownloadPrioritizationFIFO, /** first in first out */
MCDownloadPrioritizationLIFO /** last in first out */
};
typedef void (^MCSucessBlock)(NSURLRequest * _Nullable, NSHTTPURLResponse * _Nullable, NSURL * _Nonnull);
typedef void (^MCFailureBlock)(NSURLRequest * _Nullable, NSHTTPURLResponse * _Nullable, NSError * _Nonnull);
typedef void (^MCProgressBlock)(NSProgress * _Nonnull,MCDownloadReceipt *);
/**
* The receipt of a downloader,we can get all the informationg by the receipt.
*/
@interface MCDownloadReceipt : NSObject <NSCoding>
/**
* Download State
*/
@property (nonatomic, assign, readonly) MCDownloadState state;
@property (nonatomic, copy, readonly, nonnull) NSString *url;
@property (nonatomic, copy, readonly, nonnull) NSString *filePath;
@property (nonatomic, copy, readonly, nullable) NSString *filename;
@property (nonatomic, copy, readonly, nullable) NSString *truename;
@property (nonatomic, copy, readonly) NSString *speed; // KB/s
@property (assign, nonatomic, readonly) long long totalBytesWritten;
@property (assign, nonatomic, readonly) long long totalBytesExpectedToWrite;
@property (nonatomic, copy, readonly, nonnull) NSProgress *progress;
@property (nonatomic, strong, readonly, nullable) NSError *error;
@property (nonatomic,copy)MCSucessBlock successBlock;
@property (nonatomic,copy)MCFailureBlock failureBlock;
@property (nonatomic,copy)MCProgressBlock progressBlock;
@end
@protocol MCDownloadControlDelegate <NSObject>
- (void)suspendWithURL:(NSString * _Nonnull)url;
- (void)suspendWithDownloadReceipt:(MCDownloadReceipt * _Nonnull)receipt;
- (void)removeWithURL:(NSString * _Nonnull)url;
- (void)removeWithDownloadReceipt:(MCDownloadReceipt * _Nonnull)receipt;
@end
@interface MCDownloadManager : NSObject <MCDownloadControlDelegate>
/**
Defines the order prioritization of incoming download requests being inserted into the queue. `MCDownloadPrioritizationFIFO` by default.
*/
@property (nonatomic, assign) MCDownloadPrioritization downloadPrioritizaton;
/**
The shared default instance of `MCDownloadManager` initialized with default values.
*/
+ (instancetype)defaultInstance;
/**
Default initializer
@return An instance of `MCDownloadManager` initialized with default values.
*/
- (instancetype)init;
/**
Initializes the `MCDownloadManager` instance with the given session manager, download prioritization, maximum active download count.
@param sessionManager The session manager to use to download file.
@param downloadPrioritization The download prioritization of the download queue.
@param maximumActiveDownloads The maximum number of active downloads allowed at any given time. Recommend `4`.
@return The new `MCDownloadManager` instance.
*/
- (instancetype)initWithSession:(NSURLSession *)session
downloadPrioritization:(MCDownloadPrioritization)downloadPrioritization
maximumActiveDownloads:(NSInteger)maximumActiveDownloads;
///-----------------------------
/// @name Running Download Tasks
///-----------------------------
/**
Creates an `MCDownloadReceipt` with the specified request.
@param url The URL for the request.
@param downloadProgressBlock A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
@param destination A block object to be executed in order to determine the destination of the downloaded file. This block takes two arguments, the target path & the server response, and returns the desired file URL of the resulting download. The temporary file used during the download will be automatically deleted after being moved to the returned URL.
@warning If using a background `NSURLSessionConfiguration` on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use `-setDownloadTaskDidFinishDownloadingBlock:` to specify the URL for saving the downloaded file, rather than the destination block of this method.
*/
- (MCDownloadReceipt *)downloadFileWithURL:(NSString * _Nullable)url
progress:(nullable void (^)(NSProgress *downloadProgress, MCDownloadReceipt *receipt))downloadProgressBlock
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSURL *filePath))success
failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure;
- (MCDownloadReceipt * _Nullable)downloadReceiptForURL:(NSString *)url;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: MCDownloadManager/MCDownloadManager/MCDownloadManager.m
================================================
//
// MCDownloadManager.m
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "MCDownloadManager.h"
#import <CommonCrypto/CommonDigest.h>
NSString * const MCDownloadCacheFolderName = @"MCDownloadCache";
static NSString * cacheFolder() {
NSFileManager *filemgr = [NSFileManager defaultManager];
static NSString *cacheFolder;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!cacheFolder) {
NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
cacheFolder = [cacheDir stringByAppendingPathComponent:MCDownloadCacheFolderName];
}
NSError *error = nil;
if(![filemgr createDirectoryAtPath:cacheFolder withIntermediateDirectories:YES attributes:nil error:&error]) {
NSLog(@"Failed to create cache directory at %@", cacheFolder);
cacheFolder = nil;
}
});
return cacheFolder;
}
static NSString * LocalReceiptsPath() {
return [cacheFolder() stringByAppendingPathComponent:@"receipts.data"];
}
static unsigned long long fileSizeForPath(NSString *path) {
signed long long fileSize = 0;
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]) {
NSError *error = nil;
NSDictionary *fileDict = [fileManager attributesOfItemAtPath:path error:&error];
if (!error && fileDict) {
fileSize = [fileDict fileSize];
}
}
return fileSize;
}
static NSString * getMD5String(NSString *str) {
if (str == nil) return nil;
const char *cstring = str.UTF8String;
unsigned char bytes[CC_MD5_DIGEST_LENGTH];
CC_MD5(cstring, (CC_LONG)strlen(cstring), bytes);
NSMutableString *md5String = [NSMutableString string];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[md5String appendFormat:@"%02x", bytes[i]];
}
return md5String;
}
@interface MCDownloadReceipt()
@property (nonatomic, copy) NSString *url;
@property (nonatomic, copy) NSString *filePath;
@property (nonatomic, copy) NSString *filename;
@property (nonatomic, copy) NSString *truename;
@property (nonatomic, copy) NSString *speed; // KB/s
@property (nonatomic, assign) MCDownloadState state;
@property (assign, nonatomic) long long totalBytesWritten;
@property (assign, nonatomic) long long totalBytesExpectedToWrite;
@property (nonatomic, copy) NSProgress *progress;
@property (strong, nonatomic) NSOutputStream *stream;
@property (nonatomic, assign) NSUInteger totalRead;
@property (nonatomic, strong) NSDate *date;
@end
@implementation MCDownloadReceipt
- (NSOutputStream *)stream
{
if (_stream == nil) {
_stream = [NSOutputStream outputStreamToFileAtPath:self.filePath append:YES];
}
return _stream;
}
- (NSString *)filePath {
NSString *path = [cacheFolder() stringByAppendingPathComponent:self.filename];
if (![path isEqualToString:_filePath] ) {
if (_filePath && ![[NSFileManager defaultManager] fileExistsAtPath:_filePath]) {
NSString *dir = [_filePath stringByDeletingLastPathComponent];
[[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:nil];
}
_filePath = path;
}
return _filePath;
}
- (NSString *)filename {
if (_filename == nil) {
NSString *pathExtension = self.url.pathExtension;
if (pathExtension.length) {
_filename = [NSString stringWithFormat:@"%@.%@", getMD5String(self.url), pathExtension];
} else {
_filename = getMD5String(self.url);
}
}
return _filename;
}
- (NSString *)truename {
if (_truename == nil) {
_truename = self.url.lastPathComponent;
}
return _truename;
}
- (NSProgress *)progress {
if (_progress == nil) {
_progress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
}
@try {
_progress.totalUnitCount = self.totalBytesExpectedToWrite;
_progress.completedUnitCount = self.totalBytesWritten;
} @catch (NSException *exception) {
}
return _progress;
}
- (long long)totalBytesWritten {
return fileSizeForPath(self.filePath);
}
- (instancetype)initWithURL:(NSString *)url {
if (self = [self init]) {
self.url = url;
self.totalBytesExpectedToWrite = 1;
}
return self;
}
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.url forKey:NSStringFromSelector(@selector(url))];
[aCoder encodeObject:self.filePath forKey:NSStringFromSelector(@selector(filePath))];
[aCoder encodeObject:@(self.state) forKey:NSStringFromSelector(@selector(state))];
[aCoder encodeObject:self.filename forKey:NSStringFromSelector(@selector(filename))];
[aCoder encodeObject:@(self.totalBytesWritten) forKey:NSStringFromSelector(@selector(totalBytesWritten))];
[aCoder encodeObject:@(self.totalBytesExpectedToWrite) forKey:NSStringFromSelector(@selector(totalBytesExpectedToWrite))];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.url = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(url))];
self.filePath = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(filePath))];
self.state = [[aDecoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(state))] unsignedIntegerValue];
self.filename = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(filename))];
self.totalBytesWritten = [[aDecoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(totalBytesWritten))] unsignedIntegerValue];
self.totalBytesExpectedToWrite = [[aDecoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(totalBytesExpectedToWrite))] unsignedIntegerValue];
}
return self;
}
@end
#pragma mark -
#if OS_OBJECT_USE_OBJC
#define MCDispatchQueueSetterSementics strong
#else
#define MCDispatchQueueSetterSementics assign
#endif
@interface MCDownloadManager () <NSURLSessionDataDelegate>
@property (nonatomic, MCDispatchQueueSetterSementics) dispatch_queue_t synchronizationQueue;
@property (strong, nonatomic) NSURLSession *session;
@property (nonatomic, assign) NSInteger maximumActiveDownloads;
@property (nonatomic, assign) NSInteger activeRequestCount;
@property (nonatomic, strong) NSMutableArray *queuedTasks;
@property (nonatomic, strong) NSMutableDictionary *tasks;
@property (nonatomic, strong) NSMutableDictionary *allDownloadReceipts;
@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskId;
@end
@implementation MCDownloadManager
+ (NSURLSessionConfiguration *)defaultURLSessionConfiguration {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.HTTPShouldSetCookies = YES;
configuration.HTTPShouldUsePipelining = NO;
configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
configuration.allowsCellularAccess = YES;
configuration.timeoutIntervalForRequest = 60.0;
configuration.HTTPMaximumConnectionsPerHost = 10;
configuration.discretionary = YES;
return configuration;
}
- (instancetype)init {
NSURLSessionConfiguration *defaultConfiguration = [self.class defaultURLSessionConfiguration];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfiguration delegate:self delegateQueue:queue];
return [self initWithSession:session
downloadPrioritization:MCDownloadPrioritizationFIFO
maximumActiveDownloads:4 ];
}
- (instancetype)initWithSession:(NSURLSession *)session downloadPrioritization:(MCDownloadPrioritization)downloadPrioritization maximumActiveDownloads:(NSInteger)maximumActiveDownloads {
if (self = [super init]) {
self.session = session;
self.downloadPrioritizaton = downloadPrioritization;
self.maximumActiveDownloads = maximumActiveDownloads;
self.queuedTasks = [[NSMutableArray alloc] init];
self.tasks = [[NSMutableDictionary alloc] init];
self.activeRequestCount = 0;
NSString *name = [NSString stringWithFormat:@"com.mc.downloadManager.synchronizationqueue-%@", [[NSUUID UUID] UUIDString]];
self.synchronizationQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_SERIAL);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
+ (instancetype)defaultInstance {
static MCDownloadManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (NSMutableDictionary *)allDownloadReceipts {
if (_allDownloadReceipts == nil) {
NSDictionary *receipts = [NSKeyedUnarchiver unarchiveObjectWithFile:LocalReceiptsPath()];
_allDownloadReceipts = receipts != nil ? receipts.mutableCopy : [NSMutableDictionary dictionary];
}
return _allDownloadReceipts;
}
- (void)saveReceipts:(NSDictionary *)receipts {
[NSKeyedArchiver archiveRootObject:receipts toFile:LocalReceiptsPath()];
}
- (MCDownloadReceipt *)updateReceiptWithURL:(NSString *)url state:(MCDownloadState)state {
MCDownloadReceipt *receipt = [self downloadReceiptForURL:url];
receipt.state = state;
[self saveReceipts:self.allDownloadReceipts];
return receipt;
}
- (MCDownloadReceipt *)downloadFileWithURL:(NSString *)url
progress:(void (^)(NSProgress * _Nonnull,MCDownloadReceipt *receipt))downloadProgressBlock
destination:(NSURL * (^)(NSURL * _Nonnull, NSURLResponse * _Nonnull))destination
success:(nullable void (^)(NSURLRequest * _Nullable, NSHTTPURLResponse * _Nullable, NSURL * _Nonnull))success
failure:(nullable void (^)(NSURLRequest * _Nullable, NSHTTPURLResponse * _Nullable, NSError * _Nonnull))failure {
__block MCDownloadReceipt *receipt = [self downloadReceiptForURL:url];
dispatch_sync(self.synchronizationQueue, ^{
NSString *URLIdentifier = url;
if (URLIdentifier == nil) {
if (failure) {
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];
dispatch_async(dispatch_get_main_queue(), ^{
failure(nil, nil, error);
});
}
return;
}
receipt.successBlock = success;
receipt.failureBlock = failure;
receipt.progressBlock = downloadProgressBlock;
if (receipt.state == MCDownloadStateCompleted && receipt.totalBytesWritten == receipt.totalBytesExpectedToWrite) {
dispatch_async(dispatch_get_main_queue(), ^{
if (receipt.successBlock) {
receipt.successBlock(nil,nil,[NSURL URLWithString:receipt.url]);
}
});
return ;
}
if (receipt.state == MCDownloadStateDownloading && receipt.totalBytesWritten != receipt.totalBytesExpectedToWrite) {
dispatch_async(dispatch_get_main_queue(), ^{
if (receipt.progressBlock) {
receipt.progressBlock(receipt.progress,receipt);
}
});
return ;
}
NSURLSessionDataTask *task = self.tasks[receipt.url];
// 当请求暂停一段时间后。转态会变化。所有要判断下状态
if (!task || ((task.state != NSURLSessionTaskStateRunning) && (task.state != NSURLSessionTaskStateSuspended))) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:receipt.url]];
NSString *range = [NSString stringWithFormat:@"bytes=%zd-", receipt.totalBytesWritten];
[request setValue:range forHTTPHeaderField:@"Range"];
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request];
task.taskDescription = receipt.url;
self.tasks[receipt.url] = task;
[self.queuedTasks addObject:task];
}
[self resumeWithDownloadReceipt:receipt];
});
return receipt;
}
#pragma mark - -----------------------
- (NSURLSessionDataTask*)safelyRemoveTaskWithURLIdentifier:(NSString *)URLIdentifier {
__block NSURLSessionDataTask *task = nil;
dispatch_sync(self.synchronizationQueue, ^{
task = [self removeTaskWithURLIdentifier:URLIdentifier];
});
return task;
}
//This method should only be called from safely within the synchronizationQueue
- (NSURLSessionDataTask *)removeTaskWithURLIdentifier:(NSString *)URLIdentifier {
NSURLSessionDataTask *task = self.tasks[URLIdentifier];
[self.tasks removeObjectForKey:URLIdentifier];
return task;
}
- (void)safelyDecrementActiveTaskCount {
dispatch_sync(self.synchronizationQueue, ^{
if (self.activeRequestCount > 0) {
self.activeRequestCount -= 1;
}
});
}
- (void)safelyStartNextTaskIfNecessary {
dispatch_sync(self.synchronizationQueue, ^{
if ([self isActiveRequestCountBelowMaximumLimit]) {
while (self.queuedTasks.count > 0) {
NSURLSessionDataTask *task = [self dequeueTask];
MCDownloadReceipt *receipt = [self downloadReceiptForURL:task.taskDescription];
if (task.state == NSURLSessionTaskStateSuspended && receipt.state == MCDownloadStateWillResume) {
[self startTask:task];
break;
}
}
}
});
}
- (void)startTask:(NSURLSessionDataTask *)task {
[task resume];
++self.activeRequestCount;
[self updateReceiptWithURL:task.taskDescription state:MCDownloadStateDownloading];
}
- (void)enqueueTask:(NSURLSessionDataTask *)task {
switch (self.downloadPrioritizaton) {
case MCDownloadPrioritizationFIFO: //
[self.queuedTasks addObject:task];
break;
case MCDownloadPrioritizationLIFO: //
[self.queuedTasks insertObject:task atIndex:0];
break;
}
}
- (NSURLSessionDataTask *)dequeueTask {
NSURLSessionDataTask *task = nil;
task = [self.queuedTasks firstObject];
[self.queuedTasks removeObject:task];
return task;
}
- (BOOL)isActiveRequestCountBelowMaximumLimit {
return self.activeRequestCount < self.maximumActiveDownloads;
}
#pragma mark -
- (MCDownloadReceipt *)downloadReceiptForURL:(NSString *)url {
if (url == nil) return nil;
MCDownloadReceipt *receipt = self.allDownloadReceipts[url];
if (receipt) return receipt;
receipt = [[MCDownloadReceipt alloc] initWithURL:url];
receipt.state = MCDownloadStateNone;
receipt.totalBytesExpectedToWrite = 1;
dispatch_sync(self.synchronizationQueue, ^{
[self.allDownloadReceipts setObject:receipt forKey:url];
[self saveReceipts:self.allDownloadReceipts];
});
return receipt;
}
#pragma mark - NSNotification
- (void)applicationWillTerminate:(NSNotification *)not {
[self suspendAll];
}
- (void)applicationDidReceiveMemoryWarning:(NSNotification *)not {
[self suspendAll];
}
- (void)applicationWillResignActive:(NSNotification *)not {
/// 捕获到失去激活状态后
Class UIApplicationClass = NSClassFromString(@"UIApplication");
BOOL hasApplication = UIApplicationClass && [UIApplicationClass respondsToSelector:@selector(sharedApplication)];
if (hasApplication ) {
__weak __typeof__ (self) wself = self;
UIApplication * app = [UIApplicationClass performSelector:@selector(sharedApplication)];
self.backgroundTaskId = [app beginBackgroundTaskWithExpirationHandler:^{
__strong __typeof (wself) sself = wself;
if (sself) {
[sself suspendAll];
[app endBackgroundTask:sself.backgroundTaskId];
sself.backgroundTaskId = UIBackgroundTaskInvalid;
}
}];
}
}
- (void)applicationDidBecomeActive:(NSNotification *)not {
Class UIApplicationClass = NSClassFromString(@"UIApplication");
if(!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) {
return;
}
if (self.backgroundTaskId != UIBackgroundTaskInvalid) {
UIApplication * app = [UIApplication performSelector:@selector(sharedApplication)];
[app endBackgroundTask:self.backgroundTaskId];
self.backgroundTaskId = UIBackgroundTaskInvalid;
}
}
#pragma mark - MCDownloadControlDelegate
- (void)resumeWithURL:(NSString *)url {
if (url == nil) return;
MCDownloadReceipt *receipt = [self downloadReceiptForURL:url];
[self resumeWithDownloadReceipt:receipt];
}
- (void)resumeWithDownloadReceipt:(MCDownloadReceipt *)receipt {
if ([self isActiveRequestCountBelowMaximumLimit]) {
NSURLSessionDataTask *task = self.tasks[receipt.url];
// 当请求暂停一段时间后。转态会变化。所有要判断下状态
if (!task || ((task.state != NSURLSessionTaskStateRunning) && (task.state != NSURLSessionTaskStateSuspended))) {
[self downloadFileWithURL:receipt.url progress:receipt.progressBlock destination:nil success:receipt.successBlock failure:receipt.failureBlock];
}else {
[self startTask:self.tasks[receipt.url]];
receipt.date = [NSDate date];
}
}else {
receipt.state = MCDownloadStateWillResume;
[self saveReceipts:self.allDownloadReceipts];
[self enqueueTask:self.tasks[receipt.url]];
}
}
- (void)suspendAll {
for (NSURLSessionDataTask *task in self.queuedTasks) {
MCDownloadReceipt *receipt = [self downloadReceiptForURL:task.taskDescription];
receipt.state = MCDownloadStateFailed;
[task suspend];
[self safelyDecrementActiveTaskCount];
}
[self saveReceipts:self.allDownloadReceipts];
}
-(void)suspendWithURL:(NSString *)url {
if (url == nil) return;
MCDownloadReceipt *receipt = [self downloadReceiptForURL:url];
[self suspendWithDownloadReceipt:receipt];
}
- (void)suspendWithDownloadReceipt:(MCDownloadReceipt *)receipt {
[self updateReceiptWithURL:receipt.url state:MCDownloadStateSuspened];
NSURLSessionDataTask *task = self.tasks[receipt.url];
if (task) {
[task suspend];
[self safelyDecrementActiveTaskCount];
[self safelyStartNextTaskIfNecessary];
}
}
- (void)removeWithURL:(NSString *)url {
if (url == nil) return;
MCDownloadReceipt *receipt = [self downloadReceiptForURL:url];
[self removeWithDownloadReceipt:receipt];
}
- (void)removeWithDownloadReceipt:(MCDownloadReceipt *)receipt {
NSURLSessionDataTask *task = self.tasks[receipt.url];
if (task) {
[task cancel];
}
[self.queuedTasks removeObject:task];
[self safelyRemoveTaskWithURLIdentifier:receipt.url];
dispatch_sync(self.synchronizationQueue, ^{
[self.allDownloadReceipts removeObjectForKey:receipt.url];
[self saveReceipts:self.allDownloadReceipts];
});
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:receipt.filePath error:nil];
}
#pragma mark - <NSURLSessionDataDelegate>
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
MCDownloadReceipt *receipt = [self downloadReceiptForURL:dataTask.taskDescription];
receipt.totalBytesExpectedToWrite = receipt.totalBytesWritten + dataTask.countOfBytesExpectedToReceive;
receipt.state = MCDownloadStateDownloading;
[self saveReceipts:self.allDownloadReceipts];
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
dispatch_sync(self.synchronizationQueue, ^{
__block NSError *error = nil;
MCDownloadReceipt *receipt = [self downloadReceiptForURL:dataTask.taskDescription];
// Speed
receipt.totalRead += data.length;
NSDate *currentDate = [NSDate date];
if ([currentDate timeIntervalSinceDate:receipt.date] >= 1) {
double time = [currentDate timeIntervalSinceDate:receipt.date];
long long speed = receipt.totalRead/time;
receipt.speed = [self formatByteCount:speed];
receipt.totalRead = 0.0;
receipt.date = currentDate;
}
// Write Data
NSInputStream *inputStream = [[NSInputStream alloc] initWithData:data];
NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:[NSURL fileURLWithPath:receipt.filePath] append:YES];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
while ([inputStream hasBytesAvailable] && [outputStream hasSpaceAvailable]) {
uint8_t buffer[1024];
NSInteger bytesRead = [inputStream read:buffer maxLength:1024];
if (inputStream.streamError || bytesRead < 0) {
error = inputStream.streamError;
break;
}
NSInteger bytesWritten = [outputStream write:buffer maxLength:(NSUInteger)bytesRead];
if (outputStream.streamError || bytesWritten < 0) {
error = outputStream.streamError;
break;
}
if (bytesRead == 0 && bytesWritten == 0) {
break;
}
}
[outputStream close];
[inputStream close];
receipt.progress.totalUnitCount = receipt.totalBytesExpectedToWrite;
receipt.progress.completedUnitCount = receipt.totalBytesWritten;
dispatch_async(dispatch_get_main_queue(), ^{
if (receipt.progressBlock) {
receipt.progressBlock(receipt.progress,receipt);
}
});
});
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
MCDownloadReceipt *receipt = [self downloadReceiptForURL:task.taskDescription];
if (error) {
receipt.state = MCDownloadStateFailed;
dispatch_async(dispatch_get_main_queue(), ^{
if (receipt.failureBlock) {
receipt.failureBlock(task.originalRequest,(NSHTTPURLResponse *)task.response,error);
}
});
}else {
[receipt.stream close];
receipt.stream = nil;
receipt.state = MCDownloadStateCompleted;
dispatch_async(dispatch_get_main_queue(), ^{
if (receipt.successBlock) {
receipt.successBlock(task.originalRequest,(NSHTTPURLResponse *)task.response,task.originalRequest.URL);
}
});
}
[self saveReceipts:self.allDownloadReceipts];
[self safelyDecrementActiveTaskCount];
[self safelyStartNextTaskIfNecessary];
}
- (NSString*)formatByteCount:(long long)size
{
return [NSByteCountFormatter stringFromByteCount:size countStyle:NSByteCountFormatterCountStyleFile];
}
@end
================================================
FILE: MCDownloadManager/MCDownloadManager.entitlements
================================================
<?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/>
</plist>
================================================
FILE: MCDownloadManager/Networking/MCURLRequest.h
================================================
//
// MCURLRequest.h
// MCDownloadManager
//
// Created by 马超 on 16/9/23.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MCURLSessionConfiguration.h"
#import "MCURLResponse.h"
NS_ASSUME_NONNULL_BEGIN
@class MCURLRequest;
@protocol MCURLRequestDelegate <NSObject>
@optional
- (void)URLRequest:(MCURLRequest *)request didCompleteWithResponse:(MCURLResponse *)response;
@end
typedef NS_ENUM(NSUInteger, MCHTTPMethod) {
MCHTTPMethodGET,
MCHTTPMethodPOST,
MCHTTPMethodPUT,
MCHTTPMethodHEAD,
MCHTTPMethodPATCH,
MCHTTPMethodDELETE
};
//这个类是对请求的封装,在实际发出请求之前,按照设计,都在这个类处理
/**
* 设计的过程是 写请求(包括配置) -> 发请求 -> 得到相应(数据)
*/
@interface MCURLRequest : NSObject
///---------------------------------------
/// Initialization
///---------------------------------------
/*
* Customization of MCURLRequest occurs during creation of a new URLRequest.
* If you only need to use the convenience routines with custom
* configuration options it is not necessary to specify a delegate.
* If you do specify a delegate, the delegate will be retained until after
* the delegate has been sent the URLSession:didBecomeInvalidWithError: message.
这里需要调用afn的didBecomeInvalidWithError 然后释放delegate
*/
+ (instancetype)URLRequestWithConfiguration:(MCURLSessionConfiguration *)configuration;
+ (instancetype)URLRequestWithConfiguration:(MCURLSessionConfiguration *)configuration delegate:(nullable id <MCURLRequestDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
@property (nonatomic, readonly, retain) NSOperationQueue *delegateQueue;
@property (nonatomic, nullable, retain) id <MCURLRequestDelegate> delegate;
@property (nonatomic, copy) MCURLSessionConfiguration *configuration;
///---------------------------------------
/// Parameters
///---------------------------------------
// 参数,有字典,url,, nsdate ,流, 反正式afn提供的。
@property (nonatomic, copy, nullable) NSString *url;
@property (nonatomic, copy, nullable) NSDictionary *parameterDict;
@property (nonatomic, assign) MCHTTPMethod HTTPMethod;
@property (nonatomic, assign, getter=isCacheResponse) BOOL cacheResponse;
// 跟上传相关
@property (nonatomic, strong, nullable) NSData *data;
@property (nonatomic, copy, nullable) NSString *fileURL;
@property (nonatomic, strong, nullable) NSInputStream *inputStream;
@property (nonatomic, copy, nullable) NSString *fileName;
@property (nonatomic, copy, nullable) NSString *name;
@property (nonatomic, copy, nullable) NSString *mimeType;
@property (nonatomic, assign) int64_t length;
///---------------------------------------
/// Load Datas
///---------------------------------------
- (void)fetchDataWithMethod:(MCHTTPMethod)method completionHandler:(void (^)(MCURLResponse *response))handler;
- (void)fetchDataWithMethod:(MCHTTPMethod)method progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress completionHandler:(void (^)(MCURLResponse *response))handler;
///---------------------------------------
/// Upload Datas
///---------------------------------------
- (void)uploadDataWithCompletionHandler:(void (^)(MCURLResponse *response))handler;
- (void)uploadDataWithProgress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress completionHandler:(void (^)(MCURLResponse *response))handler;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: MCDownloadManager/Networking/MCURLRequest.m
================================================
//
// MCURLRequest.m
// MCDownloadManager
//
// Created by 马超 on 16/9/23.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "MCURLRequest.h"
@interface MCURLRequest ()
@property (nonatomic, retain) NSOperationQueue *delegateQueue;
@end
@implementation MCURLRequest
#pragma mark - Initialization
- (instancetype)init {
self = [super init];
if (self == nil) {
return nil;
}
self.HTTPMethod = MCHTTPMethodGET;
self.cacheResponse = NO;
MCURLSessionConfiguration *configuration = [MCURLSessionConfiguration defaultURLSessionConfiguration];
self.configuration = configuration;
self.delegateQueue = [[NSOperationQueue alloc] init];
return self;
}
+ (instancetype)URLRequestWithConfiguration:(MCURLSessionConfiguration *)configuration {
MCURLRequest *request = [self init];
if (configuration) {
request.configuration = configuration;
}
return request;
}
+(instancetype)URLRequestWithConfiguration:(MCURLSessionConfiguration *)configuration delegate:(id<MCURLRequestDelegate>)delegate delegateQueue:(NSOperationQueue *)queue {
MCURLRequest *request = [self init];
if (configuration) {
request.configuration = configuration;
}
if (queue) {
request.delegateQueue = queue;
}
return request;
}
#pragma mark - Public Methods
- (void)fetchDataWithMethod:(MCHTTPMethod)method completionHandler:(void (^)(MCURLResponse * _Nonnull))handler {
}
- (void)fetchDataWithMethod:(MCHTTPMethod)method progress:(void (^)(NSProgress * _Nonnull))downloadProgress completionHandler:(void (^)(MCURLResponse * _Nonnull))handler {
}
- (void)uploadDataWithCompletionHandler:(void (^)(MCURLResponse * _Nonnull))handler {
}
- (void)uploadDataWithProgress:(void (^)(NSProgress * _Nonnull))uploadProgress completionHandler:(void (^)(MCURLResponse * _Nonnull))handler {
}
@end
================================================
FILE: MCDownloadManager/Networking/MCURLRequestCenter.h
================================================
//
// MCURLRequestCenter.h
// MCDownloadManager
//
// Created by 马超 on 16/9/30.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MCURLRequestCenter : NSObject
@end
================================================
FILE: MCDownloadManager/Networking/MCURLRequestCenter.m
================================================
//
// MCURLRequestCenter.m
// MCDownloadManager
//
// Created by 马超 on 16/9/30.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "MCURLRequestCenter.h"
@implementation MCURLRequestCenter
@end
================================================
FILE: MCDownloadManager/Networking/MCURLResponse.h
================================================
//
// MCURLResponse.h
// MCDownloadManager
//
// Created by 马超 on 16/9/21.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, MCURLResponseStatus) {
MCURLResponseStatusNone,
MCURLResponseStatusSuccess, // 成功
MCURLResponseStatusDataInvalid, // 请求成功,但服务器返回的数据不正确
MCURLResponseStatusParameterInvalid, // 参数错误,不会发请求
MCURLResponseStatusTimeout, // 请求超时
MCURLResponseStatusNetworkNotReachable // 网络不可达,这个会在发请求之前检测网络是不是可达的
};
// 需要一个把结果加压成何种数据的说明
@interface MCURLResponse : NSObject
// 响应的所有封装的数据,这里能拿到我们需要的最原始的数据
// 这里如果出错,最好能告诉用户出错的原因。
@property (nonatomic, assign) MCURLResponseStatus status;
@property (nonatomic, copy, readonly, nullable) id responseObject;
@property (nonatomic, copy, readonly) NSDictionary *requestParameter; // 这里封装的应该是请求封装,请求封装中能够拿到必要的配置信息,
@property (nonatomic, assign, readonly, getter=isCache) BOOL cache;
@property (nonatomic, copy, nullable) NSString *URLIdentifier;
@property (nonatomic, strong, readonly, nullable) NSURLSessionDataTask *task;
@property (nonatomic, strong, readonly, nullable) NSError *error;
//对于响应来说,初始化方法,有多少个完全取决于第三方网络框架提供的获取数据成功或失败后返回的数据
- (instancetype)init;
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask * _Nullable)task responseObject:(id _Nullable)responseObject;
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask * _Nullable)task error:(NSError * _Nullable)error;
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask * _Nullable)task responseObject:(id _Nullable)responseObject error:(NSError * _Nullable)error;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: MCDownloadManager/Networking/MCURLResponse.m
================================================
//
// MCURLResponse.m
// MCDownloadManager
//
// Created by 马超 on 16/9/21.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "MCURLResponse.h"
@interface MCURLResponse()
@property (nonatomic, copy, readwrite, nullable) id responseObject;
@property (nonatomic, copy, readwrite) NSDictionary *requestParameter; // 这里封装的应该是请求封装,请求封装中能够拿到必要的配置信息,
@property (nonatomic, assign, readwrite, getter=isCache) BOOL cache;
@property (nonatomic, strong, readwrite, nullable) NSURLSessionDataTask *task;
@property (nonatomic, strong, readwrite, nullable) NSError *error;
@end
@implementation MCURLResponse
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
self.status = MCURLResponseStatusNone;
return self;
}
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask *)task responseObject:(id)responseObject {
return [self initWithURLSessionDataTask:task responseObject:responseObject error:nil];
}
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask *)task error:(NSError *)error {
return [self initWithURLSessionDataTask:task responseObject:nil error:error];
}
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask *)task responseObject:(id)responseObject error:(NSError *)error {
self = [super init];
if (!self) {
return nil;
}
self.status = MCURLResponseStatusNone;
if (error) {
self.error = error;
if (error.code == -1001) {
self.status = MCURLResponseStatusTimeout;
}
}
if (!responseObject) {
self.status = MCURLResponseStatusDataInvalid;
}
if (task) {
self.task = task;
self.URLIdentifier = task.originalRequest.URL.absoluteString;
}
self.responseObject = responseObject;
return self;
}
@end
================================================
FILE: MCDownloadManager/Networking/MCURLSessionConfiguration.h
================================================
//
// MCURLSessionConfiguration.h
// MCDownloadManager
//
// Created by 马超 on 16/9/23.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MCURLSessionConfiguration : NSObject
+ (MCURLSessionConfiguration *)defaultURLSessionConfiguration;
+ (MCURLSessionConfiguration *)ephemeralURLSessionConfiguration;
+ (MCURLSessionConfiguration *)backgroundURLSessionConfigurationWithIdentifier:(NSString *)identifier;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: MCDownloadManager/Networking/MCURLSessionConfiguration.m
================================================
//
// MCURLSessionConfiguration.m
// MCDownloadManager
//
// Created by 马超 on 16/9/23.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "MCURLSessionConfiguration.h"
@implementation MCURLSessionConfiguration
@end
================================================
FILE: MCDownloadManager/Networking/MCWiFiManager.h
================================================
//
// MCWiFiManager.h
// MCDownloadManager
//
// Created by 马超 on 16/9/14.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MCWiFi : NSObject
@property (nonatomic, copy, readonly, nullable)NSString *wifiName;
@property (nonatomic, copy, readonly, nullable)NSString *wifiBSSID;
- (instancetype)initWithName:(NSString *)name BSSID:(NSString *)bssid;
@end
@interface MCWiFiManager : NSObject
/**
The shared default instance of `MCWiFiManager` initialized with default values.
*/
+ (instancetype)defaultInstance;
/**
Default initializer
@return An instance of `MCWiFiManager` initialized with default values.
*/
- (instancetype)init;
- (void)scanNetworksWithCompletionHandler:(void(^_Nullable)(NSArray <MCWiFi *>* _Nullable networks, MCWiFi *_Nullable currentWiFi, NSError *_Nullable error))handler;
- (NSString *)getGatewayIpForCurrentWiFi;
/**
* Get the local info for currentWifi except for GatewayIp
*
* @return NSDictionary
* {
broadcast = "192.168.8.233";
interface = en0;
localIp = "192.168.5.140";
netmask = "255.255.255.0";
}
*/
- (NSDictionary *)getLocalInfoForCurrentWiFi;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: MCDownloadManager/Networking/MCWiFiManager.m
================================================
//
// MCWiFiManager.m
// MCDownloadManager
//
// Created by 马超 on 16/9/14.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "MCWiFiManager.h"
#import <NetworkExtension/NetworkExtension.h>
#import <SystemConfiguration/CaptiveNetwork.h>
#import <arpa/inet.h>
#import <netinet/in.h>
#import <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <netinet/in.h>
#include <sys/param.h>
/*
* Copyright (c) 2000-2008 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)route.h 8.3 (Berkeley) 4/19/94
* $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
*/
#ifndef TARGET_IPHONE_SIMULATOR
#ifndef _NET_ROUTE_H_
#define _NET_ROUTE_H_
#include <sys/appleapiopts.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
/*
* Kernel resident routing tables.
*
* The routing tables are initialized when interface addresses
* are set by making entries for all directly connected interfaces.
*/
/*
* A route consists of a destination address and a reference
* to a routing entry. These are often held by protocols
* in their control blocks, e.g. inpcb.
*/
struct route;
/*
* These numbers are used by reliable protocols for determining
* retransmission behavior and are included in the routing structure.
*/
struct rt_metrics {
u_int32_t rmx_locks; /* Kernel must leave these values alone */
u_int32_t rmx_mtu; /* MTU for this path */
u_int32_t rmx_hopcount; /* max hops expected */
int32_t rmx_expire; /* lifetime for route, e.g. redirect */
u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */
u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */
u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */
u_int32_t rmx_rtt; /* estimated round trip time */
u_int32_t rmx_rttvar; /* estimated rtt variance */
u_int32_t rmx_pksent; /* packets sent using this route */
u_int32_t rmx_filler[4]; /* will be used for T/TCP later */
};
/*
* rmx_rtt and rmx_rttvar are stored as microseconds;
*/
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
/*
* We distinguish between routes to hosts and routes to networks,
* preferring the former if available. For each route we infer
* the interface to use from the gateway address supplied when
* the route was entered. Routes that forward packets through
* gateways are marked so that the output routines know to address the
* gateway rather than the ultimate destination.
*/
#define RTF_UP 0x1 /* route usable */
#define RTF_GATEWAY 0x2 /* destination is a gateway */
#define RTF_HOST 0x4 /* host entry (net otherwise) */
#define RTF_REJECT 0x8 /* host or net unreachable */
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
#define RTF_DONE 0x40 /* message confirmed */
#define RTF_DELCLONE 0x80 /* delete cloned route */
#define RTF_CLONING 0x100 /* generate new routes on use */
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
#define RTF_STATIC 0x800 /* manually added */
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
#define RTF_WASCLONED 0x20000 /* route generated through cloning */
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
/* 0x80000 unused */
#define RTF_PINNED 0x100000 /* future use */
#define RTF_LOCAL 0x200000 /* route represents a local address */
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */
#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */
/* 0x4000000 and up unassigned */
/*
* Routing statistics.
*/
struct rtstat {
short rts_badredirect; /* bogus redirect calls */
short rts_dynamic; /* routes created by redirects */
short rts_newgateway; /* routes modified by redirects */
short rts_unreach; /* lookups which failed */
short rts_wildcard; /* lookups satisfied by a wildcard */
};
/*
* Structures for routing messages.
*/
struct rt_msghdr {
u_short rtm_msglen; /* to skip over non-understood messages */
u_char rtm_version; /* future binary compatibility */
u_char rtm_type; /* message type */
u_short rtm_index; /* index for associated ifp */
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
pid_t rtm_pid; /* identify sender */
int rtm_seq; /* for sender to identify action */
int rtm_errno; /* why failed */
int rtm_use; /* from rtentry */
u_int32_t rtm_inits; /* which metrics we are initializing */
struct rt_metrics rtm_rmx; /* metrics themselves */
};
struct rt_msghdr2 {
u_short rtm_msglen; /* to skip over non-understood messages */
u_char rtm_version; /* future binary compatibility */
u_char rtm_type; /* message type */
u_short rtm_index; /* index for associated ifp */
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
int32_t rtm_refcnt; /* reference count */
int rtm_parentflags; /* flags of the parent route */
int rtm_reserved; /* reserved field set to 0 */
int rtm_use; /* from rtentry */
u_int32_t rtm_inits; /* which metrics we are initializing */
struct rt_metrics rtm_rmx; /* metrics themselves */
};
#define RTM_VERSION 5 /* Up the ante and ignore older versions */
/*
* Message types.
*/
#define RTM_ADD 0x1 /* Add Route */
#define RTM_DELETE 0x2 /* Delete Route */
#define RTM_CHANGE 0x3 /* Change Metrics or flags */
#define RTM_GET 0x4 /* Report Metrics */
#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */
#define RTM_REDIRECT 0x6 /* Told to use different route */
#define RTM_MISS 0x7 /* Lookup failed on this address */
#define RTM_LOCK 0x8 /* fix specified metrics */
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
#define RTM_NEWADDR 0xc /* address being added to iface */
#define RTM_DELADDR 0xd /* address being removed from iface */
#define RTM_IFINFO 0xe /* iface going up/down etc. */
#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
#define RTM_IFINFO2 0x12 /* */
#define RTM_NEWMADDR2 0x13 /* */
#define RTM_GET2 0x14 /* */
/*
* Bitmask values for rtm_inits and rmx_locks.
*/
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
#define RTV_EXPIRE 0x4 /* init or lock _expire */
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
#define RTV_RTT 0x40 /* init or lock _rtt */
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
/*
* Bitmask values for rtm_addrs.
*/
#define RTA_DST 0x1 /* destination sockaddr present */
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
#define RTA_IFP 0x10 /* interface name sockaddr present */
#define RTA_IFA 0x20 /* interface addr sockaddr present */
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
/*
* Index offsets for sockaddr array for alternate internal encoding.
*/
#define RTAX_DST 0 /* destination sockaddr present */
#define RTAX_GATEWAY 1 /* gateway sockaddr present */
#define RTAX_NETMASK 2 /* netmask sockaddr present */
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
#define RTAX_IFP 4 /* interface name sockaddr present */
#define RTAX_IFA 5 /* interface addr sockaddr present */
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
#define RTAX_MAX 8 /* size of array to allocate */
struct rt_addrinfo {
int rti_addrs;
struct sockaddr *rti_info[RTAX_MAX];
};
struct route_cb {
int ip_count;
int ip6_count;
int ipx_count;
int ns_count;
int iso_count;
int any_count;
};
#endif
#define CTL_NET 4 /* network, see socket.h */
#if defined(BSD) || defined(__APPLE__)
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
char * getdefaultgateway(in_addr_t * addr)
{
#if 0
/* net.route.0.inet.dump.0.0 ? */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
NET_RT_DUMP, 0, 0/*tableid*/};
#endif
/* net.route.0.inet.flags.gateway */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
NET_RT_FLAGS, RTF_GATEWAY};
size_t l;
char * buf, * p;
struct rt_msghdr * rt;
struct sockaddr * sa;
struct sockaddr * sa_tab[RTAX_MAX];
int i;
int r = -1;
static char tmp[20];
#if TARGET_OS_IPHONE
if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
return tmp;
}
if(l>0) {
buf = malloc(l);
if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
return tmp;
}
for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr *)(rt + 1);
for(i=0; i<RTAX_MAX; i++) {
if(rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
} else {
sa_tab[i] = NULL;
}
}
if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
&& sa_tab[RTAX_DST]->sa_family == AF_INET
&& sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
unsigned char octet[4] = {0,0,0,0};
for (int i=0; i<4; i++){
octet[i] = ( ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr >> (i*8) ) & 0xFF;
}
if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
r = 0;
sprintf(tmp,"%d.%d.%d.%d",octet[0],octet[1],octet[2],octet[3]);
printf("gateway : %s\n",tmp);
printf("gateway address--%d.%d.%d.%d\n",octet[0],octet[1],octet[2],octet[3]);
}
}
}
free(buf);
}
#endif
return tmp;
}
#endif
#endif
@implementation MCWiFi
- (instancetype)initWithName:(NSString *)name BSSID:(NSString *)bssid {
if (self = [super init]) {
_wifiName = name;
_wifiBSSID = bssid;
}
return self;
}
@end
#pragma mark -
@implementation MCWiFiManager
- (instancetype)init {
if (self = [super init]) {
}
return self;
}
+ (instancetype)defaultInstance {
static MCWiFiManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#pragma mark -
- (void)scanNetworksWithCompletionHandler:(void (^)(NSArray<MCWiFi *> * _Nullable, MCWiFi * _Nullable, NSError * _Nullable))handler {
NSString *wifiName = @"Not Found";
NSString *wifiBSSID = @"Not Found";
CFArrayRef myArray = CNCopySupportedInterfaces();
if (myArray != nil) {
for (int i = 0; i < CFArrayGetCount(myArray); i++) {
CFStringRef strRef = CFArrayGetValueAtIndex(myArray, i);
CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(strRef);
if (myDict != nil) {
NSDictionary *dict = (NSDictionary*)CFBridgingRelease(myDict);
wifiName = [dict valueForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
wifiBSSID = [dict valueForKey:(__bridge NSString *)kCNNetworkInfoKeyBSSID];
break;
}
}
}
if (myArray) {
CFRelease(myArray);
}
MCWiFi *wifi = [[MCWiFi alloc] initWithName:wifiName BSSID:wifiBSSID];
if (handler) {
handler(@[wifi], wifi, nil);
}
}
- (NSString *)getGatewayIpForCurrentWiFi {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
//*/
while(temp_addr != NULL) {
/*/
int i=255;
while((i--)>0)
//*/
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"])
{
// Get NSString from C String //ifa_addr
//ifa->ifa_dstaddr is the broadcast address, which explains the "255's"
// address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
#ifndef TARGET_IPHONE_SIMULATOR
in_addr_t i = inet_addr([address cStringUsingEncoding:NSUTF8StringEncoding]);
in_addr_t* x = &i;
unsigned char *s = (unsigned char *)getdefaultgateway(x) ;
NSString *ip=[NSString stringWithFormat:@"%d.%d.%d.%d",s[0],s[1],s[2],s[3]];
return ip;
#endif
return nil;
}
- (NSDictionary *)getLocalInfoForCurrentWiFi {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
//*/
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
NSString *broadcast = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
if (broadcast) {
[dict setObject:broadcast forKey:@"broadcast"];
}
NSLog(@"broadcast address--%@",broadcast);
NSString *localIp = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
if (localIp) {
[dict setObject:localIp forKey:@"localIp"];
}
NSString *netmask = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)];
if (netmask) {
[dict setObject:netmask forKey:@"netmask"];
}
NSString *interface = [NSString stringWithUTF8String:temp_addr->ifa_name];
if (interface) {
[dict setObject:interface forKey:@"interface"];
}
return dict;
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return dict;
}
@end
================================================
FILE: MCDownloadManager/QKYDelayButton.h
================================================
//
// QKYDelayButton.h
// qikeyun
//
// Created by 马超 on 16/6/4.
// Copyright © 2016年 Jerome. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface QKYDelayButton : UIButton
@property (nonatomic,assign)NSTimeInterval clickDurationTime;
@end
================================================
FILE: MCDownloadManager/QKYDelayButton.m
================================================
//
// QKYDelayButton.m
// qikeyun
//
// Created by 马超 on 16/6/4.
// Copyright © 2016年 Jerome. All rights reserved.
//
#import "QKYDelayButton.h"
static NSTimeInterval defaultDuration = 1.0f;
static BOOL _isIgnoreEvent = NO;
static void resetState() {
_isIgnoreEvent = NO;
}
@implementation QKYDelayButton
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if ([self isKindOfClass:[UIButton class]]) {
self.clickDurationTime = self.clickDurationTime == 0 ? defaultDuration : self.clickDurationTime;
if (_isIgnoreEvent) {
return;
}
else if (self.clickDurationTime > 0) {
_isIgnoreEvent = YES;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.clickDurationTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
resetState();
});
[super sendAction:action to:target forEvent:event];
}
}
else {
[super sendAction:action to:target forEvent:event];
}
}
@end
================================================
FILE: MCDownloadManager/TableViewCell.h
================================================
//
// TableViewCell.h
// MCDownloadManager
//
// Created by 马超 on 16/9/6.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "QKYDelayButton.h"
@class TableViewCell;
@protocol TableViewCellDelegate <NSObject>
- (void)cell:(TableViewCell *)cell didClickedBtn:(UIButton *)btn;
@end
@interface TableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet QKYDelayButton *button;
@property (weak, nonatomic) IBOutlet UILabel *bytesLable;
@property (weak, nonatomic) IBOutlet UILabel *speedLable;
@property (nonatomic, weak) id <TableViewCellDelegate> delegate;
@property (nonatomic,copy)NSString *url;
@end
================================================
FILE: MCDownloadManager/TableViewCell.m
================================================
//
// TableViewCell.m
// MCDownloadManager
//
// Created by 马超 on 16/9/6.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "TableViewCell.h"
#import "MCDownloadManager.h"
@implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
self.button.clipsToBounds = YES;
self.button.layer.cornerRadius = 10;
self.button.layer.borderWidth = 1;
self.button.layer.borderColor = [UIColor orangeColor].CGColor;
[self.button setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
self.button.clickDurationTime = 1.0;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)setUrl:(NSString *)url {
_url = url;
MCDownloadReceipt *receipt = [[MCDownloadManager defaultInstance] downloadReceiptForURL:url];
self.nameLabel.text = receipt.truename;
self.speedLable.text = nil;
self.bytesLable.text = nil;
self.progressView.progress = 0;
self.progressView.progress = receipt.progress.fractionCompleted;
if (receipt.state == MCDownloadStateDownloading) {
[self.button setTitle:@"停止" forState:UIControlStateNormal];
}else if (receipt.state == MCDownloadStateCompleted) {
[self.button setTitle:@"播放" forState:UIControlStateNormal];
}else {
[self.button setTitle:@"下载" forState:UIControlStateNormal];
}
receipt.progressBlock = ^(NSProgress * _Nonnull downloadProgress,MCDownloadReceipt *receipt) {
if ([receipt.url isEqualToString:self.url]) {
self.progressView.progress = downloadProgress.fractionCompleted ;
self.bytesLable.text = [NSString stringWithFormat:@"%0.2fm/%0.2fm", downloadProgress.completedUnitCount/1024.0/1024, downloadProgress.totalUnitCount/1024.0/1024];
self.speedLable.text = [NSString stringWithFormat:@"%@/s", receipt.speed];
}
};
receipt.successBlock = ^(NSURLRequest * _Nullablerequest, NSHTTPURLResponse * _Nullableresponse, NSURL * _NonnullfilePath) {
[self.button setTitle:@"播放" forState:UIControlStateNormal];
};
receipt.failureBlock = ^(NSURLRequest * _Nullable request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
[self.button setTitle:@"下载" forState:UIControlStateNormal];
};
}
- (IBAction)buttonAction:(UIButton *)sender {
MCDownloadReceipt *receipt = [[MCDownloadManager defaultInstance] downloadReceiptForURL:self.url];
if (receipt.state == MCDownloadStateDownloading) {
[self.button setTitle:@"下载" forState:UIControlStateNormal];
[[MCDownloadManager defaultInstance] suspendWithDownloadReceipt:receipt];
}else if (receipt.state == MCDownloadStateCompleted) {
if ([self.delegate respondsToSelector:@selector(cell:didClickedBtn:)]) {
[self.delegate cell:self didClickedBtn:sender];
}
}else {
[self.button setTitle:@"停止" forState:UIControlStateNormal];
[self download];
}
}
- (void)download {
[[MCDownloadManager defaultInstance] downloadFileWithURL:self.url
progress:^(NSProgress * _Nonnull downloadProgress, MCDownloadReceipt *receipt) {
if ([receipt.url isEqualToString:self.url]) {
self.progressView.progress = downloadProgress.fractionCompleted ;
self.bytesLable.text = [NSString stringWithFormat:@"%0.2fm/%0.2fm", downloadProgress.completedUnitCount/1024.0/1024, downloadProgress.totalUnitCount/1024.0/1024];
self.speedLable.text = [NSString stringWithFormat:@"%@/s", receipt.speed];
}
}
destination:nil
success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSURL * _Nonnull filePath) {
[self.button setTitle:@"播放" forState:UIControlStateNormal];
}
failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
[self.button setTitle:@"下载" forState:UIControlStateNormal];
}];
}
@end
================================================
FILE: MCDownloadManager/TestViewController.h
================================================
//
// TestViewController.h
// MCDownloadManager
//
// Created by M.C on 17/3/1.
// Copyright © 2017年 qikeyun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TestViewController : UIViewController
@end
================================================
FILE: MCDownloadManager/TestViewController.m
================================================
//
// TestViewController.m
// MCDownloadManager
//
// Created by M.C on 17/3/1.
// Copyright © 2017年 qikeyun. All rights reserved.
//
#import "TestViewController.h"
@interface TestViewController ()
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
================================================
FILE: MCDownloadManager/ViewController.h
================================================
//
// ViewController.h
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UITableViewController
@end
================================================
FILE: MCDownloadManager/ViewController.m
================================================
//
// ViewController.m
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import "ViewController.h"
#import "MCDownloadManager.h"
#import "TableViewCell.h"
#import "MCWiFiManager.h"
#import <MediaPlayer/MediaPlayer.h>
#import "TestViewController.h"
@interface ViewController () <TableViewCellDelegate>
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (strong, nonatomic) NSMutableArray *urls;
@end
@implementation ViewController
- (NSMutableArray *)urls
{
if (!_urls) {
self.urls = [NSMutableArray array];
for (int i = 1; i<=10; i++) {
[self.urls addObject:[NSString stringWithFormat:@"http://120.25.226.186:32812/resources/videos/minion_%02d.mp4", i]];
// [self.urls addObject:@"http://localhost/MJDownload-master.zip"];
}
}
return _urls;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
MCWiFiManager *wifiManager = [[MCWiFiManager alloc] init];
[wifiManager scanNetworksWithCompletionHandler:^(NSArray<MCWiFi *> * _Nullable networks, MCWiFi * _Nullable currentWiFi, NSError * _Nullable error) {
NSLog(@"name:%@ -- mac:%@",currentWiFi.wifiName,currentWiFi.wifiBSSID);
}];
NSLog(@"网关:%@",[wifiManager getGatewayIpForCurrentWiFi]);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.urls.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
cell.url = self.urls[indexPath.row];
cell.delegate = self;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[[MCDownloadManager defaultInstance] removeWithURL:self.urls[indexPath.row]];
[self.tableView reloadData];
}
}
- (IBAction)nextAction:(id)sender {
TestViewController *vc = [[TestViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
return;
NSArray *urls = @[
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F1.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F2.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F3.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F4.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F5.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F6.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F7.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F8.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F9.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F10.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F11.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F12.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F13.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F14.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F15.jpg",
@"http://mhpic.taomanhua.com/comic/M%2F%E8%8E%BD%E8%8D%92%E7%BA%AA%2F34%E8%AF%9D%E5%86%8D%E6%88%98%E7%BF%BC%E8%9B%87%E4%BA%8C%2F16.jpg"
];
for (NSString *url in urls) {
[[MCDownloadManager defaultInstance] downloadFileWithURL:url progress:^(NSProgress * _Nonnull downloadProgress, MCDownloadReceipt * _Nonnull receipt) {
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
return nil;
} success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSURL * _Nonnull filePath) {
NSLog(@"----====");
NSFileManager *filemgr = [NSFileManager defaultManager];
NSString *cacheFolder;
NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
cacheFolder = [cacheDir stringByAppendingPathComponent:@"diyizhang"];
NSError *error = nil;
if(![filemgr createDirectoryAtPath:cacheFolder withIntermediateDirectories:YES attributes:nil error:&error]) {
NSLog(@"Failed to create cache directory at %@", cacheFolder);
cacheFolder = nil;
}
MCDownloadReceipt * receipt = [[MCDownloadManager defaultInstance] downloadReceiptForURL:url];
[filemgr copyItemAtPath:receipt.filePath toPath:[cacheFolder stringByAppendingPathComponent:receipt.filename] error:nil];
[filemgr removeItemAtPath:receipt.filePath error:nil];
} failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
}];
}
}
- (void)cell:(TableViewCell *)cell didClickedBtn:(UIButton *)btn {
MCDownloadReceipt *receipt = [[MCDownloadManager defaultInstance] downloadReceiptForURL:cell.url];
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
MPMoviePlayerViewController *mpc = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL fileURLWithPath:receipt.filePath]];
[vc presentViewController:mpc animated:YES completion:nil];
}
@end
================================================
FILE: MCDownloadManager/main.m
================================================
//
// main.m
// MCDownloadManager
//
// Created by 马超 on 16/9/5.
// Copyright © 2016年 qikeyun. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: MCDownloadManager.podspec
================================================
#
# Be sure to run `pod spec lint MCDownloadManager.podspec' to ensure this is a
# valid spec and to remove all comments including this before submitting the spec.
#
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#
Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# These will help people to find your library, and whilst it
# can feel like a chore to fill in it's definitely to your advantage. The
# summary should be tweet-length, and the description more in depth.
#
s.name = "MCDownloadManager"
s.version = "1.0.3"
s.summary = "A simple and convenient multi task download manager"
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
# s.description = <<-DESC
# A simple and convenient multi task download manager
# DESC
s.homepage = "https://github.com/agelessman/MCDownloadManager"
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Licensing your code is important. See http://choosealicense.com for more info.
# CocoaPods will detect a license file if there is a named LICENSE*
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
#
s.license = "MIT"
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the authors of the library, with email addresses. Email addresses
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
# accepts just a name if you'd rather not provide an email address.
#
# Specify a social_media_url where others can refer to, for example a twitter
# profile URL.
#
s.author = { "machao" => "714080794@qq.com" }
# Or just: s.author = "machao"
# s.authors = { "machao" => "714080794@qq.com" }
# s.social_media_url = "http://twitter.com/machao"
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If this Pod runs only on iOS or OS X, then specify the platform and
# the deployment target. You can optionally include the target after the platform.
#
# s.platform = :ios
s.platform = :ios, "7.0"
# When using multiple platforms
# s.ios.deployment_target = "5.0"
# s.osx.deployment_target = "10.7"
# s.watchos.deployment_target = "2.0"
# s.tvos.deployment_target = "9.0"
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the location from where the source should be retrieved.
# Supports git, hg, bzr, svn and HTTP.
#
s.source = { :git => "https://github.com/agelessman/MCDownloadManager.git", :tag => "#{s.version}" }
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any swift, h, m, mm, c & cpp files.
# For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public.
#
s.source_files = "MCDownloadManager/MCDownloadManager/*.{h,m}"
s.exclude_files = "Classes/Exclude"
# s.public_header_files = "Classes/**/*.h"
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# A list of resources included with the Pod. These are copied into the
# target bundle with a build phase script. Anything else will be cleaned.
# You can preserve files from being cleaned, please don't preserve
# non-essential files like tests, examples and documentation.
#
# s.resource = "icon.png"
# s.resources = "Resources/*.png"
# s.preserve_paths = "FilesToSave", "MoreFilesToSave"
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Link your library with frameworks, or libraries. Libraries do not include
# the lib prefix of their name.
#
s.framework = "Foundation", "UIKit"
# s.frameworks = "Foundation", "UIKit"
# s.library = "iconv"
# s.libraries = "iconv", "xml2"
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If your library depends on compiler flags you can set them in the xcconfig hash
# where they will only apply to your library. If you depend on other Podspecs
# you can include multiple dependencies to ensure it works.
# s.requires_arc = true
# s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
# s.dependency "JSONKit", "~> 1.4"
end
================================================
FILE: MCDownloadManager.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
9B0E8D281D825CDC00452963 /* QKYDelayButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E8D271D825CDC00452963 /* QKYDelayButton.m */; };
9B24E5C41D7D44D300AA2ECC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B24E5C31D7D44D300AA2ECC /* main.m */; };
9B24E5C71D7D44D300AA2ECC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B24E5C61D7D44D300AA2ECC /* AppDelegate.m */; };
9B24E5CA1D7D44D300AA2ECC /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B24E5C91D7D44D300AA2ECC /* ViewController.m */; };
9B24E5CD1D7D44D300AA2ECC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9B24E5CB1D7D44D300AA2ECC /* Main.storyboard */; };
9B24E5CF1D7D44D300AA2ECC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9B24E5CE1D7D44D300AA2ECC /* Assets.xcassets */; };
9B24E5D21D7D44D300AA2ECC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9B24E5D01D7D44D300AA2ECC /* LaunchScreen.storyboard */; };
9B24E5DC1D7D453B00AA2ECC /* MCDownloadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B24E5DB1D7D453B00AA2ECC /* MCDownloadManager.m */; };
9B48434E1D7EC00E00A2CBBE /* TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B48434D1D7EC00E00A2CBBE /* TableViewCell.m */; };
E78B54CB1E66C5C100C28612 /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E78B54CA1E66C5C100C28612 /* TestViewController.m */; };
E78B54D51E69214900C28612 /* MCURLRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E78B54CE1E69214900C28612 /* MCURLRequest.m */; };
E78B54D61E69214900C28612 /* MCURLRequestCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = E78B54D01E69214900C28612 /* MCURLRequestCenter.m */; };
E78B54D71E69214900C28612 /* MCURLResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E78B54D21E69214900C28612 /* MCURLResponse.m */; };
E78B54D81E69214900C28612 /* MCURLSessionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = E78B54D41E69214900C28612 /* MCURLSessionConfiguration.m */; };
E78B54DB1E693B3B00C28612 /* MCWiFiManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E78B54DA1E693B3B00C28612 /* MCWiFiManager.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
521970A81DF69503009C7D65 /* MCDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDefine.h; sourceTree = "<group>"; };
9B0E8D261D825CDC00452963 /* QKYDelayButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QKYDelayButton.h; sourceTree = "<group>"; };
9B0E8D271D825CDC00452963 /* QKYDelayButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QKYDelayButton.m; sourceTree = "<group>"; };
9B24E5BF1D7D44D300AA2ECC /* MCDownloadManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MCDownloadManager.app; sourceTree = BUILT_PRODUCTS_DIR; };
9B24E5C31D7D44D300AA2ECC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
9B24E5C51D7D44D300AA2ECC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
9B24E5C61D7D44D300AA2ECC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9B24E5C81D7D44D300AA2ECC /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
9B24E5C91D7D44D300AA2ECC /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
9B24E5CC1D7D44D300AA2ECC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
9B24E5CE1D7D44D300AA2ECC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
9B24E5D11D7D44D300AA2ECC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
9B24E5D31D7D44D300AA2ECC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9B24E5DA1D7D453B00AA2ECC /* MCDownloadManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDownloadManager.h; sourceTree = "<group>"; };
9B24E5DB1D7D453B00AA2ECC /* MCDownloadManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCDownloadManager.m; sourceTree = "<group>"; };
9B48434C1D7EC00E00A2CBBE /* TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewCell.h; sourceTree = "<group>"; };
9B48434D1D7EC00E00A2CBBE /* TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewCell.m; sourceTree = "<group>"; };
E78B54C91E66C5C100C28612 /* TestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = "<group>"; };
E78B54CA1E66C5C100C28612 /* TestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = "<group>"; };
E78B54CD1E69214900C28612 /* MCURLRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCURLRequest.h; sourceTree = "<group>"; };
E78B54CE1E69214900C28612 /* MCURLRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCURLRequest.m; sourceTree = "<group>"; };
E78B54CF1E69214900C28612 /* MCURLRequestCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCURLRequestCenter.h; sourceTree = "<group>"; };
E78B54D01E69214900C28612 /* MCURLRequestCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCURLRequestCenter.m; sourceTree = "<group>"; };
E78B54D11E69214900C28612 /* MCURLResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCURLResponse.h; sourceTree = "<group>"; };
E78B54D21E69214900C28612 /* MCURLResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCURLResponse.m; sourceTree = "<group>"; };
E78B54D31E69214900C28612 /* MCURLSessionConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCURLSessionConfiguration.h; sourceTree = "<group>"; };
E78B54D41E69214900C28612 /* MCURLSessionConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCURLSessionConfiguration.m; sourceTree = "<group>"; };
E78B54D91E693B3B00C28612 /* MCWiFiManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCWiFiManager.h; sourceTree = "<group>"; };
E78B54DA1E693B3B00C28612 /* MCWiFiManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCWiFiManager.m; sourceTree = "<group>"; };
E797F6CB1E78ECD300F5631B /* MCDownloadManager.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MCDownloadManager.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9B24E5BC1D7D44D300AA2ECC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9B24E5B61D7D44D300AA2ECC = {
isa = PBXGroup;
children = (
9B24E5C11D7D44D300AA2ECC /* MCDownloadManager */,
9B24E5C01D7D44D300AA2ECC /* Products */,
E797F6C81E78ECD300F5631B /* Frameworks */,
);
sourceTree = "<group>";
};
9B24E5C01D7D44D300AA2ECC /* Products */ = {
isa = PBXGroup;
children = (
9B24E5BF1D7D44D300AA2ECC /* MCDownloadManager.app */,
);
name = Products;
sourceTree = "<group>";
};
9B24E5C11D7D44D300AA2ECC /* MCDownloadManager */ = {
isa = PBXGroup;
children = (
E797F6CB1E78ECD300F5631B /* MCDownloadManager.entitlements */,
E78B54CC1E69214900C28612 /* Networking */,
9B24E5D91D7D451200AA2ECC /* MCDownloadManager */,
9B24E5C51D7D44D300AA2ECC /* AppDelegate.h */,
9B24E5C61D7D44D300AA2ECC /* AppDelegate.m */,
9B24E5C81D7D44D300AA2ECC /* ViewController.h */,
9B24E5C91D7D44D300AA2ECC /* ViewController.m */,
E78B54C91E66C5C100C28612 /* TestViewController.h */,
E78B54CA1E66C5C100C28612 /* TestViewController.m */,
9B48434C1D7EC00E00A2CBBE /* TableViewCell.h */,
9B48434D1D7EC00E00A2CBBE /* TableViewCell.m */,
9B0E8D261D825CDC00452963 /* QKYDelayButton.h */,
9B0E8D271D825CDC00452963 /* QKYDelayButton.m */,
9B24E5CB1D7D44D300AA2ECC /* Main.storyboard */,
9B24E5CE1D7D44D300AA2ECC /* Assets.xcassets */,
9B24E5D01D7D44D300AA2ECC /* LaunchScreen.storyboard */,
9B24E5D31D7D44D300AA2ECC /* Info.plist */,
9B24E5C21D7D44D300AA2ECC /* Supporting Files */,
);
path = MCDownloadManager;
sourceTree = "<group>";
};
9B24E5C21D7D44D300AA2ECC /* Supporting Files */ = {
isa = PBXGroup;
children = (
9B24E5C31D7D44D300AA2ECC /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
9B24E5D91D7D451200AA2ECC /* MCDownloadManager */ = {
isa = PBXGroup;
children = (
521970A81DF69503009C7D65 /* MCDefine.h */,
9B24E5DA1D7D453B00AA2ECC /* MCDownloadManager.h */,
9B24E5DB1D7D453B00AA2ECC /* MCDownloadManager.m */,
);
path = MCDownloadManager;
sourceTree = "<group>";
};
E78B54CC1E69214900C28612 /* Networking */ = {
isa = PBXGroup;
children = (
E78B54D91E693B3B00C28612 /* MCWiFiManager.h */,
E78B54DA1E693B3B00C28612 /* MCWiFiManager.m */,
E78B54CD1E69214900C28612 /* MCURLRequest.h */,
E78B54CE1E69214900C28612 /* MCURLRequest.m */,
E78B54CF1E69214900C28612 /* MCURLRequestCenter.h */,
E78B54D01E69214900C28612 /* MCURLRequestCenter.m */,
E78B54D11E69214900C28612 /* MCURLResponse.h */,
E78B54D21E69214900C28612 /* MCURLResponse.m */,
E78B54D31E69214900C28612 /* MCURLSessionConfiguration.h */,
E78B54D41E69214900C28612 /* MCURLSessionConfiguration.m */,
);
path = Networking;
sourceTree = "<group>";
};
E797F6C81E78ECD300F5631B /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9B24E5BE1D7D44D300AA2ECC /* MCDownloadManager */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9B24E5D61D7D44D300AA2ECC /* Build configuration list for PBXNativeTarget "MCDownloadManager" */;
buildPhases = (
9B24E5BB1D7D44D300AA2ECC /* Sources */,
9B24E5BC1D7D44D300AA2ECC /* Frameworks */,
9B24E5BD1D7D44D300AA2ECC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = MCDownloadManager;
productName = MCDownloadManager;
productReference = 9B24E5BF1D7D44D300AA2ECC /* MCDownloadManager.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9B24E5B71D7D44D300AA2ECC /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = qikeyun;
TargetAttributes = {
9B24E5BE1D7D44D300AA2ECC = {
CreatedOnToolsVersion = 7.3;
DevelopmentTeam = XC34BSW465;
SystemCapabilities = {
com.apple.BackgroundModes = {
enabled = 1;
};
com.apple.InterAppAudio = {
enabled = 0;
};
};
};
};
};
buildConfigurationList = 9B24E5BA1D7D44D300AA2ECC /* Build configuration list for PBXProject "MCDownloadManager" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 9B24E5B61D7D44D300AA2ECC;
productRefGroup = 9B24E5C01D7D44D300AA2ECC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9B24E5BE1D7D44D300AA2ECC /* MCDownloadManager */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
9B24E5BD1D7D44D300AA2ECC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9B24E5D21D7D44D300AA2ECC /* LaunchScreen.storyboard in Resources */,
9B24E5CF1D7D44D300AA2ECC /* Assets.xcassets in Resources */,
9B24E5CD1D7D44D300AA2ECC /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9B24E5BB1D7D44D300AA2ECC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E78B54DB1E693B3B00C28612 /* MCWiFiManager.m in Sources */,
E78B54D81E69214900C28612 /* MCURLSessionConfiguration.m in Sources */,
E78B54CB1E66C5C100C28612 /* TestViewController.m in Sources */,
E78B54D71E69214900C28612 /* MCURLResponse.m in Sources */,
9B24E5CA1D7D44D300AA2ECC /* ViewController.m in Sources */,
9B48434E1D7EC00E00A2CBBE /* TableViewCell.m in Sources */,
9B24E5DC1D7D453B00AA2ECC /* MCDownloadManager.m in Sources */,
E78B54D51E69214900C28612 /* MCURLRequest.m in Sources */,
9B24E5C71D7D44D300AA2ECC /* AppDelegate.m in Sources */,
E78B54D61E69214900C28612 /* MCURLRequestCenter.m in Sources */,
9B0E8D281D825CDC00452963 /* QKYDelayButton.m in Sources */,
9B24E5C41D7D44D300AA2ECC /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
9B24E5CB1D7D44D300AA2ECC /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
9B24E5CC1D7D44D300AA2ECC /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
9B24E5D01D7D44D300AA2ECC /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
9B24E5D11D7D44D300AA2ECC /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
9B24E5D41D7D44D300AA2ECC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
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_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
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 = 9.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
9B24E5D51D7D44D300AA2ECC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
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_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
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 = 9.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
9B24E5D71D7D44D300AA2ECC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = XC34BSW465;
INFOPLIST_FILE = MCDownloadManager/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.7keyun.com.MCDownloadManager;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
9B24E5D81D7D44D300AA2ECC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = XC34BSW465;
INFOPLIST_FILE = MCDownloadManager/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.7keyun.com.MCDownloadManager;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9B24E5BA1D7D44D300AA2ECC /* Build configuration list for PBXProject "MCDownloadManager" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9B24E5D41D7D44D300AA2ECC /* Debug */,
9B24E5D51D7D44D300AA2ECC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9B24E5D61D7D44D300AA2ECC /* Build configuration list for PBXNativeTarget "MCDownloadManager" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9B24E5D71D7D44D300AA2ECC /* Debug */,
9B24E5D81D7D44D300AA2ECC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 9B24E5B71D7D44D300AA2ECC /* Project object */;
}
================================================
FILE: MCDownloadManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:MCDownloadManager.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/M.C.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "1"
version = "2.0">
</Bucket>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/M.C.xcuserdatad/xcschemes/MCDownloadManager.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/M.C.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?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>SchemeUserState</key>
<dict>
<key>MCDownloadManager.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>9B24E5BE1D7D44D300AA2ECC</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/machao.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "1"
version = "2.0">
</Bucket>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/machao.xcuserdatad/xcschemes/MCDownloadManager.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/machao.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?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>SchemeUserState</key>
<dict>
<key>MCDownloadManager.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>9B24E5BE1D7D44D300AA2ECC</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/test.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "1"
version = "2.0">
</Bucket>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/test.xcuserdatad/xcschemes/MCDownloadManager.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0810"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9B24E5BE1D7D44D300AA2ECC"
BuildableName = "MCDownloadManager.app"
BlueprintName = "MCDownloadManager"
ReferencedContainer = "container:MCDownloadManager.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: MCDownloadManager.xcodeproj/xcuserdata/test.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?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>SchemeUserState</key>
<dict>
<key>MCDownloadManager.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>9B24E5BE1D7D44D300AA2ECC</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
================================================
FILE: README.md
================================================
# MCDownloadManager
A simple and convenient multi task download manager

## Attention
这个版本默认只支持同时下载10个文件
This version only supports 10 file downloads at the same time.
若要支持更多,请修改下边的代码
`configuration.HTTPMaximumConnectionsPerHost = 10;`
**添加了速度提示(比如:400KB/s)**
**支持后台和锁屏下载**
## Installation
### Cocoapods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
```bash
$ gem install cocoapods
```
> CocoaPods 1.1.0+ is required to build MCDownloadManager 1.0.0+.
To integrate MCDownloadManager into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
pod 'MCDownloadManager', '~> 1.0.3'
```
Then, run the following command:
```bash
$ pod install
```
## Usage
- (void)download {
[[MCDownloadManager defaultInstance] downloadFileWithURL:self.url
progress:^(NSProgress * _Nonnull downloadProgress, MCDownloadReceipt *receipt) {
if ([receipt.url isEqualToString:self.url]) {
self.progressView.progress = downloadProgress.fractionCompleted ;
}
}
destination:nil
success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSURL * _Nonnull filePath) {
[self.button setTitle:@"播放" forState:UIControlStateNormal];
}
failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
[self.button setTitle:@"重新下载" forState:UIControlStateNormal];
}];
}
gitextract_f5m8txjr/ ├── LICENSE ├── MCDownloadManager/ │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets/ │ │ └── AppIcon.appiconset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── MCDownloadManager/ │ │ ├── MCDefine.h │ │ ├── MCDownloadManager.h │ │ └── MCDownloadManager.m │ ├── MCDownloadManager.entitlements │ ├── Networking/ │ │ ├── MCURLRequest.h │ │ ├── MCURLRequest.m │ │ ├── MCURLRequestCenter.h │ │ ├── MCURLRequestCenter.m │ │ ├── MCURLResponse.h │ │ ├── MCURLResponse.m │ │ ├── MCURLSessionConfiguration.h │ │ ├── MCURLSessionConfiguration.m │ │ ├── MCWiFiManager.h │ │ └── MCWiFiManager.m │ ├── QKYDelayButton.h │ ├── QKYDelayButton.m │ ├── TableViewCell.h │ ├── TableViewCell.m │ ├── TestViewController.h │ ├── TestViewController.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── MCDownloadManager.podspec ├── MCDownloadManager.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata/ │ │ ├── M.C.xcuserdatad/ │ │ │ └── UserInterfaceState.xcuserstate │ │ ├── machao.xcuserdatad/ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── test.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata/ │ ├── M.C.xcuserdatad/ │ │ ├── xcdebugger/ │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes/ │ │ ├── MCDownloadManager.xcscheme │ │ └── xcschememanagement.plist │ ├── machao.xcuserdatad/ │ │ ├── xcdebugger/ │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes/ │ │ ├── MCDownloadManager.xcscheme │ │ └── xcschememanagement.plist │ └── test.xcuserdatad/ │ ├── xcdebugger/ │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes/ │ ├── MCDownloadManager.xcscheme │ └── xcschememanagement.plist └── README.md
SYMBOL INDEX (2 symbols across 1 files)
FILE: MCDownloadManager/MCDownloadManager/MCDownloadManager.h
type MCDownloadStateNone (line 18) | typedef NS_ENUM(NSUInteger, MCDownloadState) {
type MCDownloadPrioritizationFIFO (line 28) | typedef NS_ENUM(NSInteger, MCDownloadPrioritization) {
Condensed preview — 46 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (149K chars).
[
{
"path": "LICENSE",
"chars": 1102,
"preview": "Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)\n\nPermission is hereby granted, free of cha"
},
{
"path": "MCDownloadManager/AppDelegate.h",
"chars": 274,
"preview": "//\n// AppDelegate.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All rights res"
},
{
"path": "MCDownloadManager/AppDelegate.m",
"chars": 2060,
"preview": "//\n// AppDelegate.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All rights res"
},
{
"path": "MCDownloadManager/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 585,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"size\" : \"29x29\",\n \"scale\" : \"2x\"\n },\n {\n \"idiom\""
},
{
"path": "MCDownloadManager/Base.lproj/LaunchScreen.storyboard",
"chars": 1664,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "MCDownloadManager/Base.lproj/Main.storyboard",
"chars": 12161,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "MCDownloadManager/Info.plist",
"chars": 1566,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "MCDownloadManager/MCDownloadManager/MCDefine.h",
"chars": 614,
"preview": "//\n// MCDefine.h\n// JZGChryslerForPad\n//\n// Created by test on 16/12/6.\n// Copyright © 2016年 Beijing JingZhenGu Info"
},
{
"path": "MCDownloadManager/MCDownloadManager/MCDownloadManager.h",
"chars": 5575,
"preview": "//\n// MCDownloadManager.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All righ"
},
{
"path": "MCDownloadManager/MCDownloadManager/MCDownloadManager.m",
"chars": 24596,
"preview": "//\n// MCDownloadManager.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All righ"
},
{
"path": "MCDownloadManager/MCDownloadManager.entitlements",
"chars": 181,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "MCDownloadManager/Networking/MCURLRequest.h",
"chars": 3328,
"preview": "//\n// MCURLRequest.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/23.\n// Copyright © 2016年 qikeyun. All rights r"
},
{
"path": "MCDownloadManager/Networking/MCURLRequest.m",
"chars": 1907,
"preview": "//\n// MCURLRequest.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/23.\n// Copyright © 2016年 qikeyun. All rights r"
},
{
"path": "MCDownloadManager/Networking/MCURLRequestCenter.h",
"chars": 221,
"preview": "//\n// MCURLRequestCenter.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/30.\n// Copyright © 2016年 qikeyun. All ri"
},
{
"path": "MCDownloadManager/Networking/MCURLRequestCenter.m",
"chars": 212,
"preview": "//\n// MCURLRequestCenter.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/30.\n// Copyright © 2016年 qikeyun. All ri"
},
{
"path": "MCDownloadManager/Networking/MCURLResponse.h",
"chars": 1682,
"preview": "//\n// MCURLResponse.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/21.\n// Copyright © 2016年 qikeyun. All rights "
},
{
"path": "MCDownloadManager/Networking/MCURLResponse.m",
"chars": 1839,
"preview": "//\n// MCURLResponse.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/21.\n// Copyright © 2016年 qikeyun. All rights "
},
{
"path": "MCDownloadManager/Networking/MCURLSessionConfiguration.h",
"chars": 512,
"preview": "//\n// MCURLSessionConfiguration.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/23.\n// Copyright © 2016年 qikeyun."
},
{
"path": "MCDownloadManager/Networking/MCURLSessionConfiguration.m",
"chars": 233,
"preview": "//\n// MCURLSessionConfiguration.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/23.\n// Copyright © 2016年 qikeyun."
},
{
"path": "MCDownloadManager/Networking/MCWiFiManager.h",
"chars": 1238,
"preview": "//\n// MCWiFiManager.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/14.\n// Copyright © 2016年 qikeyun. All rights "
},
{
"path": "MCDownloadManager/Networking/MCWiFiManager.m",
"chars": 19539,
"preview": "//\n// MCWiFiManager.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/14.\n// Copyright © 2016年 qikeyun. All rights "
},
{
"path": "MCDownloadManager/QKYDelayButton.h",
"chars": 254,
"preview": "//\n// QKYDelayButton.h\n// qikeyun\n//\n// Created by 马超 on 16/6/4.\n// Copyright © 2016年 Jerome. All rights reserved.\n/"
},
{
"path": "MCDownloadManager/QKYDelayButton.m",
"chars": 1142,
"preview": "//\n// QKYDelayButton.m\n// qikeyun\n//\n// Created by 马超 on 16/6/4.\n// Copyright © 2016年 Jerome. All rights reserved.\n/"
},
{
"path": "MCDownloadManager/TableViewCell.h",
"chars": 781,
"preview": "//\n// TableViewCell.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/6.\n// Copyright © 2016年 qikeyun. All rights r"
},
{
"path": "MCDownloadManager/TableViewCell.m",
"chars": 4884,
"preview": "//\n// TableViewCell.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/6.\n// Copyright © 2016年 qikeyun. All rights r"
},
{
"path": "MCDownloadManager/TestViewController.h",
"chars": 219,
"preview": "//\n// TestViewController.h\n// MCDownloadManager\n//\n// Created by M.C on 17/3/1.\n// Copyright © 2017年 qikeyun. All ri"
},
{
"path": "MCDownloadManager/TestViewController.m",
"chars": 832,
"preview": "//\n// TestViewController.m\n// MCDownloadManager\n//\n// Created by M.C on 17/3/1.\n// Copyright © 2017年 qikeyun. All ri"
},
{
"path": "MCDownloadManager/ViewController.h",
"chars": 217,
"preview": "//\n// ViewController.h\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All rights "
},
{
"path": "MCDownloadManager/ViewController.m",
"chars": 7284,
"preview": "//\n// ViewController.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All rights "
},
{
"path": "MCDownloadManager/main.m",
"chars": 331,
"preview": "//\n// main.m\n// MCDownloadManager\n//\n// Created by 马超 on 16/9/5.\n// Copyright © 2016年 qikeyun. All rights reserved.\n"
},
{
"path": "MCDownloadManager.podspec",
"chars": 5152,
"preview": "#\n# Be sure to run `pod spec lint MCDownloadManager.podspec' to ensure this is a\n# valid spec and to remove all commen"
},
{
"path": "MCDownloadManager.xcodeproj/project.pbxproj",
"chars": 19775,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "MCDownloadManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 162,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:MCDownloadManag"
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/M.C.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
"chars": 91,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n type = \"1\"\n version = \"2.0\">\n</Bucket>\n"
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/M.C.xcuserdatad/xcschemes/MCDownloadManager.xcscheme",
"chars": 3423,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0810\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/M.C.xcuserdatad/xcschemes/xcschememanagement.plist",
"chars": 489,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/machao.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
"chars": 91,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n type = \"1\"\n version = \"2.0\">\n</Bucket>\n"
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/machao.xcuserdatad/xcschemes/MCDownloadManager.xcscheme",
"chars": 3423,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0800\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/machao.xcuserdatad/xcschemes/xcschememanagement.plist",
"chars": 489,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/test.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
"chars": 91,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n type = \"1\"\n version = \"2.0\">\n</Bucket>\n"
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/test.xcuserdatad/xcschemes/MCDownloadManager.xcscheme",
"chars": 3423,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0810\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "MCDownloadManager.xcodeproj/xcuserdata/test.xcuserdatad/xcschemes/xcschememanagement.plist",
"chars": 489,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "README.md",
"chars": 2279,
"preview": "# MCDownloadManager\nA simple and convenient multi task download manager\n\n
About this extraction
This page contains the full source code of the agelessman/MCDownloadManager GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 46 files (133.2 KB), approximately 37.0k tokens, and a symbol index with 2 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.