├── .DS_Store ├── HWDownloadDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ └── wangqibin.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings ├── xcshareddata │ └── xcschemes │ │ └── HWDownloadDemo.xcscheme └── xcuserdata │ └── wangqibin.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── HWDownloadDemo ├── Categorys │ ├── NSArray+Crash.h │ ├── NSArray+Crash.m │ ├── NSString+HW.h │ ├── NSString+HW.m │ ├── UIColor+HW.h │ ├── UIColor+HW.m │ ├── UIImage+HW.h │ ├── UIImage+HW.m │ ├── UIView+Extension.h │ └── UIView+Extension.m ├── Common │ ├── .DS_Store │ ├── HWDownloadManager │ │ ├── HWDataBaseManager.h │ │ ├── HWDataBaseManager.m │ │ ├── HWDownload.h │ │ ├── HWDownloadManager.h │ │ ├── HWDownloadManager.m │ │ ├── HWDownloadModel.h │ │ ├── HWDownloadModel.m │ │ ├── NSURLSession+CorrectedResumeData.h │ │ └── NSURLSession+CorrectedResumeData.m │ ├── HWNetworkReachabilityManager.h │ ├── HWNetworkReachabilityManager.m │ ├── HWProgressHUD.h │ ├── HWProgressHUD.m │ ├── HWToolBox.h │ ├── HWToolBox.m │ └── SwizzlingDefine.h ├── Home │ ├── HWPlayVC │ │ └── Controller │ │ │ ├── HWPlayVC.h │ │ │ └── HWPlayVC.m │ └── Home │ │ ├── Controller │ │ ├── HWHomeVC.h │ │ └── HWHomeVC.m │ │ └── View │ │ ├── HWDownloadButton.h │ │ ├── HWDownloadButton.m │ │ ├── HWHomeCell.h │ │ └── HWHomeCell.m ├── Main │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── HWBaseViewController.h │ ├── HWBaseViewController.m │ ├── NavigationController │ │ ├── HWNavigationController.h │ │ ├── HWNavigationController.m │ │ ├── UINavigationBar+Swizzling.h │ │ ├── UINavigationBar+Swizzling.m │ │ ├── UINavigationItem+Swizzling.h │ │ └── UINavigationItem+Swizzling.m │ └── TabBarController │ │ ├── HWTabBarController.h │ │ ├── HWTabBarController.m │ │ ├── HWTabBarView.h │ │ └── HWTabBarView.m ├── Me │ ├── Cache │ │ └── Controller │ │ │ ├── HWCacheBaseVC.h │ │ │ ├── HWCacheBaseVC.m │ │ │ ├── HWCacheVC.h │ │ │ ├── HWCacheVC.m │ │ │ ├── HWDownloadingVC.h │ │ │ └── HWDownloadingVC.m │ ├── Me │ │ └── Controller │ │ │ ├── HWMeVC.h │ │ │ └── HWMeVC.m │ └── Setting │ │ └── Controller │ │ ├── HWSettingVC.h │ │ └── HWSettingVC.m ├── Other │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── GlobeConst.h │ ├── GlobeConst.m │ ├── GlobeHeader.h │ ├── Images │ │ └── Common │ │ │ ├── com_download_default@2x.png │ │ │ ├── com_download_default@3x.png │ │ │ ├── com_download_error@2x.png │ │ │ ├── com_download_error@3x.png │ │ │ ├── com_download_finish@2x.png │ │ │ ├── com_download_finish@3x.png │ │ │ ├── com_download_pause@2x.png │ │ │ ├── com_download_pause@3x.png │ │ │ ├── com_download_waiting@2x.png │ │ │ ├── com_download_waiting@3x.png │ │ │ ├── com_loading01@2x.png │ │ │ ├── com_loading02@2x.png │ │ │ ├── com_loading03@2x.png │ │ │ ├── com_loading04@2x.png │ │ │ ├── com_loading05@2x.png │ │ │ ├── com_loading06@2x.png │ │ │ ├── com_loading07@2x.png │ │ │ ├── com_loading08@2x.png │ │ │ ├── nav_back@2x.png │ │ │ ├── nav_back@3x.png │ │ │ ├── nav_cancelBtn@2x.png │ │ │ ├── nav_cancelBtn@3x.png │ │ │ ├── nav_deleteBtn@2x.png │ │ │ ├── nav_deleteBtn@3x.png │ │ │ ├── tabbar_home_nor@2x.png │ │ │ ├── tabbar_home_nor@3x.png │ │ │ ├── tabbar_home_sel@2x.png │ │ │ ├── tabbar_home_sel@3x.png │ │ │ ├── tabbar_me_nor@2x.png │ │ │ ├── tabbar_me_nor@3x.png │ │ │ ├── tabbar_me_sel@2x.png │ │ │ └── tabbar_me_sel@3x.png │ ├── Info.plist │ ├── PrefixHeader.pch │ ├── main.m │ └── testData.plist └── Vender │ ├── AFNetworking │ ├── AFNetworking │ │ ├── AFHTTPSessionManager.h │ │ ├── AFHTTPSessionManager.m │ │ ├── AFNetworkReachabilityManager.h │ │ ├── AFNetworkReachabilityManager.m │ │ ├── AFNetworking.h │ │ ├── AFSecurityPolicy.h │ │ ├── AFSecurityPolicy.m │ │ ├── AFURLRequestSerialization.h │ │ ├── AFURLRequestSerialization.m │ │ ├── AFURLResponseSerialization.h │ │ ├── AFURLResponseSerialization.m │ │ ├── AFURLSessionManager.h │ │ └── AFURLSessionManager.m │ ├── LICENSE │ ├── README.md │ └── UIKit+AFNetworking │ │ ├── AFAutoPurgingImageCache.h │ │ ├── AFAutoPurgingImageCache.m │ │ ├── AFImageDownloader.h │ │ ├── AFImageDownloader.m │ │ ├── AFNetworkActivityIndicatorManager.h │ │ ├── AFNetworkActivityIndicatorManager.m │ │ ├── UIActivityIndicatorView+AFNetworking.h │ │ ├── UIActivityIndicatorView+AFNetworking.m │ │ ├── UIButton+AFNetworking.h │ │ ├── UIButton+AFNetworking.m │ │ ├── UIImage+AFNetworking.h │ │ ├── UIImageView+AFNetworking.h │ │ ├── UIImageView+AFNetworking.m │ │ ├── UIKit+AFNetworking.h │ │ ├── UIProgressView+AFNetworking.h │ │ ├── UIProgressView+AFNetworking.m │ │ ├── UIRefreshControl+AFNetworking.h │ │ ├── UIRefreshControl+AFNetworking.m │ │ ├── UIWebView+AFNetworking.h │ │ └── UIWebView+AFNetworking.m │ ├── FMDB │ ├── LICENSE.txt │ ├── README.markdown │ └── src │ │ └── fmdb │ │ ├── FMDB.h │ │ ├── FMDatabase.h │ │ ├── FMDatabase.m │ │ ├── FMDatabaseAdditions.h │ │ ├── FMDatabaseAdditions.m │ │ ├── FMDatabasePool.h │ │ ├── FMDatabasePool.m │ │ ├── FMDatabaseQueue.h │ │ ├── FMDatabaseQueue.m │ │ ├── FMResultSet.h │ │ └── FMResultSet.m │ └── MJExtension │ ├── LICENSE │ ├── MJExtension │ ├── MJExtension.h │ ├── MJExtensionConst.h │ ├── MJExtensionConst.m │ ├── MJFoundation.h │ ├── MJFoundation.m │ ├── MJProperty.h │ ├── MJProperty.m │ ├── MJPropertyKey.h │ ├── MJPropertyKey.m │ ├── MJPropertyType.h │ ├── MJPropertyType.m │ ├── NSObject+MJClass.h │ ├── NSObject+MJClass.m │ ├── NSObject+MJCoding.h │ ├── NSObject+MJCoding.m │ ├── NSObject+MJKeyValue.h │ ├── NSObject+MJKeyValue.m │ ├── NSObject+MJProperty.h │ ├── NSObject+MJProperty.m │ ├── NSString+MJExtension.h │ └── NSString+MJExtension.m │ └── README.md ├── HWDownloadDemoTests ├── HWDownloadDemoTests.m └── Info.plist ├── HWDownloadDemoUITests ├── HWDownloadDemoUITests.m └── Info.plist └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/.DS_Store -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/project.xcworkspace/xcuserdata/wangqibin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo.xcodeproj/project.xcworkspace/xcuserdata/wangqibin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/project.xcworkspace/xcuserdata/wangqibin.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | EnabledFullIndexStoreVisibility 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/xcshareddata/xcschemes/HWDownloadDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 89 | 90 | 91 | 92 | 93 | 94 | 100 | 102 | 108 | 109 | 110 | 111 | 113 | 114 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/xcuserdata/wangqibin.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /HWDownloadDemo.xcodeproj/xcuserdata/wangqibin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HWDownloadDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | HWDownloadDemo.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 3DADAD6620B2BD70006D7FC8 21 | 22 | primary 23 | 24 | 25 | 3DADAD7E20B2BD70006D7FC8 26 | 27 | primary 28 | 29 | 30 | 3DADAD8920B2BD70006D7FC8 31 | 32 | primary 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/NSArray+Crash.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Crash.h 3 | // SXEducation 4 | // 5 | // Created by sxmaps_w on 2017/11/24. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSArray (Crash) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/NSArray+Crash.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Crash.m 3 | // SXEducation 4 | // 5 | // Created by sxmaps_w on 2017/11/24. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | #import "NSArray+Crash.h" 10 | #import 11 | 12 | @implementation NSArray (Crash) 13 | 14 | + (void)load 15 | { 16 | [super load]; 17 | 18 | //替换不可变数组方法 19 | Method oldObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:)); 20 | Method newObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtSafeIndex:)); 21 | method_exchangeImplementations(oldObjectAtIndex, newObjectAtIndex); 22 | 23 | //替换可变数组方法 24 | Method oldMutableObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(objectAtIndex:)); 25 | Method newMutableObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(mutableObjectAtSafeIndex:)); 26 | method_exchangeImplementations(oldMutableObjectAtIndex, newMutableObjectAtIndex); 27 | } 28 | 29 | - (id)objectAtSafeIndex:(NSUInteger)index 30 | { 31 | if (index > self.count - 1 || !self.count) { 32 | @try { 33 | return [self objectAtSafeIndex:index]; 34 | } 35 | @catch (NSException *exception) { 36 | HWLog(@"exception: %@", exception.reason); 37 | return nil; 38 | } 39 | 40 | }else { 41 | return [self objectAtSafeIndex:index]; 42 | } 43 | } 44 | 45 | - (id)mutableObjectAtSafeIndex:(NSUInteger)index 46 | { 47 | if (index > self.count - 1 || !self.count) { 48 | @try { 49 | return [self mutableObjectAtSafeIndex:index]; 50 | } 51 | @catch (NSException *exception) { 52 | HWLog(@"exception: %@", exception.reason); 53 | return nil; 54 | } 55 | 56 | }else { 57 | return [self mutableObjectAtSafeIndex:index]; 58 | } 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/NSString+HW.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HW.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (HW) 12 | 13 | // MD5加密 14 | - (NSString *)MD5; 15 | 16 | // 中文、特殊字符转码 17 | - (NSString *)transEncodingString; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/NSString+HW.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HW.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "NSString+HW.h" 10 | #import 11 | 12 | @implementation NSString (HW) 13 | 14 | // MD5加密 15 | - (NSString *)MD5 16 | { 17 | const char *ptr = [self UTF8String]; 18 | 19 | unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH]; 20 | 21 | CC_MD5(ptr, (unsigned int)strlen(ptr), md5Buffer); 22 | 23 | NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH *2]; 24 | for (int i = 0; i 10 | 11 | @interface UIColor (HW) 12 | 13 | //16进制转化RGB 14 | + (UIColor *)colorWithHexString:(NSString *)string; 15 | 16 | //随即色 17 | + (UIColor *)randomColor; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/UIColor+HW.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+HW.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "UIColor+HW.h" 10 | 11 | @implementation UIColor (HW) 12 | 13 | + (UIColor *)colorWithHexString:(NSString *)string 14 | { 15 | if ([string hasPrefix:@"#"]) string = [string substringFromIndex:1]; 16 | 17 | // Separate into r, g, b substrings 18 | NSRange range; 19 | range.length = 2; 20 | 21 | range.location = 0; 22 | NSString *rString = [string substringWithRange:range]; 23 | 24 | range.location = 2; 25 | NSString *gString = [string substringWithRange:range]; 26 | 27 | range.location = 4; 28 | NSString *bString = [string substringWithRange:range]; 29 | 30 | unsigned int r, g, b; 31 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 32 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 33 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 34 | 35 | return [UIColor colorWithRed:((float)r/255.0f) green:((float)g/255.0f) blue:((float)b/255.0f) alpha:1]; 36 | } 37 | 38 | + (UIColor *)randomColor 39 | { 40 | CGFloat red = arc4random_uniform(256); 41 | CGFloat green = arc4random_uniform(256); 42 | CGFloat blue = arc4random_uniform(256); 43 | 44 | return [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/UIImage+HW.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+HW.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (HW) 12 | 13 | //根据颜色返回图片 14 | + (UIImage *)imageWithColor:(UIColor *)color; 15 | 16 | //获取网络图片 17 | + (UIImage *)imageWithUrlString:(NSString *)urlString; 18 | 19 | //绘制图片圆角 20 | - (UIImage *)drawCornerInRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/UIImage+HW.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+HW.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "UIImage+HW.h" 10 | 11 | @implementation UIImage (HW) 12 | 13 | //根据颜色返回图片 14 | + (UIImage *)imageWithColor:(UIColor *)color 15 | { 16 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 17 | UIGraphicsBeginImageContext(rect.size); 18 | CGContextRef context = UIGraphicsGetCurrentContext(); 19 | CGContextSetFillColorWithColor(context, [color CGColor]); 20 | CGContextFillRect(context, rect); 21 | 22 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 23 | UIGraphicsEndImageContext(); 24 | 25 | return theImage; 26 | } 27 | 28 | //获取网络图片 29 | + (UIImage *)imageWithUrlString:(NSString *)urlString 30 | { 31 | NSURL *url = [NSURL URLWithString:urlString]; 32 | 33 | NSData *date = [NSData dataWithContentsOfURL:url]; 34 | 35 | UIImage *image = [UIImage imageWithData:date]; 36 | 37 | return image; 38 | } 39 | 40 | //绘制图片圆角 41 | - (UIImage *)drawCornerInRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius 42 | { 43 | UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; 44 | UIGraphicsBeginImageContextWithOptions(rect.size, false, [UIScreen mainScreen].scale); 45 | CGContextAddPath(UIGraphicsGetCurrentContext(), bezierPath.CGPath); 46 | CGContextClip(UIGraphicsGetCurrentContext()); 47 | [self drawInRect:rect]; 48 | 49 | CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke); 50 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 51 | UIGraphicsEndImageContext(); 52 | 53 | return image; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/UIView+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Extension) 12 | 13 | @property (nonatomic, assign) CGFloat frameX; 14 | @property (nonatomic, assign) CGFloat frameY; 15 | @property (nonatomic, assign) CGFloat frameWidth; 16 | @property (nonatomic, assign) CGFloat frameHeight; 17 | @property (nonatomic, assign) CGPoint frameOrigin; 18 | @property (nonatomic, assign) CGSize frameSize; 19 | @property (nonatomic, assign) CGFloat boundsX; 20 | @property (nonatomic, assign) CGFloat boundsY; 21 | @property (nonatomic, assign) CGFloat boundsWidth; 22 | @property (nonatomic, assign) CGFloat boundsHeight; 23 | @property (nonatomic, assign) CGFloat centerX; 24 | @property (nonatomic, assign) CGFloat centerY; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /HWDownloadDemo/Categorys/UIView+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "UIView+Extension.h" 10 | 11 | @implementation UIView (Extension) 12 | 13 | - (CGFloat)frameX 14 | { 15 | return self.frame.origin.x; 16 | } 17 | 18 | - (void)setFrameX:(CGFloat)newX 19 | { 20 | self.frame = CGRectMake(newX, self.frame.origin.y, self.frame.size.width, self.frame.size.height); 21 | } 22 | 23 | - (CGFloat)frameY 24 | { 25 | return self.frame.origin.y; 26 | } 27 | 28 | - (void)setFrameY:(CGFloat)newY 29 | { 30 | self.frame = CGRectMake(self.frame.origin.x, newY, self.frame.size.width, self.frame.size.height); 31 | } 32 | 33 | - (CGFloat)frameWidth 34 | { 35 | return self.frame.size.width; 36 | } 37 | 38 | - (void)setFrameWidth:(CGFloat)newWidth 39 | { 40 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, newWidth, self.frame.size.height); 41 | } 42 | 43 | - (CGFloat)frameHeight 44 | { 45 | return self.frame.size.height; 46 | } 47 | 48 | - (void)setFrameHeight:(CGFloat)newHeight 49 | { 50 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, newHeight); 51 | } 52 | 53 | - (CGPoint)frameOrigin 54 | { 55 | return self.frame.origin; 56 | } 57 | 58 | - (void)setFrameOrigin:(CGPoint)newOrigin 59 | { 60 | self.frame = CGRectMake(newOrigin.x, newOrigin.y, self.frame.size.width, self.frame.size.height); 61 | } 62 | 63 | - (CGSize)frameSize 64 | { 65 | return self.frame.size; 66 | } 67 | 68 | - (void)setFrameSize:(CGSize)newSize 69 | { 70 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, newSize.width, newSize.height); 71 | } 72 | 73 | - (CGFloat)boundsX 74 | { 75 | return self.bounds.origin.x; 76 | } 77 | 78 | - (void)setBoundsX:(CGFloat)newX 79 | { 80 | self.bounds = CGRectMake(newX, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height); 81 | } 82 | 83 | - (CGFloat)boundsY 84 | { 85 | return self.bounds.origin.y; 86 | } 87 | 88 | - (void)setBoundsY:(CGFloat)newY 89 | { 90 | self.bounds = CGRectMake(self.bounds.origin.x, newY, self.bounds.size.width, self.bounds.size.height); 91 | } 92 | 93 | - (CGFloat)boundsWidth 94 | { 95 | return self.bounds.size.width; 96 | } 97 | 98 | - (void)setBoundsWidth:(CGFloat)newWidth 99 | { 100 | self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, newWidth, self.bounds.size.height); 101 | } 102 | 103 | - (CGFloat)boundsHeight 104 | { 105 | return self.bounds.size.height; 106 | } 107 | 108 | - (void)setBoundsHeight:(CGFloat)newHeight 109 | { 110 | self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, newHeight); 111 | } 112 | 113 | - (CGFloat)centerX 114 | { 115 | return self.center.x; 116 | } 117 | 118 | - (void)setCenterX:(CGFloat)newX 119 | { 120 | self.center = CGPointMake(newX, self.center.y); 121 | } 122 | 123 | - (CGFloat)centerY 124 | { 125 | return self.center.y; 126 | } 127 | 128 | - (void)setCenterY:(CGFloat)newY 129 | { 130 | self.center = CGPointMake(self.center.x, newY); 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Common/.DS_Store -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/HWDataBaseManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWDataBaseManager.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/25. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_OPTIONS(NSUInteger, HWDBUpdateOption) { 12 | HWDBUpdateOptionState = 1 << 0, // 更新状态 13 | HWDBUpdateOptionLastStateTime = 1 << 1, // 更新状态最后改变的时间 14 | HWDBUpdateOptionResumeData = 1 << 2, // 更新下载的数据 15 | HWDBUpdateOptionProgressData = 1 << 3, // 更新进度数据(包含tmpFileSize、totalFileSize、progress、intervalFileSize、lastSpeedTime) 16 | HWDBUpdateOptionAllParam = 1 << 4 // 更新全部数据 17 | }; 18 | 19 | @interface HWDataBaseManager : NSObject 20 | 21 | // 获取单例 22 | + (instancetype)shareManager; 23 | 24 | // 插入数据 25 | - (void)insertModel:(HWDownloadModel *)model; 26 | 27 | // 获取数据 28 | - (HWDownloadModel *)getModelWithUrl:(NSString *)url; // 根据url获取数据 29 | - (HWDownloadModel *)getWaitingModel; // 获取第一条等待的数据 30 | - (HWDownloadModel *)getLastDownloadingModel; // 获取最后一条正在下载的数据 31 | - (NSArray *)getAllCacheData; // 获取所有数据 32 | - (NSArray *)getAllDownloadingData; // 根据lastStateTime倒叙获取所有正在下载的数据 33 | - (NSArray *)getAllDownloadedData; // 获取所有下载完成的数据 34 | - (NSArray *)getAllUnDownloadedData; // 获取所有未下载完成的数据(包含正在下载、等待、暂停、错误) 35 | - (NSArray *)getAllWaitingData; // 获取所有等待下载的数据 36 | 37 | // 更新数据 38 | - (void)updateWithModel:(HWDownloadModel *)model option:(HWDBUpdateOption)option; 39 | 40 | // 删除数据 41 | - (void)deleteModelWithUrl:(NSString *)url; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/HWDownload.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownload.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/24. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #ifndef HWDownload_h 10 | #define HWDownload_h 11 | 12 | #import "HWDownloadManager.h" 13 | #import "HWDataBaseManager.h" 14 | #import "HWDownloadModel.h" 15 | 16 | #endif /* HWDownload_h */ 17 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/HWDownloadManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadManager.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/24. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class HWDownloadModel; 12 | 13 | typedef NS_ENUM(NSInteger, HWDownloadState) { 14 | HWDownloadStateDefault = 0, // 默认 15 | HWDownloadStateDownloading, // 正在下载 16 | HWDownloadStateWaiting, // 等待 17 | HWDownloadStatePaused, // 暂停 18 | HWDownloadStateFinish, // 完成 19 | HWDownloadStateError, // 错误 20 | }; 21 | 22 | @interface HWDownloadManager : NSObject 23 | 24 | // 初始化下载单例,若之前程序杀死时有正在下的任务,会自动恢复下载 25 | + (instancetype)shareManager; 26 | 27 | // 开始下载 28 | - (void)startDownloadTask:(HWDownloadModel *)model; 29 | 30 | // 暂停下载 31 | - (void)pauseDownloadTask:(HWDownloadModel *)model; 32 | 33 | // 删除下载任务及本地缓存 34 | - (void)deleteTaskAndCache:(HWDownloadModel *)model; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/HWDownloadModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadModel.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/24. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class FMResultSet; 12 | 13 | @interface HWDownloadModel : NSObject 14 | 15 | @property (nonatomic, copy) NSString *localPath; // 下载完成路径 16 | @property (nonatomic, copy) NSString *vid; // 文件唯一id标识 17 | @property (nonatomic, copy) NSString *fileName; // 文件名 18 | @property (nonatomic, copy) NSString *url; // url 19 | @property (nonatomic, strong) NSData *resumeData; // 下载的数据 20 | @property (nonatomic, assign) CGFloat progress; // 下载进度 21 | @property (nonatomic, assign) HWDownloadState state; // 下载状态 22 | @property (nonatomic, assign) NSUInteger totalFileSize; // 文件总大小 23 | @property (nonatomic, assign) NSUInteger tmpFileSize; // 下载大小 24 | @property (nonatomic, assign) NSUInteger speed; // 下载速度 25 | @property (nonatomic, assign) NSTimeInterval lastSpeedTime; // 上次计算速度时的时间戳 26 | @property (nonatomic, assign) NSUInteger intervalFileSize; // 计算速度时间内下载文件的大小 27 | @property (nonatomic, assign) NSUInteger lastStateTime; // 记录任务加入准备下载的时间(点击默认、暂停、失败状态),用于计算开始、停止任务的先后顺序 28 | 29 | // 根据数据库查询结果初始化 30 | - (instancetype)initWithFMResultSet:(FMResultSet *)resultSet; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/HWDownloadModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadModel.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/24. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWDownloadModel.h" 10 | 11 | @implementation HWDownloadModel 12 | 13 | - (NSString *)localPath 14 | { 15 | if (!_localPath) { 16 | NSString *fileName = [_url substringFromIndex:[_url rangeOfString:@"/" options:NSBackwardsSearch].location + 1]; 17 | NSString *str = [NSString stringWithFormat:@"%@_%@", _vid, fileName]; 18 | _localPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:str]; 19 | } 20 | 21 | return _localPath; 22 | } 23 | 24 | - (instancetype)initWithFMResultSet:(FMResultSet *)resultSet 25 | { 26 | if (!resultSet) return nil; 27 | 28 | _vid = [NSString stringWithFormat:@"%@", [resultSet objectForColumn:@"vid"]]; 29 | _url = [NSString stringWithFormat:@"%@", [resultSet objectForColumn:@"url"]]; 30 | _fileName = [NSString stringWithFormat:@"%@", [resultSet objectForColumn:@"fileName"]]; 31 | _totalFileSize = [[resultSet objectForColumn:@"totalFileSize"] integerValue]; 32 | _tmpFileSize = [[resultSet objectForColumn:@"tmpFileSize"] integerValue]; 33 | _progress = [[resultSet objectForColumn:@"progress"] floatValue]; 34 | _state = [[resultSet objectForColumn:@"state"] integerValue]; 35 | _lastSpeedTime = [resultSet doubleForColumn:@"lastSpeedTime"]; 36 | _intervalFileSize = [[resultSet objectForColumn:@"intervalFileSize"] integerValue]; 37 | _lastStateTime = [[resultSet objectForColumn:@"lastStateTime"] integerValue]; 38 | _resumeData = [resultSet dataForColumn:@"resumeData"]; 39 | 40 | return self; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/NSURLSession+CorrectedResumeData.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLSession+CorrectedResumeData.h 3 | // HWDownloadDemo 4 | // 5 | // Created by wangqibin on 2018/5/25. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 用于修复iOS 10.0、10.1系统暂停后继续下载错误问题 8 | 9 | #import 10 | 11 | @interface NSURLSession (CorrectedResumeData) 12 | 13 | - (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWDownloadManager/NSURLSession+CorrectedResumeData.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLSession+CorrectedResumeData.m 3 | // HWDownloadDemo 4 | // 5 | // Created by wangqibin on 2018/5/25. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #import "NSURLSession+CorrectedResumeData.h" 10 | 11 | static NSString *const resumeCurrentRequest = @"NSURLSessionResumeCurrentRequest"; 12 | static NSString *const resumeOriginalRequest = @"NSURLSessionResumeOriginalRequest"; 13 | 14 | @implementation NSURLSession (CorrectedResumeData) 15 | 16 | - (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData 17 | { 18 | NSData *data = [self getCorrectResumeDataWithData:resumeData]; 19 | data = data ? data : resumeData; 20 | NSURLSessionDownloadTask *task = [self downloadTaskWithResumeData:data]; 21 | NSMutableDictionary *resumeDic = [self getResumeDictionaryWithData:data]; 22 | 23 | if (resumeDic) { 24 | if (!task.originalRequest) { 25 | NSData *originalReqData = resumeDic[resumeOriginalRequest]; 26 | NSURLRequest *originalRequest = [NSKeyedUnarchiver unarchiveObjectWithData:originalReqData]; 27 | if (originalRequest) [task setValue:originalRequest forKey:@"originalRequest"]; 28 | } 29 | if (!task.currentRequest) { 30 | NSData *currentReqData = resumeDic[resumeCurrentRequest]; 31 | NSURLRequest *currentRequest = [NSKeyedUnarchiver unarchiveObjectWithData:currentReqData]; 32 | if (currentRequest) [task setValue:currentRequest forKey:@"currentRequest"]; 33 | } 34 | } 35 | 36 | return task; 37 | } 38 | 39 | - (NSData *)getCorrectResumeDataWithData:(NSData *)data 40 | { 41 | if (!data) return nil; 42 | 43 | NSMutableDictionary *resumeDictionary = [self getResumeDictionaryWithData:data]; 44 | if (!resumeDictionary) return nil; 45 | 46 | resumeDictionary[resumeCurrentRequest] = [self getCorrectRequestDataWithData:resumeDictionary[resumeCurrentRequest]]; 47 | resumeDictionary[resumeOriginalRequest] = [self getCorrectRequestDataWithData:resumeDictionary[resumeOriginalRequest]]; 48 | 49 | return [NSPropertyListSerialization dataWithPropertyList:resumeDictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nil]; 50 | } 51 | 52 | - (NSMutableDictionary *)getResumeDictionaryWithData:(NSData *)data 53 | { 54 | return [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil]; 55 | } 56 | 57 | - (NSData *)getCorrectRequestDataWithData:(NSData *)data 58 | { 59 | if (!data) return nil; 60 | 61 | if ([NSKeyedUnarchiver unarchiveObjectWithData:data]) return data; 62 | 63 | NSMutableDictionary *archive = [[NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil] mutableCopy]; 64 | if (!archive) return nil; 65 | 66 | NSInteger i = 0; 67 | id objectss = archive[@"$objects"]; 68 | while ([objectss[1] objectForKey:[NSString stringWithFormat:@"$%ld", i]]) { 69 | i++; 70 | } 71 | 72 | NSInteger j = 0; 73 | while ([archive[@"$objects"][1] objectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld", j]]) { 74 | NSMutableArray *array = archive[@"$objects"]; 75 | NSMutableDictionary *dic = array[1]; 76 | id obj = [dic objectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld", j]]; 77 | if (obj) { 78 | [dic setValue:obj forKey:[NSString stringWithFormat:@"$%ld", i + j]]; 79 | [dic removeObjectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld", j]]; 80 | [array replaceObjectAtIndex:1 withObject:dic]; 81 | archive[@"$objects"] = array; 82 | } 83 | j++; 84 | } 85 | 86 | if ([archive[@"$objects"][1] objectForKey:@"__nsurlrequest_proto_props"]) { 87 | NSMutableArray *array = archive[@"$objects"]; 88 | NSMutableDictionary *dic = array[1]; 89 | id obj = [dic objectForKey:@"__nsurlrequest_proto_props"]; 90 | if (obj) { 91 | [dic setValue:obj forKey:[NSString stringWithFormat:@"$%ld", i + j]]; 92 | [dic removeObjectForKey:@"__nsurlrequest_proto_props"]; 93 | [array replaceObjectAtIndex:1 withObject:dic]; 94 | archive[@"$objects"] = array; 95 | } 96 | } 97 | 98 | if ([archive[@"$top"] objectForKey:@"NSKeyedArchiveRootObjectKey"]) { 99 | [archive[@"$top"] setObject:archive[@"$top"][@"NSKeyedArchiveRootObjectKey"] forKey: NSKeyedArchiveRootObjectKey]; 100 | [archive[@"$top"] removeObjectForKey:@"NSKeyedArchiveRootObjectKey"]; 101 | } 102 | 103 | return [NSPropertyListSerialization dataWithPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil]; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWNetworkReachabilityManager.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/5/18. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "AFNetworkReachabilityManager.h" 10 | 11 | @interface HWNetworkReachabilityManager : NSObject 12 | 13 | // 当前网络状态 14 | @property (nonatomic, assign, readonly) AFNetworkReachabilityStatus networkReachabilityStatus; 15 | 16 | // 获取单例 17 | + (instancetype)shareManager; 18 | 19 | // 监听网络状态 20 | - (void)monitorNetworkStatus; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWNetworkReachabilityManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWNetworkReachabilityManager.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/5/18. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWNetworkReachabilityManager.h" 10 | 11 | @interface HWNetworkReachabilityManager () 12 | 13 | @property (nonatomic, assign, readwrite) AFNetworkReachabilityStatus networkReachabilityStatus; 14 | 15 | @end 16 | 17 | @implementation HWNetworkReachabilityManager 18 | 19 | + (instancetype)shareManager 20 | { 21 | static HWNetworkReachabilityManager *manager = nil; 22 | 23 | static dispatch_once_t onceToken; 24 | dispatch_once(&onceToken, ^{ 25 | manager = [[self alloc] init]; 26 | }); 27 | 28 | return manager; 29 | } 30 | 31 | // 监听网络状态 32 | - (void)monitorNetworkStatus 33 | { 34 | // 创建网络监听者 35 | AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; 36 | 37 | [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { 38 | switch (status) { 39 | case AFNetworkReachabilityStatusUnknown: 40 | // 未知网络 41 | HWLog(@"当前网络:未知网络"); 42 | break; 43 | 44 | case AFNetworkReachabilityStatusNotReachable: 45 | // 无网络 46 | HWLog(@"当前网络:无网络"); 47 | break; 48 | 49 | case AFNetworkReachabilityStatusReachableViaWWAN: 50 | // 蜂窝数据 51 | HWLog(@"当前网络:蜂窝数据"); 52 | break; 53 | 54 | case AFNetworkReachabilityStatusReachableViaWiFi: 55 | // 无线网络 56 | HWLog(@"当前网络:无线网络"); 57 | break; 58 | 59 | default: 60 | break; 61 | } 62 | 63 | if (_networkReachabilityStatus != status) { 64 | _networkReachabilityStatus = status; 65 | // 网络改变通知 66 | [[NSNotificationCenter defaultCenter] postNotificationName:HWNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithInteger:status]]; 67 | } 68 | }]; 69 | 70 | // 开始监听 71 | [manager startMonitoring]; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWProgressHUD.h 3 | // HWProgressHUD 4 | // 5 | // Created by sxmaps_w on 2017/4/21. 6 | // Copyright © 2017年 wqb. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWProgressHUD : UIView 12 | 13 | // 显示转圈加载,调用dismiss、showMessage等方法隐藏,常用于已有视图上提交加载数据 14 | + (void)show; 15 | 16 | // 显示加载,在特定视图 17 | + (void)showInView:(UIView *)view; 18 | 19 | // 空页面显示加载动画,常用于未创建视图时加载数据,创建控件 20 | + (void)showWhilePushing; 21 | 22 | // 加载动画,传YES显示空页面显示加载动画,传NO显示转圈加载动画 23 | + (void)showWhilePushing:(BOOL)pushing; 24 | 25 | // 显示文字,默认两秒后消失 26 | + (void)showMessage:(NSString *)message; 27 | 28 | // 显示文字,默认两秒后消失,在特定视图 29 | + (void)showMessage:(NSString *)message inView:(UIView *)view; 30 | 31 | // 显示文字,设置显示时长 32 | + (void)showMessage:(NSString *)message duration:(NSTimeInterval)duration; 33 | 34 | // 显示文字,设置显示时长,在特定视图 35 | + (void)showMessage:(NSString *)message duration:(NSTimeInterval)duration inView:(UIView *)view; 36 | 37 | // 隐藏 38 | + (void)dismiss; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/HWToolBox.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWToolBox.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWToolBox : NSObject 12 | 13 | // 根据字节大小返回文件大小字符KB、MB 14 | + (NSString *)stringFromByteCount:(long long)byteCount; 15 | 16 | // 时间转换为时间戳 17 | + (NSTimeInterval)getTimeStampWithDate:(NSDate *)date; 18 | 19 | // 时间戳转换为时间 20 | + (NSDate *)getDateWithTimeStamp:(NSTimeInterval)timeStamp; 21 | 22 | // 一个时间戳与当前时间的间隔(s) 23 | + (NSInteger)getIntervalsWithTimeStamp:(NSTimeInterval)timeStamp; 24 | 25 | //获得当前设备型号 26 | + (NSString *)getCurrentDeviceModel; 27 | 28 | //通过view获取控制器 29 | + (UIViewController *)findViewController:(UIView *)view; 30 | 31 | //获取当前控制器 32 | + (UIViewController *)getCurrentVC; 33 | 34 | //删除path路径下的文件 35 | + (void)clearCachesWithFilePath:(NSString *)path; 36 | 37 | //获取沙盒Library的文件目录 38 | + (NSString *)LibraryDirectory; 39 | 40 | //获取沙盒Document的文件目录 41 | + (NSString *)DocumentDirectory; 42 | 43 | //获取沙盒Preference的文件目录 44 | + (NSString *)PreferencePanesDirectory; 45 | 46 | // 获取沙盒Caches的文件目录 47 | + (NSString *)CachesDirectory; 48 | 49 | //验证是否是纯数字 50 | + (BOOL)isAllNumber:(NSString *)number; 51 | 52 | //验证手机号码 53 | + (BOOL)isMobileNumber:(NSString *)mobileNum; 54 | 55 | //验证身份证号码 56 | + (BOOL)isIdentityCardNumber:(NSString *)number; 57 | 58 | //验证香港身份证号码 59 | + (BOOL)isIdentityHKCardNumber:(NSString *)number; 60 | 61 | //验证密码格式(包含大写、小写、数字) 62 | + (BOOL)isConformSXPassword:(NSString *)password; 63 | 64 | //验证护照 65 | + (BOOL)isPassportNumber:(NSString *)number; 66 | 67 | //计算文字的长度 68 | + (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize; 69 | 70 | //去掉小数点后无效的零 71 | + (NSString *)deleteFailureZero:(NSString *)string; 72 | 73 | //得到中英文混合字符串长度 74 | + (int)lengthForText:(NSString *)text; 75 | 76 | //提示弹窗 77 | + (void)showAlertWithTitle:(NSString *)title sureMessage:(NSString *)sureMessage cancelMessage:(NSString *)cancelMessage warningMessage:(NSString *)warningMessage style:(UIAlertControllerStyle)UIAlertControllerStyle target:(id)target sureHandler:(void(^)(UIAlertAction *action))sureHandler cancelHandler:(void(^)(UIAlertAction *action))cancelHandler warningHandler:(void(^)(UIAlertAction *action))warningHandler; 78 | 79 | //获取当前时间 80 | + (NSString *)currentTime; 81 | 82 | // 获取当前时间(时分秒毫秒) 83 | + (NSString *)currentTimeCorrectToMillisecond; 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /HWDownloadDemo/Common/SwizzlingDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwizzlingDefine.h 3 | // SXEducation 4 | // 5 | // Created by sxmaps on 2017/10/19. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | #ifndef SwizzlingDefine_h 10 | #define SwizzlingDefine_h 11 | #import 12 | 13 | static inline void swizzling_exchangeMethod(Class clazz, SEL originalSelector, SEL swizzledSelector) { 14 | Method originalMethod = class_getInstanceMethod(clazz, originalSelector); 15 | Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector); 16 | 17 | BOOL success = class_addMethod(clazz, originalSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 18 | if (success) { 19 | class_replaceMethod(clazz, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 20 | } else { 21 | method_exchangeImplementations(originalMethod, swizzledMethod); 22 | } 23 | } 24 | 25 | #endif /* SwizzlingDefine_h */ 26 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/HWPlayVC/Controller/HWPlayVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWPlayVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/25. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWBaseViewController.h" 10 | 11 | @interface HWPlayVC : HWBaseViewController 12 | 13 | @property (nonatomic, strong) HWDownloadModel *model; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/HWPlayVC/Controller/HWPlayVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWPlayVC.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/25. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWPlayVC.h" 10 | #import 11 | 12 | @interface HWPlayVC () 13 | 14 | @property (nonatomic, strong) AVPlayer *player; 15 | 16 | @end 17 | 18 | @implementation HWPlayVC 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | self.navTitle = _model.fileName; 24 | 25 | [self creatControl]; 26 | } 27 | 28 | - (void)creatControl 29 | { 30 | // 进度条 31 | UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(50, KSuitFloat(400), KMainW - 100, 50)]; 32 | [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged]; 33 | [self.view addSubview:slider]; 34 | 35 | // 创建播放器 36 | _player = [AVPlayer playerWithPlayerItem:[AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:_model.localPath]]]; 37 | 38 | // 创建显示的图层 39 | AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player]; 40 | playerLayer.frame = CGRectMake(0, 0, KMainW, 400); 41 | [self.view.layer addSublayer:playerLayer]; 42 | 43 | // 播放视频 44 | [_player play]; 45 | 46 | // 进度回调 47 | weakify(self); 48 | [_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { 49 | strongify(weakSelf); 50 | // 刷新slider 51 | slider.value = CMTimeGetSeconds(time) / CMTimeGetSeconds(strongSelf.player.currentItem.duration); 52 | }]; 53 | } 54 | 55 | - (void)sliderValueChanged:(UISlider *)slider 56 | { 57 | // 计算时间 58 | float time = slider.value * CMTimeGetSeconds(_player.currentItem.duration); 59 | 60 | // 跳转到指定时间 61 | [_player seekToTime:CMTimeMake(time, 1.0)]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/Home/Controller/HWHomeVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWHomeVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWBaseViewController.h" 10 | 11 | @interface HWHomeVC : HWBaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/Home/Controller/HWHomeVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWHomeVC.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWHomeVC.h" 10 | #import "HWHomeCell.h" 11 | #import "HWPlayVC.h" 12 | 13 | @interface HWHomeVC () 14 | 15 | @property (nonatomic, strong) NSMutableArray *dataSource; 16 | @property (nonatomic, weak) UITableView *tableView; 17 | 18 | @end 19 | 20 | @implementation HWHomeVC 21 | 22 | - (NSMutableArray *)dataSource 23 | { 24 | if (!_dataSource) { 25 | _dataSource = [NSMutableArray array]; 26 | } 27 | 28 | return _dataSource; 29 | } 30 | 31 | - (void)viewDidLoad { 32 | [super viewDidLoad]; 33 | 34 | self.navTitle = @"首页"; 35 | 36 | // 创建控件 37 | [self creatControl]; 38 | 39 | // 添加通知 40 | [self addNotification]; 41 | } 42 | 43 | - (void)viewWillAppear:(BOOL)animated 44 | { 45 | [super viewWillAppear:animated]; 46 | 47 | // 获取网络数据 48 | [self getInfo]; 49 | 50 | // 获取缓存 51 | [self getCacheData]; 52 | } 53 | 54 | - (void)getInfo 55 | { 56 | // 模拟网络数据 57 | NSArray *testData = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"testData.plist" ofType:nil]]; 58 | 59 | // 转模型 60 | self.dataSource = [HWDownloadModel mj_objectArrayWithKeyValuesArray:testData]; 61 | } 62 | 63 | - (void)getCacheData 64 | { 65 | // 获取已缓存数据 66 | NSArray *cacheData = [[HWDataBaseManager shareManager] getAllCacheData]; 67 | 68 | // 这里是把本地缓存数据更新到网络请求的数据中,实际开发还是尽可能避免这样在两个地方取数据再整合 69 | for (int i = 0; i < self.dataSource.count; i++) { 70 | HWDownloadModel *model = self.dataSource[i]; 71 | for (HWDownloadModel *downloadModel in cacheData) { 72 | if ([model.url isEqualToString:downloadModel.url]) { 73 | self.dataSource[i] = downloadModel; 74 | break; 75 | } 76 | } 77 | } 78 | 79 | [_tableView reloadData]; 80 | } 81 | 82 | - (void)creatControl 83 | { 84 | // tableView 85 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(10, 0, KMainW - 20, KMainH - KNavHeight - KTabBarHeight)]; 86 | tableView.showsVerticalScrollIndicator = NO; 87 | tableView.dataSource = self; 88 | tableView.delegate = self; 89 | tableView.rowHeight = 80.f; 90 | tableView.sectionHeaderHeight = 5.f; 91 | tableView.sectionFooterHeight = 5.f; 92 | tableView.backgroundColor = KWhiteColor; 93 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 94 | [self.view addSubview:tableView]; 95 | _tableView = tableView; 96 | } 97 | 98 | - (void)addNotification 99 | { 100 | // 进度通知 101 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downLoadProgress:) name:HWDownloadProgressNotification object:nil]; 102 | // 状态改变通知 103 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downLoadStateChange:) name:HWDownloadStateChangeNotification object:nil]; 104 | } 105 | 106 | #pragma mark - UITableViewDataSource 107 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 108 | { 109 | return self.dataSource.count; 110 | } 111 | 112 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 113 | { 114 | HWHomeCell *cell = [HWHomeCell cellWithTableView:tableView]; 115 | 116 | cell.model = self.dataSource[indexPath.row]; 117 | 118 | return cell; 119 | } 120 | 121 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 122 | { 123 | HWDownloadModel *model = self.dataSource[indexPath.row]; 124 | 125 | if (model.state == HWDownloadStateFinish) { 126 | HWPlayVC *vc = [[HWPlayVC alloc] init]; 127 | vc.model = model; 128 | [self.navigationController pushViewController:vc animated:YES]; 129 | } 130 | } 131 | 132 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 133 | { 134 | UIView *view = [[UIView alloc] init]; 135 | view.backgroundColor = KClearColor; 136 | 137 | return view; 138 | } 139 | 140 | - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 141 | { 142 | UIView *view = [[UIView alloc] init]; 143 | view.backgroundColor = KClearColor; 144 | 145 | return view; 146 | } 147 | 148 | #pragma mark - HWDownloadNotification 149 | // 正在下载,进度回调 150 | - (void)downLoadProgress:(NSNotification *)notification 151 | { 152 | HWDownloadModel *downloadModel = notification.object; 153 | 154 | [self.dataSource enumerateObjectsUsingBlock:^(HWDownloadModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 155 | if ([model.url isEqualToString:downloadModel.url]) { 156 | // 主线程更新cell进度 157 | dispatch_async(dispatch_get_main_queue(), ^{ 158 | HWHomeCell *cell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:0]]; 159 | [cell updateViewWithModel:downloadModel]; 160 | }); 161 | 162 | *stop = YES; 163 | } 164 | }]; 165 | } 166 | 167 | // 状态改变 168 | - (void)downLoadStateChange:(NSNotification *)notification 169 | { 170 | HWDownloadModel *downloadModel = notification.object; 171 | 172 | [self.dataSource enumerateObjectsUsingBlock:^(HWDownloadModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 173 | if ([model.url isEqualToString:downloadModel.url]) { 174 | // 更新数据源 175 | self.dataSource[idx] = downloadModel; 176 | 177 | // 主线程刷新cell 178 | dispatch_async(dispatch_get_main_queue(), ^{ 179 | [_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationNone]; 180 | }); 181 | 182 | *stop = YES; 183 | } 184 | }]; 185 | } 186 | 187 | - (void)dealloc 188 | { 189 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 190 | } 191 | 192 | @end 193 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/Home/View/HWDownloadButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadButton.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/24. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWDownloadButton : UIView 12 | 13 | @property (nonatomic, strong) HWDownloadModel *model; // 数据模型 14 | @property (nonatomic, assign) HWDownloadState state; // 下载状态 15 | @property (nonatomic, assign) CGFloat progress; // 下载进度 16 | 17 | // 添加点击方法 18 | - (void)addTarget:(id)target action:(SEL)action; 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/Home/View/HWDownloadButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadButton.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/24. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWDownloadButton.h" 10 | 11 | @interface HWDownloadButton () { 12 | id _target; 13 | SEL _action; 14 | } 15 | 16 | @property (nonatomic, weak) UILabel *proLabel; // 进度标签 17 | @property (nonatomic, weak) UIImageView *imgView; // 状态视图 18 | 19 | @end 20 | 21 | @implementation HWDownloadButton 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame 24 | { 25 | if (self = [super initWithFrame:frame]) { 26 | self.backgroundColor = KWhiteColor; 27 | 28 | // 百分比标签 29 | UILabel *proLabel = [[UILabel alloc] initWithFrame:self.bounds]; 30 | proLabel.font = [UIFont boldSystemFontOfSize:15.0f]; 31 | proLabel.textColor = [UIColor colorWithRed:0/255.0 green:191/255.0 blue:255/255.0 alpha:1]; 32 | proLabel.textAlignment = NSTextAlignmentCenter; 33 | [self addSubview:proLabel]; 34 | _proLabel = proLabel; 35 | 36 | // 状态视图 37 | UIImageView *imgView = [[UIImageView alloc] initWithFrame:self.bounds]; 38 | imgView.backgroundColor = KWhiteColor; 39 | imgView.image = [UIImage imageNamed:@"com_download_default"]; 40 | [self addSubview:imgView]; 41 | _imgView = imgView; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (void)setProgress:(CGFloat)progress 48 | { 49 | _progress = progress; 50 | 51 | _proLabel.text = [NSString stringWithFormat:@"%d%%", (int)floor(progress * 100)]; 52 | 53 | [self setNeedsDisplay]; 54 | } 55 | 56 | - (void)drawRect:(CGRect)rect 57 | { 58 | CGFloat lineWidth = 3.f; 59 | 60 | UIBezierPath *path = [[UIBezierPath alloc] init]; 61 | path.lineWidth = lineWidth; 62 | [_proLabel.textColor set]; 63 | path.lineCapStyle = kCGLineCapRound; 64 | path.lineJoinStyle = kCGLineJoinRound; 65 | CGFloat radius = (MIN(rect.size.width, rect.size.height) - lineWidth) * 0.5; 66 | // 画弧(参数:中心、半径、起始角度(3点钟方向为0)、结束角度、是否顺时针) 67 | [path addArcWithCenter:(CGPoint){rect.size.width * 0.5, rect.size.height * 0.5} radius:radius startAngle:M_PI * 1.5 endAngle:M_PI * 1.5 + M_PI * 2 * _progress clockwise:YES]; 68 | [path stroke]; 69 | } 70 | 71 | - (void)setModel:(HWDownloadModel *)model 72 | { 73 | _model = model; 74 | 75 | self.state = model.state; 76 | } 77 | 78 | - (void)setState:(HWDownloadState)state 79 | { 80 | _imgView.hidden = state == HWDownloadStateDownloading; 81 | _proLabel.hidden = !_imgView.hidden; 82 | 83 | switch (state) { 84 | case HWDownloadStateDefault: 85 | _imgView.image = [UIImage imageNamed:@"com_download_default"]; 86 | break; 87 | 88 | case HWDownloadStateDownloading: 89 | break; 90 | 91 | case HWDownloadStateWaiting: 92 | _imgView.image = [UIImage imageNamed:@"com_download_waiting"]; 93 | break; 94 | 95 | case HWDownloadStatePaused: 96 | _imgView.image = [UIImage imageNamed:@"com_download_pause"]; 97 | break; 98 | 99 | case HWDownloadStateFinish: 100 | _imgView.image = [UIImage imageNamed:@"com_download_finish"]; 101 | break; 102 | 103 | case HWDownloadStateError: 104 | _imgView.image = [UIImage imageNamed:@"com_download_error"]; 105 | break; 106 | 107 | default: 108 | break; 109 | } 110 | 111 | _state = state; 112 | } 113 | 114 | - (void)addTarget:(id)target action:(SEL)action 115 | { 116 | _target = target; 117 | _action = action; 118 | } 119 | 120 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 121 | { 122 | if (_state == HWDownloadStateDefault || _state == HWDownloadStatePaused || _state == HWDownloadStateError) { 123 | // 点击默认、暂停、失败状态,调用开始下载 124 | [[HWDownloadManager shareManager] startDownloadTask:_model]; 125 | 126 | }else if (_state == HWDownloadStateDownloading || _state == HWDownloadStateWaiting) { 127 | // 点击正在下载、等待状态,调用暂停下载 128 | [[HWDownloadManager shareManager] pauseDownloadTask:_model]; 129 | } 130 | 131 | if (!_target || !_action) return; 132 | ((void (*)(id, SEL, id))[_target methodForSelector:_action])(_target, _action, self); 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/Home/View/HWHomeCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWHomeCell.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/23. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWHomeCell : UITableViewCell 12 | 13 | @property (nonatomic, strong) HWDownloadModel *model; 14 | 15 | + (instancetype)cellWithTableView:(UITableView *)tabelView; 16 | 17 | // 更新视图 18 | - (void)updateViewWithModel:(HWDownloadModel *)model; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /HWDownloadDemo/Home/Home/View/HWHomeCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWHomeCell.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/23. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWHomeCell.h" 10 | #import "HWDownloadButton.h" 11 | 12 | @interface HWHomeCell () 13 | 14 | @property (nonatomic, weak) UILabel *titleLabel; // 标题 15 | @property (nonatomic, weak) UILabel *speedLabel; // 进度标签 16 | @property (nonatomic, weak) UILabel *fileSizeLabel; // 文件大小标签 17 | @property (nonatomic, weak) HWDownloadButton *downloadBtn; // 下载按钮 18 | 19 | @end 20 | 21 | @implementation HWHomeCell 22 | 23 | + (instancetype)cellWithTableView:(UITableView *)tabelView 24 | { 25 | static NSString *identifier = @"HWHomeCellIdentifier"; 26 | 27 | HWHomeCell *cell = [tabelView dequeueReusableCellWithIdentifier:identifier]; 28 | if (!cell) { 29 | cell = [[HWHomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; 30 | cell.selectionStyle = UITableViewCellSelectionStyleNone; 31 | cell.backgroundColor = KWhiteColor; 32 | 33 | // 选中时cell背景色 34 | UIView *backgroundViews = [[UIView alloc] initWithFrame:cell.frame]; 35 | backgroundViews.backgroundColor = [[UIColor colorWithHexString:@"#00CDCD"] colorWithAlphaComponent:0.5f]; 36 | [cell setSelectedBackgroundView:backgroundViews]; 37 | } 38 | 39 | return cell; 40 | } 41 | 42 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 43 | { 44 | if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 45 | // 底图 46 | CGFloat margin = 10.f; 47 | CGFloat backViewH = 70.f; 48 | UIView *backView = [[UIView alloc] initWithFrame:CGRectMake(0, margin * 0.5, KMainW - margin * 2, backViewH)]; 49 | backView.backgroundColor = [UIColor colorWithHexString:@"#00CDCD"]; 50 | [self.contentView addSubview:backView]; 51 | 52 | // 下载按钮 53 | CGFloat btnW = 50.f; 54 | HWDownloadButton *downloadBtn = [[HWDownloadButton alloc] initWithFrame:CGRectMake(backView.frameWidth - btnW - margin, (backViewH - btnW) * 0.5, btnW, btnW)]; 55 | [downloadBtn addTarget:self action:@selector(downBtnOnClick:)]; 56 | [backView addSubview:downloadBtn]; 57 | _downloadBtn = downloadBtn; 58 | 59 | // 标题 60 | UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(margin, 0, backView.frameWidth - margin * 3 - btnW, backViewH * 0.6)]; 61 | titleLabel.font = [UIFont boldSystemFontOfSize:18.f]; 62 | titleLabel.textColor = KWhiteColor; 63 | titleLabel.backgroundColor = backView.backgroundColor; 64 | titleLabel.layer.masksToBounds = YES; 65 | [backView addSubview:titleLabel]; 66 | _titleLabel = titleLabel; 67 | 68 | // 进度标签 69 | UILabel *speedLable = [[UILabel alloc] initWithFrame:CGRectMake(margin, CGRectGetMaxY(titleLabel.frame), titleLabel.frameWidth * 0.36, backViewH * 0.4)]; 70 | speedLable.font = [UIFont systemFontOfSize:14.f]; 71 | speedLable.textColor = KWhiteColor; 72 | speedLable.textAlignment = NSTextAlignmentRight; 73 | speedLable.backgroundColor = backView.backgroundColor; 74 | speedLable.layer.masksToBounds = YES; 75 | [backView addSubview:speedLable]; 76 | _speedLabel = speedLable; 77 | 78 | // 文件大小标签 79 | UILabel *fileSizeLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(speedLable.frame), CGRectGetMaxY(titleLabel.frame), titleLabel.frameWidth - speedLable.frameWidth, backViewH * 0.4)]; 80 | fileSizeLabel.font = [UIFont systemFontOfSize:14.f]; 81 | fileSizeLabel.textColor = KWhiteColor; 82 | fileSizeLabel.textAlignment = NSTextAlignmentRight; 83 | fileSizeLabel.backgroundColor = backView.backgroundColor; 84 | fileSizeLabel.layer.masksToBounds = YES; 85 | [backView addSubview:fileSizeLabel]; 86 | _fileSizeLabel = fileSizeLabel; 87 | } 88 | 89 | return self; 90 | } 91 | 92 | - (void)layoutSubviews 93 | { 94 | [super layoutSubviews]; 95 | 96 | NSArray *subviews = ISIOS11 ? self.superview.subviews : self.subviews; 97 | NSString *classString = ISIOS11 ? @"UISwipeActionPullView" : @"UITableViewCellDeleteConfirmationView"; 98 | for (UIView *view in subviews) { 99 | if ([view isKindOfClass:NSClassFromString(classString)]) { 100 | UIButton *deleteBtn = view.subviews.firstObject; 101 | view.backgroundColor = KClearColor; 102 | deleteBtn.frameY = 5; 103 | deleteBtn.frameHeight = 70; 104 | [deleteBtn setTitle:@"删除" forState:UIControlStateNormal]; 105 | break; 106 | } 107 | } 108 | } 109 | 110 | - (void)setModel:(HWDownloadModel *)model 111 | { 112 | _model = model; 113 | 114 | _downloadBtn.model = model; 115 | _titleLabel.text = model.fileName; 116 | [self updateViewWithModel:model]; 117 | } 118 | 119 | // 更新视图 120 | - (void)updateViewWithModel:(HWDownloadModel *)model 121 | { 122 | _downloadBtn.progress = model.progress; 123 | 124 | [self reloadLabelWithModel:model]; 125 | } 126 | 127 | // 刷新标签 128 | - (void)reloadLabelWithModel:(HWDownloadModel *)model 129 | { 130 | NSString *totalSize = [HWToolBox stringFromByteCount:model.totalFileSize]; 131 | NSString *tmpSize = [HWToolBox stringFromByteCount:model.tmpFileSize]; 132 | 133 | if (model.state == HWDownloadStateFinish) { 134 | _fileSizeLabel.text = [NSString stringWithFormat:@"%@", totalSize]; 135 | 136 | }else { 137 | _fileSizeLabel.text = [NSString stringWithFormat:@"%@ / %@", tmpSize, totalSize]; 138 | } 139 | _fileSizeLabel.hidden = model.totalFileSize == 0; 140 | 141 | if (model.speed > 0) { 142 | _speedLabel.text = [NSString stringWithFormat:@"%@ / s", [HWToolBox stringFromByteCount:model.speed]]; 143 | } 144 | _speedLabel.hidden = !(model.state == HWDownloadStateDownloading && model.totalFileSize > 0); 145 | } 146 | 147 | - (void)downBtnOnClick:(HWDownloadButton *)btn 148 | { 149 | // do something... 150 | } 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HWDownloadDemo 4 | // 5 | // Created by wangqibin on 2018/5/21. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @property (nonatomic, copy) void (^ backgroundSessionCompletionHandler)(void); // 后台所有下载任务完成回调 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HWDownloadDemo 4 | // 5 | // Created by wangqibin on 2018/5/21. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "HWTabBarController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 21 | self.window.backgroundColor = KWhiteColor; 22 | [self.window makeKeyAndVisible]; 23 | self.window.rootViewController = [[HWTabBarController alloc] init]; 24 | 25 | // 一次性代码 26 | [self projectOnceCode]; 27 | 28 | // 开启网络监听 29 | [[HWNetworkReachabilityManager shareManager] monitorNetworkStatus]; 30 | 31 | // 初始化下载单例,若之前程序杀死时有正在下的任务,会自动恢复下载 32 | [HWDownloadManager shareManager]; 33 | 34 | return YES; 35 | } 36 | 37 | // 应用处于后台,所有下载任务完成调用 38 | - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler 39 | { 40 | _backgroundSessionCompletionHandler = completionHandler; 41 | } 42 | 43 | // 一次性代码 44 | - (void)projectOnceCode 45 | { 46 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 47 | NSString *onceKey = @"HWProjectOnceKey"; 48 | if (![defaults boolForKey:onceKey]) { 49 | // 初始化下载最大并发数为1,不允许蜂窝网络下载 50 | [defaults setInteger:1 forKey:HWDownloadMaxConcurrentCountKey]; 51 | [defaults setBool:NO forKey:HWDownloadAllowsCellularAccessKey]; 52 | [defaults setBool:YES forKey:onceKey]; 53 | } 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/HWBaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWBaseViewController.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWBaseViewController : UIViewController 12 | 13 | // 导航栏标题 14 | @property (nonatomic, copy) NSString *navTitle; 15 | 16 | // 是否允许二级页面屏幕左侧右滑返回,默认允许 17 | @property (nonatomic, assign) BOOL isAllowScrollBack; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/HWBaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWBaseViewController.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/9. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWBaseViewController.h" 10 | #import "HWTabBarController.h" 11 | 12 | @interface HWBaseViewController () 13 | 14 | @end 15 | 16 | @implementation HWBaseViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | //默认视图背景色 22 | self.view.backgroundColor = KWhiteColor; 23 | 24 | //设置状态栏文字颜色为白色 25 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:NO]; 26 | 27 | //用以支持二级页面边缘右滑返回 28 | _isAllowScrollBack = YES; 29 | self.navigationController.interactivePopGestureRecognizer.delegate = (id)self; 30 | 31 | // 列表适配 32 | [self adaptiveView]; 33 | } 34 | 35 | - (void)viewWillAppear:(BOOL)animated 36 | { 37 | [super viewWillAppear:animated]; 38 | 39 | self.navigationController.interactivePopGestureRecognizer.enabled = _isAllowScrollBack; 40 | 41 | //一级页面显示tabBar 42 | if (self.navigationController.viewControllers.count == 1) { 43 | HWTabBarController *tabBarController = (HWTabBarController *)self.tabBarController; 44 | [tabBarController setTabBarShowWithAnimaition:YES]; 45 | } 46 | } 47 | 48 | //设置导航栏标题 49 | - (void)setNavTitle:(NSString *)navTitle 50 | { 51 | _navTitle = navTitle; 52 | 53 | self.navigationItem.title = _navTitle; 54 | } 55 | 56 | // 列表适配 57 | - (void)adaptiveView 58 | { 59 | self.automaticallyAdjustsScrollViewInsets = NO; 60 | [UITableView appearance].estimatedRowHeight = 0; 61 | [UITableView appearance].estimatedSectionHeaderHeight = 0; 62 | [UITableView appearance].estimatedSectionFooterHeight = 0; 63 | // iOS 11 解决SafeArea的问题,同时能解决pop时上级页面scrollView抖动的问题 64 | if (@available(iOS 11, *)) [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/NavigationController/HWNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWNavigationController.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol BackButtonHandlerProtocol 12 | 13 | @optional 14 | /** 15 | 导航栏返回按钮点击事件,默认返回上一级,如有特殊操作可调用此方法 16 | */ 17 | - (void)back; 18 | 19 | @end 20 | 21 | @interface UIViewController (customBackPopButton) 22 | 23 | @end 24 | 25 | @interface HWNavigationController : UINavigationController 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/NavigationController/HWNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWNavigationController.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWNavigationController.h" 10 | #import "HWTabBarController.h" 11 | 12 | @interface HWNavigationController () 13 | 14 | @end 15 | 16 | @implementation HWNavigationController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | UIImage *navBackImage = [UIImage imageWithColor:[UIColor colorWithHexString:@"#009ACD"]]; 22 | UINavigationBar *navBar = [UINavigationBar appearance]; 23 | [navBar setShadowImage:[[UIImage alloc] init]]; 24 | [navBar setBackgroundImage:navBackImage forBarMetrics:UIBarMetricsDefault]; 25 | } 26 | 27 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated 28 | { 29 | if (self.childViewControllers.count) { 30 | HWTabBarController *tabBarController = (HWTabBarController *)self.tabBarController; 31 | [tabBarController setTabBarHiddenWithAnimaition:YES]; 32 | 33 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 34 | [button setImage:[UIImage imageNamed:@"nav_back"] forState:UIControlStateNormal]; 35 | [button setImage:[UIImage imageNamed:@"nav_back"] forState:UIControlStateHighlighted]; 36 | [button sizeToFit]; 37 | [button addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; 38 | viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; 39 | } 40 | 41 | if (![[super topViewController] isKindOfClass:[viewController class]]) { 42 | [super pushViewController:viewController animated:animated]; 43 | } 44 | } 45 | 46 | - (void)back 47 | { 48 | if ([self.topViewController respondsToSelector:@selector(back)]) { 49 | [self.topViewController back]; 50 | 51 | } else { 52 | [self popViewControllerAnimated:YES]; 53 | } 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/NavigationController/UINavigationBar+Swizzling.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationBar+Swizzling.h 3 | // SXEducation 4 | // 5 | // Created by sxmaps on 2017/10/19. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface UINavigationBar (Swizzling) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/NavigationController/UINavigationBar+Swizzling.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationBar+Swizzling.m 3 | // SXEducation 4 | // 5 | // Created by sxmaps on 2017/10/19. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | #import "UINavigationBar+Swizzling.h" 10 | #import "SwizzlingDefine.h" 11 | 12 | @implementation UINavigationBar (Swizzling) 13 | 14 | + (void)load 15 | { 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | swizzling_exchangeMethod([UINavigationBar class], @selector(layoutSubviews), @selector(swizzling_layoutSubViews)); 19 | }); 20 | } 21 | 22 | - (void)swizzling_layoutSubViews 23 | { 24 | UINavigationItem *navgationItem = [self topItem]; 25 | 26 | if ([navgationItem.titleView isKindOfClass:[UILabel class]]) { 27 | UILabel *label = (UILabel *)navgationItem.titleView; 28 | UIFont *font = self.titleTextAttributes[NSFontAttributeName]; 29 | if (font) { 30 | label.font = font; 31 | } 32 | 33 | UIColor *color = self.titleTextAttributes[NSForegroundColorAttributeName]; 34 | if (color) { 35 | label.textColor = color; 36 | } 37 | 38 | [label sizeToFit]; 39 | } 40 | 41 | if (!ISIOS11) { 42 | [self layoutLabel]; 43 | } 44 | [self swizzling_layoutSubViews]; 45 | } 46 | 47 | - (void)layoutLabel 48 | { 49 | UINavigationItem *navigationItem = [self topItem]; 50 | UIView *view = navigationItem.titleView; 51 | view.centerX = self.frameWidth * .5f; 52 | view.centerY = self.frameHeight * .5f; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/NavigationController/UINavigationItem+Swizzling.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationItem+Swizzling.h 3 | // SXEducation 4 | // 5 | // Created by sxmaps on 2017/10/19. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface UINavigationItem (Swizzling) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/NavigationController/UINavigationItem+Swizzling.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationItem+Swizzling.m 3 | // SXEducation 4 | // 5 | // Created by sxmaps on 2017/10/19. 6 | // Copyright © 2017年 sxmaps. All rights reserved. 7 | // 8 | 9 | #import "UINavigationItem+Swizzling.h" 10 | #import "SwizzlingDefine.h" 11 | 12 | #define KTitleLabelFont [UIFont boldSystemFontOfSize:18.f] 13 | #define KTitleLabelTextColor [UIColor colorWithHexString:@"#ffffff"] 14 | 15 | @implementation UINavigationItem (Swizzling) 16 | 17 | + (void)load 18 | { 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | swizzling_exchangeMethod([UINavigationItem class], @selector(setTitle:), @selector(swizzling_setTitle:)); 22 | swizzling_exchangeMethod([UINavigationItem class], @selector(title), @selector(swizzling_title)); 23 | }); 24 | } 25 | 26 | - (void)swizzling_setTitle:(NSString *)title 27 | { 28 | UILabel *titleLabel = (UILabel *)self.titleView; 29 | if (!titleLabel) { 30 | titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 31 | self.titleView = titleLabel; 32 | } 33 | 34 | if ([titleLabel isKindOfClass:[UILabel class]]) { 35 | titleLabel.font = KTitleLabelFont; 36 | titleLabel.textColor = KTitleLabelTextColor; 37 | titleLabel.text = title; 38 | } 39 | 40 | [titleLabel.superview layoutSubviews]; 41 | } 42 | 43 | - (NSString *)swizzling_title 44 | { 45 | if ([self swizzling_title].length ) { 46 | return [self swizzling_title]; 47 | } 48 | 49 | UILabel *titleLabel = (UILabel *)self.titleView; 50 | if ([titleLabel isKindOfClass:[UILabel class]]) { 51 | titleLabel.font = KTitleLabelFont; 52 | titleLabel.textColor = KTitleLabelTextColor; 53 | 54 | return titleLabel.text; 55 | } 56 | 57 | return nil; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/TabBarController/HWTabBarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWTabBarController.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWTabBarController : UITabBarController 12 | 13 | //隐藏TabBar 14 | - (void)setTabBarHiddenWithAnimaition:(BOOL)annimation; 15 | 16 | //显示TabBar 17 | - (void)setTabBarShowWithAnimaition:(BOOL)annimation; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/TabBarController/HWTabBarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWTabBarController.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWTabBarController.h" 10 | #import "HWTabBarView.h" 11 | #import "HWNavigationController.h" 12 | 13 | @interface HWTabBarController () 14 | 15 | @property (nonatomic, weak) HWTabBarView *tabBarView; 16 | 17 | @end 18 | 19 | @implementation HWTabBarController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | //隐藏系统的tabbar 25 | self.tabBar.alpha = 0.0; 26 | 27 | [self creatControl]; 28 | 29 | [self addViewControllers]; 30 | } 31 | 32 | - (void)creatControl 33 | { 34 | //初始化tabBar视图 35 | HWTabBarView *tabBarView = [[HWTabBarView alloc] initWithFrame:(CGRect){0, KMainH - KTabBarHeight, KMainW, KTabBarHeight}]; 36 | tabBarView.delegate = self; 37 | [self.view addSubview:tabBarView]; 38 | _tabBarView = tabBarView; 39 | } 40 | 41 | - (void)addViewControllers 42 | { 43 | NSArray *classNameArray = @[@"HWHomeVC", @"HWMeVC"]; 44 | NSMutableArray *array = [NSMutableArray array]; 45 | 46 | for (int i = 0; i < classNameArray.count; i++) { 47 | UIViewController *vc = [[NSClassFromString(classNameArray[i]) alloc] init]; 48 | HWNavigationController *nav = [[HWNavigationController alloc] initWithRootViewController:vc]; 49 | [array addObject:nav]; 50 | } 51 | 52 | self.viewControllers = array; 53 | self.selectedIndex = 0; 54 | } 55 | 56 | #pragma mark - HWTabBarViewDelegate 57 | - (void)SKTabBarView:(HWTabBarView *)tabBarView didClickMenuButton:(UIButton *)button 58 | { 59 | //让所有button归位成非选中状态 60 | for (int i = 0; i < 3; i ++) { 61 | UIButton *btn = (UIButton *) [_tabBarView viewWithTag:i + 100]; 62 | [btn setSelected:NO]; 63 | } 64 | 65 | //设置当前按钮为选中状态 66 | button.selected = YES; 67 | 68 | //设置当前tabBarController的选中页面 69 | [self setSelectedIndex:button.tag - 100]; 70 | } 71 | 72 | //隐藏TabBar 73 | - (void)setTabBarHiddenWithAnimaition:(BOOL)annimation 74 | { 75 | [UIView animateWithDuration:annimation ? 0.25 : 0 animations:^{ 76 | _tabBarView.frame = CGRectMake(0, KMainH + KTabBarHeight, KMainW, KTabBarHeight); 77 | }]; 78 | } 79 | 80 | //显示TabBar 81 | - (void)setTabBarShowWithAnimaition:(BOOL)annimation 82 | { 83 | [UIView animateWithDuration:annimation ? 0.25 : 0 animations:^{ 84 | _tabBarView.frame = CGRectMake(0, KMainH - KTabBarHeight, KMainW, KTabBarHeight); 85 | }]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/TabBarController/HWTabBarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWTabBarView.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class HWTabBarView; 12 | 13 | @protocol HWTabBarViewDelegate 14 | 15 | /** 16 | 菜单按钮点击事件 17 | 18 | @param tabBarView HWTabBarView 19 | @param button 菜单按钮 20 | */ 21 | - (void)SKTabBarView:(HWTabBarView *)tabBarView didClickMenuButton:(UIButton *)button; 22 | 23 | @end 24 | 25 | @interface HWTabBarView : UIView 26 | 27 | @property (nonatomic, weak) id delegate; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /HWDownloadDemo/Main/TabBarController/HWTabBarView.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWTabBarView.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWTabBarView.h" 10 | 11 | @implementation HWTabBarView 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | if (self = [super initWithFrame:frame]) { 16 | //普通状态图片 17 | NSArray *imgNorArray = @[@"tabbar_home_nor", @"tabbar_me_nor"]; 18 | //选中状态图片 19 | NSArray *imgSelArray = @[@"tabbar_home_sel", @"tabbar_me_sel"]; 20 | 21 | //菜单按钮 22 | for (int i = 0; i < imgNorArray.count; i ++) { 23 | CGFloat btnW = KMainW / imgNorArray.count; 24 | CGFloat btnX = btnW * i; 25 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(btnX, 0, btnW, 49)]; 26 | btn.adjustsImageWhenHighlighted = NO; 27 | [btn setImage:[UIImage imageNamed:imgNorArray[i]] forState:UIControlStateNormal]; 28 | [btn setImage:[UIImage imageNamed:imgSelArray[i]] forState:UIControlStateSelected]; 29 | [btn setImage:[UIImage imageNamed:imgSelArray[i]] forState:UIControlStateSelected | UIControlStateHighlighted]; 30 | btn.tag = i + 100; 31 | [btn setSelected:i == 0]; 32 | [btn addTarget:self action:@selector(menuBtnOnClick:) forControlEvents:UIControlEventTouchUpInside]; 33 | [self addSubview:btn]; 34 | } 35 | 36 | //线 37 | UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KMainW, 0.5)]; 38 | line.backgroundColor = [UIColor colorWithHexString:@"#a0a0a0"]; 39 | line.alpha = 0.4f; 40 | [self addSubview:line]; 41 | 42 | self.backgroundColor = KWhiteColor; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | - (void)menuBtnOnClick:(UIButton *)btn 49 | { 50 | if (btn.selected) return; 51 | 52 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animation]; 53 | animation.keyPath = @"transform.scale"; 54 | animation.values = @[@1.0, @1.2, @1.0]; 55 | animation.duration = 0.25; 56 | animation.calculationMode = kCAAnimationCubic; 57 | [btn.imageView.layer addAnimation:animation forKey:nil]; 58 | 59 | if (_delegate && [_delegate respondsToSelector:@selector(SKTabBarView:didClickMenuButton:)]) { 60 | [_delegate SKTabBarView:self didClickMenuButton:btn]; 61 | } 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Cache/Controller/HWCacheBaseVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWCacheBaseVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/28. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWBaseViewController.h" 10 | 11 | @interface HWCacheBaseVC : HWBaseViewController 12 | 13 | @property (nonatomic, strong) NSMutableArray *dataSource; // 数据源 14 | @property (nonatomic, weak) UITableView *tableView; // 列表 15 | @property (nonatomic, assign, readonly, getter=isNavEditing) BOOL navEditing; // 是否是编辑删除状态 16 | @property (nonatomic, assign, readonly) CGFloat tabbarViewHeight; // 底部工具栏视图高度 17 | 18 | // 刷新列表 19 | - (void)reloadTableView; 20 | 21 | // 刷新一个cell 22 | - (void)reloadRowWithModel:(HWDownloadModel *)model index:(NSInteger)index; 23 | 24 | // 增加一条数据 25 | - (void)insertModel:(HWDownloadModel *)model; 26 | 27 | // 移除一条数据 28 | - (void)deleteRowAtIndex:(NSInteger)index; 29 | 30 | // 更新数据 31 | - (void)updateViewWithModel:(HWDownloadModel *)model index:(NSInteger)index; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Cache/Controller/HWCacheVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWCacheVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/28. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWCacheBaseVC.h" 10 | 11 | @interface HWCacheVC : HWCacheBaseVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Cache/Controller/HWCacheVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWCacheVC.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/28. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWCacheVC.h" 10 | #import "HWDownloadingVC.h" 11 | 12 | @interface HWCacheVC () 13 | 14 | @property (nonatomic, weak) UIButton *downloadingBtn; 15 | @property (nonatomic, assign) NSInteger downloadingCount; 16 | 17 | @end 18 | 19 | @implementation HWCacheVC 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | self.navTitle = @"缓存"; 25 | 26 | // 创建控件 27 | [self creatControl]; 28 | 29 | // 添加通知 30 | [self addNotification]; 31 | } 32 | 33 | - (void)viewWillAppear:(BOOL)animated 34 | { 35 | [super viewWillAppear:animated]; 36 | 37 | // 获取缓存 38 | [self getCacheData]; 39 | } 40 | 41 | - (void)creatControl 42 | { 43 | // 正在缓存按钮 44 | UIButton *downloadingBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, KMainW, 50)]; 45 | downloadingBtn.hidden = YES; 46 | downloadingBtn.backgroundColor = [UIColor lightGrayColor]; 47 | [downloadingBtn addTarget:self action:@selector(downloadingBtnOnClick) forControlEvents:UIControlEventTouchUpInside]; 48 | [self.view addSubview:downloadingBtn]; 49 | _downloadingBtn = downloadingBtn; 50 | } 51 | 52 | - (void)downloadingBtnOnClick 53 | { 54 | [self.navigationController pushViewController:[[HWDownloadingVC alloc] init] animated:YES]; 55 | } 56 | 57 | - (void)addNotification 58 | { 59 | // 状态改变通知 60 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downLoadStateChange:) name:HWDownloadStateChangeNotification object:nil]; 61 | } 62 | 63 | - (void)getCacheData 64 | { 65 | // 获取已缓存数据 66 | self.dataSource = [[[HWDataBaseManager shareManager] getAllDownloadedData] mutableCopy]; 67 | [self reloadTableView]; 68 | 69 | // 获取所有未下载完成的数据 70 | _downloadingCount = [[HWDataBaseManager shareManager] getAllUnDownloadedData].count; 71 | [self reloadCacheView]; 72 | } 73 | 74 | // 刷新正在缓存提示视图 75 | - (void)reloadCacheView 76 | { 77 | _downloadingBtn.hidden = _downloadingCount == 0; 78 | [_downloadingBtn setTitle:[NSString stringWithFormat:@"%ld个文件正在缓存", _downloadingCount] forState:UIControlStateNormal]; 79 | 80 | self.tableView.frameY = _downloadingCount == 0 ? 0 : _downloadingBtn.frameHeight; 81 | self.tableView.frameHeight = KMainH - KNavHeight - self.tableView.frameY - (self.isNavEditing ? self.tabbarViewHeight - self.tableView.sectionFooterHeight + 5 : 0); 82 | } 83 | 84 | // 状态改变 85 | - (void)downLoadStateChange:(NSNotification *)notification 86 | { 87 | HWDownloadModel *downloadModel = notification.object; 88 | 89 | if (downloadModel.state == HWDownloadStateFinish) { 90 | dispatch_async(dispatch_get_main_queue(), ^{ 91 | [self insertModel:downloadModel]; 92 | _downloadingCount--; 93 | [self reloadCacheView]; 94 | }); 95 | } 96 | } 97 | 98 | - (void)dealloc 99 | { 100 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Cache/Controller/HWDownloadingVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadingVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/5/1. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWCacheBaseVC.h" 10 | 11 | @interface HWDownloadingVC : HWCacheBaseVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Cache/Controller/HWDownloadingVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadingVC.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/5/1. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWDownloadingVC.h" 10 | 11 | @interface HWDownloadingVC () 12 | 13 | @end 14 | 15 | @implementation HWDownloadingVC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | self.navTitle = @"正在缓存"; 21 | 22 | // 添加通知 23 | [self addNotification]; 24 | 25 | // 获取缓存 26 | [self getCacheData]; 27 | } 28 | 29 | - (void)addNotification 30 | { 31 | // 进度通知 32 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downLoadProgress:) name:HWDownloadProgressNotification object:nil]; 33 | // 状态改变通知 34 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downLoadStateChange:) name:HWDownloadStateChangeNotification object:nil]; 35 | } 36 | 37 | - (void)getCacheData 38 | { 39 | // 获取所有未下载完成的数据 40 | self.dataSource = [[[HWDataBaseManager shareManager] getAllUnDownloadedData] mutableCopy]; 41 | [self reloadTableView]; 42 | } 43 | 44 | #pragma mark - HWDownloadNotification 45 | // 正在下载,进度回调 46 | - (void)downLoadProgress:(NSNotification *)notification 47 | { 48 | HWDownloadModel *downloadModel = notification.object; 49 | 50 | dispatch_async(dispatch_get_main_queue(), ^{ 51 | [self.dataSource enumerateObjectsUsingBlock:^(HWDownloadModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 52 | if ([model.url isEqualToString:downloadModel.url]) { 53 | // 更新cell进度 54 | [self updateViewWithModel:downloadModel index:idx]; 55 | 56 | *stop = YES; 57 | } 58 | }]; 59 | }); 60 | } 61 | 62 | // 状态改变 63 | - (void)downLoadStateChange:(NSNotification *)notification 64 | { 65 | HWDownloadModel *downloadModel = notification.object; 66 | 67 | dispatch_async(dispatch_get_main_queue(), ^{ 68 | [self.dataSource enumerateObjectsUsingBlock:^(HWDownloadModel *model, NSUInteger idx, BOOL * _Nonnull stop) { 69 | if ([model.url isEqualToString:downloadModel.url]) { 70 | if (downloadModel.state == HWDownloadStateFinish) { 71 | // 下载完成,移除cell 72 | [self deleteRowAtIndex:idx]; 73 | 74 | // 没有正在下载的数据,则返回 75 | if (self.dataSource.count == 0) [self.navigationController popViewControllerAnimated:YES]; 76 | 77 | }else { 78 | // 刷新列表 79 | [self reloadRowWithModel:downloadModel index:idx]; 80 | } 81 | 82 | *stop = YES; 83 | } 84 | }]; 85 | }); 86 | } 87 | 88 | - (void)dealloc 89 | { 90 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Me/Controller/HWMeVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWMeVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWBaseViewController.h" 10 | 11 | @interface HWMeVC : HWBaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Me/Controller/HWMeVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWMeVC.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/10. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWMeVC.h" 10 | #import "HWCacheVC.h" 11 | #import "HWSettingVC.h" 12 | 13 | @interface HWMeVC () 14 | 15 | @end 16 | 17 | @implementation HWMeVC 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.navTitle = @"我的"; 23 | 24 | [self creatControl]; 25 | } 26 | 27 | - (void)creatControl 28 | { 29 | CGFloat controlX = 30; 30 | CGFloat controlYPadding = 50.f; 31 | CGFloat controlW = KMainW - controlX * 2; 32 | CGFloat controlH = 44.f; 33 | 34 | // 我的缓存 35 | UIButton *cacheBtn = [[UIButton alloc] initWithFrame:CGRectMake(controlX, controlYPadding, controlW, controlH)]; 36 | [cacheBtn setTitle:@"我的缓存" forState:UIControlStateNormal]; 37 | cacheBtn.backgroundColor = [UIColor lightGrayColor]; 38 | [cacheBtn addTarget:self action:@selector(cacheBtnOnClick) forControlEvents:UIControlEventTouchUpInside]; 39 | [self.view addSubview:cacheBtn]; 40 | 41 | // 设置 42 | UIButton *setBtn = [[UIButton alloc] initWithFrame:CGRectMake(controlX, CGRectGetMaxY(cacheBtn.frame) + controlYPadding, controlW, controlH)]; 43 | [setBtn setTitle:@"设置" forState:UIControlStateNormal]; 44 | setBtn.backgroundColor = [UIColor lightGrayColor]; 45 | [setBtn addTarget:self action:@selector(setBtnOnClick) forControlEvents:UIControlEventTouchUpInside]; 46 | [self.view addSubview:setBtn]; 47 | } 48 | 49 | - (void)cacheBtnOnClick 50 | { 51 | [self.navigationController pushViewController:[[HWCacheVC alloc] init] animated:YES]; 52 | } 53 | 54 | - (void)setBtnOnClick 55 | { 56 | [self.navigationController pushViewController:[[HWSettingVC alloc] init] animated:YES]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Setting/Controller/HWSettingVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HWSettingVC.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/26. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWBaseViewController.h" 10 | 11 | @interface HWSettingVC : HWBaseViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Me/Setting/Controller/HWSettingVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWSettingVC.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/26. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import "HWSettingVC.h" 10 | 11 | @interface HWSettingVC () 12 | 13 | @property (nonatomic, weak) UITextField *textField; 14 | 15 | @end 16 | 17 | @implementation HWSettingVC 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.navTitle = @"设置"; 23 | 24 | [self creatControl]; 25 | } 26 | 27 | - (void)creatControl 28 | { 29 | CGFloat controlX = 30.f; 30 | CGFloat controlYPadding = 50.f; 31 | CGFloat controlW = KMainW - controlX * 2; 32 | CGFloat controlH = 44.f; 33 | 34 | // 设置最大并发数 35 | UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(controlX, controlYPadding, controlW, controlH)]; 36 | UILabel *leftView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 222, controlH)]; 37 | leftView.text = @" 设置下载最大并发数(上限5):"; 38 | leftView.textColor = KWhiteColor; 39 | textField.leftView = leftView; 40 | textField.leftViewMode = UITextFieldViewModeAlways; 41 | textField.text = [NSString stringWithFormat:@"%ld", [[NSUserDefaults standardUserDefaults] integerForKey:HWDownloadMaxConcurrentCountKey]]; 42 | textField.textColor = [UIColor yellowColor]; 43 | textField.font = [UIFont boldSystemFontOfSize:18.f]; 44 | textField.backgroundColor = [UIColor lightGrayColor]; 45 | textField.textAlignment = NSTextAlignmentCenter; 46 | textField.returnKeyType = UIReturnKeyDone; 47 | textField.keyboardType = UIKeyboardTypeNumbersAndPunctuation; 48 | [textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]; 49 | [textField addTarget:self action:@selector(done) forControlEvents:UIControlEventEditingDidEndOnExit]; 50 | [self.view addSubview:textField]; 51 | _textField = textField; 52 | 53 | // 是否允许蜂窝网络下载 54 | UILabel *accessLable = [[UILabel alloc] initWithFrame:CGRectMake(controlX, CGRectGetMaxY(textField.frame) + controlYPadding, controlW, controlH)]; 55 | accessLable.text = @" 是否允许蜂窝网络下载"; 56 | accessLable.textColor = KWhiteColor; 57 | accessLable.textAlignment = NSTextAlignmentLeft; 58 | accessLable.userInteractionEnabled = YES; 59 | accessLable.backgroundColor = [UIColor lightGrayColor]; 60 | accessLable.layer.masksToBounds = YES; 61 | [self.view addSubview:accessLable]; 62 | 63 | // 开关 64 | UISwitch *accessSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(accessLable.frameWidth - 60, 6.5, 0, 0)]; 65 | accessSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:HWDownloadAllowsCellularAccessKey]; 66 | [accessSwitch addTarget:self action:@selector(accessSwitchOnClick:) forControlEvents:UIControlEventValueChanged]; 67 | [accessLable addSubview:accessSwitch]; 68 | 69 | // 清空缓存 70 | UIButton *clearBtn = [[UIButton alloc] initWithFrame:CGRectMake(controlX, CGRectGetMaxY(accessLable.frame) + controlYPadding, controlW, controlH)]; 71 | [clearBtn setTitle:@"清空缓存" forState:UIControlStateNormal]; 72 | clearBtn.backgroundColor = [UIColor lightGrayColor]; 73 | [clearBtn addTarget:self action:@selector(clearBtnOnClick) forControlEvents:UIControlEventTouchUpInside]; 74 | [self.view addSubview:clearBtn]; 75 | } 76 | 77 | - (void)textFieldEditingChanged:(UITextField *)textField 78 | { 79 | if (textField.text.length > 1) { 80 | textField.text = [textField.text substringToIndex:1]; 81 | 82 | }else if (textField.text.length == 1) { 83 | NSCharacterSet *characterSet = [[NSCharacterSet characterSetWithCharactersInString:@"12345"] invertedSet]; 84 | NSString *filtered = [[_textField.text componentsSeparatedByCharactersInSet:characterSet] componentsJoinedByString:@""]; 85 | BOOL basicTest = [_textField.text isEqualToString:filtered]; 86 | if (!basicTest) { 87 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"请输入数字1~5" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; 88 | [alert show]; 89 | textField.text = @""; 90 | } 91 | } 92 | } 93 | 94 | - (void)done 95 | { 96 | if ([_textField.text isEqualToString:@""]) _textField.text = @"1"; 97 | 98 | // 原并发数 99 | NSInteger oldCount = [[NSUserDefaults standardUserDefaults] integerForKey:HWDownloadMaxConcurrentCountKey]; 100 | // 新并发数 101 | NSInteger newCount = [_textField.text integerValue]; 102 | 103 | if (oldCount != newCount) { 104 | // 保存 105 | [[NSUserDefaults standardUserDefaults] setInteger:newCount forKey:HWDownloadMaxConcurrentCountKey]; 106 | 107 | // 通知 108 | [[NSNotificationCenter defaultCenter] postNotificationName:HWDownloadMaxConcurrentCountChangeNotification object:[NSNumber numberWithInteger:newCount]]; 109 | } 110 | } 111 | 112 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 113 | { 114 | [self.view endEditing:YES]; 115 | 116 | [self done]; 117 | } 118 | 119 | - (void)accessSwitchOnClick:(UISwitch *)accessSwitch 120 | { 121 | // 保存 122 | [[NSUserDefaults standardUserDefaults] setBool:accessSwitch.isOn forKey:HWDownloadAllowsCellularAccessKey]; 123 | 124 | // 通知 125 | [[NSNotificationCenter defaultCenter] postNotificationName:HWDownloadAllowsCellularAccessChangeNotification object:[NSNumber numberWithBool:accessSwitch.isOn]]; 126 | } 127 | 128 | - (void)clearBtnOnClick 129 | { 130 | [HWToolBox showAlertWithTitle:@"是否清空所有缓存?" sureMessage:@"确认" cancelMessage:@"取消" warningMessage:nil style:UIAlertControllerStyleAlert target:self sureHandler:^(UIAlertAction *action) { 131 | // 清空缓存 132 | [self clearLocalCache]; 133 | } cancelHandler:nil warningHandler:nil]; 134 | } 135 | 136 | - (void)clearLocalCache 137 | { 138 | dispatch_queue_t queue = dispatch_get_global_queue(0, 0); 139 | dispatch_async(queue, ^{ 140 | NSArray *array = [[HWDataBaseManager shareManager] getAllCacheData]; 141 | for (HWDownloadModel *model in array) { 142 | [[HWDownloadManager shareManager] deleteTaskAndCache:model]; 143 | } 144 | }); 145 | } 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/GlobeConst.h: -------------------------------------------------------------------------------- 1 | // 2 | // GlobeConst.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/20. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | /************************* 下载 *************************/ 10 | UIKIT_EXTERN NSString * const HWDownloadProgressNotification; // 进度回调通知 11 | UIKIT_EXTERN NSString * const HWDownloadStateChangeNotification; // 状态改变通知 12 | UIKIT_EXTERN NSString * const HWDownloadMaxConcurrentCountKey; // 最大同时下载数量key 13 | UIKIT_EXTERN NSString * const HWDownloadMaxConcurrentCountChangeNotification; // 最大同时下载数量改变通知 14 | UIKIT_EXTERN NSString * const HWDownloadAllowsCellularAccessKey; // 是否允许蜂窝网络下载key 15 | UIKIT_EXTERN NSString * const HWDownloadAllowsCellularAccessChangeNotification; // 是否允许蜂窝网络下载改变通知 16 | 17 | /************************* 网络 *************************/ 18 | UIKIT_EXTERN NSString * const HWNetworkingReachabilityDidChangeNotification; // 网络改变改变通知 19 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/GlobeConst.m: -------------------------------------------------------------------------------- 1 | // 2 | // GlobeConst.m 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/20. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /************************* 下载 *************************/ 12 | NSString * const HWDownloadProgressNotification = @"HWDownloadProgressNotification"; 13 | NSString * const HWDownloadStateChangeNotification = @"HWDownloadStateChangeNotification"; 14 | NSString * const HWDownloadMaxConcurrentCountKey = @"HWDownloadMaxConcurrentCountKey"; 15 | NSString * const HWDownloadMaxConcurrentCountChangeNotification = @"HWDownloadMaxConcurrentCountChangeNotification"; 16 | NSString * const HWDownloadAllowsCellularAccessKey = @"HWDownloadAllowsCellularAccessKey"; 17 | NSString * const HWDownloadAllowsCellularAccessChangeNotification = @"HWDownloadAllowsCellularAccessChangeNotification"; 18 | 19 | /************************* 网络 *************************/ 20 | NSString * const HWNetworkingReachabilityDidChangeNotification = @"HWNetworkingReachabilityDidChangeNotification"; 21 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/GlobeHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // GlobeHeader.h 3 | // HWProject 4 | // 5 | // Created by wangqibin on 2018/4/20. 6 | // Copyright © 2018年 wangqibin. All rights reserved. 7 | // 8 | 9 | #ifndef GlobeHeader_h 10 | #define GlobeHeader_h 11 | 12 | /************************* system *************************/ 13 | #import 14 | 15 | /************************* categorys *************************/ 16 | #import "NSString+HW.h" 17 | #import "UIColor+HW.h" 18 | #import "UIImage+HW.h" 19 | #import "UIView+Extension.h" 20 | 21 | /************************* common *************************/ 22 | #import "HWToolBox.h" 23 | #import "HWDownload.h" 24 | #import "HWNetworkReachabilityManager.h" 25 | #import "HWProgressHUD.h" 26 | 27 | /************************* vender *************************/ 28 | #import "AFNetworking.h" 29 | #import "MJExtension.h" 30 | #import "FMDB.h" 31 | 32 | /************************* other *************************/ 33 | #import "GlobeConst.h" 34 | #import "AppDelegate.h" 35 | 36 | #endif /* GlobeHeader_h */ 37 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_default@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_default@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_default@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_error@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_error@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_finish@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_finish@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_finish@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_finish@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_pause@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_pause@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_pause@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_pause@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_waiting@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_waiting@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_download_waiting@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_download_waiting@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading01@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading01@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading02@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading02@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading03@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading03@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading04@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading04@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading05@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading05@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading06@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading06@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading07@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading07@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/com_loading08@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/com_loading08@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/nav_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/nav_back@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/nav_back@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/nav_back@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/nav_cancelBtn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/nav_cancelBtn@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/nav_cancelBtn@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/nav_cancelBtn@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/nav_deleteBtn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/nav_deleteBtn@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/nav_deleteBtn@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/nav_deleteBtn@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_home_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_home_nor@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_home_nor@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_home_nor@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_home_sel@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_home_sel@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_home_sel@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_home_sel@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_me_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_me_nor@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_me_nor@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_me_nor@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_me_sel@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_me_sel@2x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Images/Common/tabbar_me_sel@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeroWqb/HWDownloadDemo/161bf067c492b8f378f52d0c306e6a3b7450946b/HWDownloadDemo/Other/Images/Common/tabbar_me_sel@3x.png -------------------------------------------------------------------------------- /HWDownloadDemo/Other/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIViewControllerBasedStatusBarAppearance 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // HWDownloadDemo 4 | // 5 | // Created by wangqibin on 2018/5/21. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #ifndef PrefixHeader_pch 10 | #define PrefixHeader_pch 11 | 12 | #import "GlobeHeader.h" 13 | 14 | #define KWhiteColor [UIColor whiteColor] 15 | #define KClearColor [UIColor clearColor] 16 | 17 | #define KMainW [UIScreen mainScreen].bounds.size.width 18 | #define KMainH [UIScreen mainScreen].bounds.size.height 19 | #define KStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height 20 | #define KNavHeight (KStatusBarHeight + 44.f) 21 | #define KIsBangScreen (KStatusBarHeight > 20.1) // 刘海屏,状态栏44pt,底部留功能区34pt 22 | #define KTabBarHeight (KIsBangScreen ? 83.0f : 49.0f) 23 | #define KBottomSafeArea (KIsBangScreen ? 34.0f : 0.0f) 24 | 25 | #define IS_IPHONE_4 (KMainH == 480.0) // 320*480 3.5 @2x 26 | #define IS_IPHONE_5 (KMainH == 568.0) // 320*568 4.0 @2x 27 | #define IS_IPHONE_6 (KMainH == 667.0) // 375*667 4.7 @2x 28 | #define IS_IPHONE_6P (KMainH == 736.0) // 414*736 5.5 @3x 29 | #define IS_IPHONE_X (KMainH == 812.0) // 375*812 5.8 @3x iPhone X、Xs 30 | #define IS_IPHONE_XM (KMainH == 896.0) // 414*896 6.1 @2x iPhone Xr、6.5 @3x iPhone Xs Max 31 | #define ISIOS8 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ? YES : NO) 32 | #define ISIOS9 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0 ? YES : NO) 33 | #define ISIOS10 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0 ? YES : NO) 34 | #define ISIOS11 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11.0 ? YES : NO) 35 | #define ISIOS12 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 12.0 ? YES : NO) 36 | 37 | #define KScreenRate (375 / KMainW) 38 | #define KSuitFloat(float) ((float) / KScreenRate) 39 | #define KSuitSize(width, height) CGSizeMake((width) / KScreenRate, (height) / KScreenRate) 40 | #define KSuitPoint(x, y) CGPointMake((x) / KScreenRate, (y) / KScreenRate) 41 | #define KSuitFrame(x, y, width, heigth) CGRectMake((x) / KScreenRate, (y) / KScreenRate, (width) / KScreenRate, (heigth) / KScreenRate) 42 | 43 | #define weakify(var) __weak typeof(var) weakSelf = var 44 | #define strongify(var) __strong typeof(var) strongSelf = var 45 | 46 | #define NSLog(...) printf("[%s] %s [第%d行] %s\n", [[HWToolBox currentTimeCorrectToMillisecond] UTF8String], __FUNCTION__, __LINE__, [[NSString stringWithFormat:__VA_ARGS__] UTF8String]); 47 | 48 | #ifdef DEBUG 49 | #define HWLog(format, ...) printf("[%s] %s [第%d行] %s\n", [[HWToolBox currentTimeCorrectToMillisecond] UTF8String], __FUNCTION__, __LINE__, [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String]); 50 | #else 51 | #define HWLog(format, ...) 52 | #endif 53 | 54 | #endif /* PrefixHeader_pch */ 55 | 56 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HWDownloadDemo 4 | // 5 | // Created by wangqibin on 2018/5/21. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /HWDownloadDemo/Other/testData.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vid 7 | 1 8 | fileName 9 | 网络视频文件 01 10 | url 11 | https://www.apple.com/105/media/cn/iphone-x/2017/01df5b43-28e4-4848-bf20-490c34a926a7/films/feature/iphone-x-feature-cn-20170912_1280x720h.mp4 12 | 13 | 14 | vid 15 | 2 16 | fileName 17 | 网络视频文件 02 18 | url 19 | https://images.apple.com/media/cn/macbook-pro/2016/b4a9efaa_6fe5_4075_a9d0_8e4592d6146c/films/design/macbook-pro-design-tft-cn-20161026_1536x640h.mp4 20 | 21 | 22 | vid 23 | 3 24 | fileName 25 | 网络视频文件 03 26 | url 27 | https://www.apple.com/105/media/cn/ipad-pro/how-to/2017/a0f629be_c30b_4333_942f_13a221fc44f3/films/dock/ipad-pro-dock-cn-20160907_1280x720h.mp4 28 | 29 | 30 | vid 31 | 4 32 | fileName 33 | 网络视频文件 04 34 | url 35 | https://www.apple.com/105/media/cn/ipad/2018/08716702_0a2f_4b2c_9fdd_e08394ae72f1/films/use-two-apps/ipad-use-two-apps-tpl-cn-20180404_1280x720h.mp4 36 | 37 | 38 | vid 39 | 5 40 | fileName 41 | 网络视频文件 05 42 | url 43 | https://www.apple.com/105/media/us/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/hero/large.mp4 44 | 45 | 46 | vid 47 | 6 48 | fileName 49 | 网络视频文件 06 50 | url 51 | https://www.apple.com/105/media/us/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/thumbnails/buck/large.mp4 52 | 53 | 54 | vid 55 | 7 56 | fileName 57 | 网络视频文件 07 58 | url 59 | https://www.apple.com/105/media/us/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/thumbnails/erin-sarofsky/large.mp4 60 | 61 | 62 | vid 63 | 8 64 | fileName 65 | 网络视频文件 08 66 | url 67 | https://www.apple.com/105/media/cn/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/films/buck/imac-pro-buck-tpl-cn-20180223_1280x720h.mp4 68 | 69 | 70 | vid 71 | 9 72 | fileName 73 | 网络视频文件 09 74 | url 75 | https://www.apple.com/105/media/cn/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/films/esteban-diacono/imac-pro-esteban-diacono-tpl-cn-20180223_1280x720h.mp4 76 | 77 | 78 | vid 79 | 10 80 | fileName 81 | 网络视频文件 10 82 | url 83 | https://www.apple.com/105/media/cn/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/films/luigi-honorat/imac-pro-luigi-honrat-tpl-cn-20180223_1280x720h.mp4 84 | 85 | 86 | vid 87 | 11 88 | fileName 89 | 网络视频文件 11 90 | url 91 | https://www.apple.com/105/media/cn/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/films/bts/luigi-honorat/imac-pro-luigi-honrat-bts-tpl-cn-20180223_1280x720h.mp4 92 | 93 | 94 | vid 95 | 12 96 | fileName 97 | 网络视频文件 12 98 | url 99 | https://www.apple.com/105/media/cn/imac-pro/2018/d0b63f9b_f0de_4dea_a993_62b4cb35ca96/films/michelle-dougherty/imac-pro-michelle-dougherty-tpl-cn-20180223_1280x720h.mp4 100 | 101 | 102 | vid 103 | 13 104 | fileName 105 | 网络视频文件 13 106 | url 107 | https://www.apple.com/105/media/cn/iphone-x/2018/5b64bc98_3bd3_4c12_9b3e_bae2df6b2d9d/films/new-light/iphone-x-new-light-tpl-cn-20180201_1280x720h.mp4 108 | 109 | 110 | vid 111 | 14 112 | fileName 113 | 网络视频文件 14 114 | url 115 | https://www.apple.com/105/media/cn/iphone-x/2017/01df5b43-28e4-4848-bf20-490c34a926a7/films/animoji/iphone-x-animoji-cn-20171205_1280x720h.mp4 116 | 117 | 118 | vid 119 | 15 120 | fileName 121 | 网络视频文件 15 122 | url 123 | https://www.apple.com/105/media/cn/ipad/2018/08716702_0a2f_4b2c_9fdd_e08394ae72f1/films/browse-files/ipad-browse-files-tpl-cn-20180404_1280x720h.mp4 124 | 125 | 126 | vid 127 | 16 128 | fileName 129 | 网络视频文件 16 130 | url 131 | https://www.apple.com/105/media/cn/iphone-x/2017/01df5b43-28e4-4848-bf20-490c34a926a7/films/face-id/iphone-x-face-id-cn-20171129_1280x720h.mp4 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | #import 26 | 27 | #ifndef _AFNETWORKING_ 28 | #define _AFNETWORKING_ 29 | 30 | #import "AFURLRequestSerialization.h" 31 | #import "AFURLResponseSerialization.h" 32 | #import "AFSecurityPolicy.h" 33 | 34 | #if !TARGET_OS_WATCH 35 | #import "AFNetworkReachabilityManager.h" 36 | #endif 37 | 38 | #import "AFURLSessionManager.h" 39 | #import "AFHTTPSessionManager.h" 40 | 41 | #endif /* _AFNETWORKING_ */ 42 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011–2016 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkActivityIndicatorManager.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS 27 | 28 | #import 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | /** 33 | `AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a session task has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero. 34 | 35 | You should enable the shared instance of `AFNetworkActivityIndicatorManager` when your application finishes launching. In `AppDelegate application:didFinishLaunchingWithOptions:` you can do so with the following code: 36 | 37 | [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; 38 | 39 | By setting `enabled` to `YES` for `sharedManager`, the network activity indicator will show and hide automatically as requests start and finish. You should not ever need to call `incrementActivityCount` or `decrementActivityCount` yourself. 40 | 41 | See the Apple Human Interface Guidelines section about the Network Activity Indicator for more information: 42 | http://developer.apple.com/library/iOS/#documentation/UserExperience/Conceptual/MobileHIG/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW44 43 | */ 44 | NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.") 45 | @interface AFNetworkActivityIndicatorManager : NSObject 46 | 47 | /** 48 | A Boolean value indicating whether the manager is enabled. 49 | 50 | If YES, the manager will change status bar network activity indicator according to network operation notifications it receives. The default value is NO. 51 | */ 52 | @property (nonatomic, assign, getter = isEnabled) BOOL enabled; 53 | 54 | /** 55 | A Boolean value indicating whether the network activity indicator manager is currently active. 56 | */ 57 | @property (readonly, nonatomic, assign, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; 58 | 59 | /** 60 | A time interval indicating the minimum duration of networking activity that should occur before the activity indicator is displayed. The default value 1 second. If the network activity indicator should be displayed immediately when network activity occurs, this value should be set to 0 seconds. 61 | 62 | Apple's HIG describes the following: 63 | 64 | > Display the network activity indicator to provide feedback when your app accesses the network for more than a couple of seconds. If the operation finishes sooner than that, you don’t have to show the network activity indicator, because the indicator is likely to disappear before users notice its presence. 65 | 66 | */ 67 | @property (nonatomic, assign) NSTimeInterval activationDelay; 68 | 69 | /** 70 | A time interval indicating the duration of time of no networking activity required before the activity indicator is disabled. This allows for continuous display of the network activity indicator across multiple requests. The default value is 0.17 seconds. 71 | */ 72 | 73 | @property (nonatomic, assign) NSTimeInterval completionDelay; 74 | 75 | /** 76 | Returns the shared network activity indicator manager object for the system. 77 | 78 | @return The systemwide network activity indicator manager. 79 | */ 80 | + (instancetype)sharedManager; 81 | 82 | /** 83 | Increments the number of active network requests. If this number was zero before incrementing, this will start animating the status bar network activity indicator. 84 | */ 85 | - (void)incrementActivityCount; 86 | 87 | /** 88 | Decrements the number of active network requests. If this number becomes zero after decrementing, this will stop animating the status bar network activity indicator. 89 | */ 90 | - (void)decrementActivityCount; 91 | 92 | /** 93 | Set the a custom method to be executed when the network activity indicator manager should be hidden/shown. By default, this is null, and the UIApplication Network Activity Indicator will be managed automatically. If this block is set, it is the responsiblity of the caller to manager the network activity indicator going forward. 94 | 95 | @param block A block to be executed when the network activity indicator status changes. 96 | */ 97 | - (void)setNetworkingActivityActionWithBlock:(nullable void (^)(BOOL networkActivityIndicatorVisible))block; 98 | 99 | @end 100 | 101 | NS_ASSUME_NONNULL_END 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIActivityIndicatorView+AFNetworking.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | 28 | #import 29 | 30 | /** 31 | This category adds methods to the UIKit framework's `UIActivityIndicatorView` class. The methods in this category provide support for automatically starting and stopping animation depending on the loading state of a session task. 32 | */ 33 | @interface UIActivityIndicatorView (AFNetworking) 34 | 35 | ///---------------------------------- 36 | /// @name Animating for Session Tasks 37 | ///---------------------------------- 38 | 39 | /** 40 | Binds the animating state to the state of the specified task. 41 | 42 | @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. 43 | */ 44 | - (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task; 45 | 46 | @end 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIActivityIndicatorView+AFNetworking.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "UIActivityIndicatorView+AFNetworking.h" 23 | #import 24 | 25 | #if TARGET_OS_IOS || TARGET_OS_TV 26 | 27 | #import "AFURLSessionManager.h" 28 | 29 | @interface AFActivityIndicatorViewNotificationObserver : NSObject 30 | @property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView; 31 | - (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView; 32 | 33 | - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; 34 | 35 | @end 36 | 37 | @implementation UIActivityIndicatorView (AFNetworking) 38 | 39 | - (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver { 40 | AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); 41 | if (notificationObserver == nil) { 42 | notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self]; 43 | objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 44 | } 45 | return notificationObserver; 46 | } 47 | 48 | - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { 49 | [[self af_notificationObserver] setAnimatingWithStateOfTask:task]; 50 | } 51 | 52 | @end 53 | 54 | @implementation AFActivityIndicatorViewNotificationObserver 55 | 56 | - (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView 57 | { 58 | self = [super init]; 59 | if (self) { 60 | _activityIndicatorView = activityIndicatorView; 61 | } 62 | return self; 63 | } 64 | 65 | - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { 66 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 67 | 68 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; 69 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; 70 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; 71 | 72 | if (task) { 73 | if (task.state != NSURLSessionTaskStateCompleted) { 74 | 75 | #pragma clang diagnostic push 76 | #pragma clang diagnostic ignored "-Wreceiver-is-weak" 77 | #pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" 78 | if (task.state == NSURLSessionTaskStateRunning) { 79 | [self.activityIndicatorView startAnimating]; 80 | } else { 81 | [self.activityIndicatorView stopAnimating]; 82 | } 83 | #pragma clang diagnostic pop 84 | 85 | [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task]; 86 | [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task]; 87 | [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidSuspendNotification object:task]; 88 | } 89 | } 90 | } 91 | 92 | #pragma mark - 93 | 94 | - (void)af_startAnimating { 95 | dispatch_async(dispatch_get_main_queue(), ^{ 96 | #pragma clang diagnostic push 97 | #pragma clang diagnostic ignored "-Wreceiver-is-weak" 98 | [self.activityIndicatorView startAnimating]; 99 | #pragma clang diagnostic pop 100 | }); 101 | } 102 | 103 | - (void)af_stopAnimating { 104 | dispatch_async(dispatch_get_main_queue(), ^{ 105 | #pragma clang diagnostic push 106 | #pragma clang diagnostic ignored "-Wreceiver-is-weak" 107 | [self.activityIndicatorView stopAnimating]; 108 | #pragma clang diagnostic pop 109 | }); 110 | } 111 | 112 | #pragma mark - 113 | 114 | - (void)dealloc { 115 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 116 | 117 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; 118 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; 119 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; 120 | } 121 | 122 | @end 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIImage+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+AFNetworking.h 3 | // 4 | // 5 | // Created by Paulo Ferreira on 08/07/15. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #if TARGET_OS_IOS || TARGET_OS_TV 26 | 27 | #import 28 | 29 | @interface UIImage (AFNetworking) 30 | 31 | + (UIImage*) safeImageWithData:(NSData*)data; 32 | 33 | @end 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIImageView+AFNetworking.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | 28 | #import 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | @class AFImageDownloader; 33 | 34 | /** 35 | This category adds methods to the UIKit framework's `UIImageView` class. The methods in this category provide support for loading remote images asynchronously from a URL. 36 | */ 37 | @interface UIImageView (AFNetworking) 38 | 39 | ///------------------------------------ 40 | /// @name Accessing the Image Downloader 41 | ///------------------------------------ 42 | 43 | /** 44 | Set the shared image downloader used to download images. 45 | 46 | @param imageDownloader The shared image downloader used to download images. 47 | */ 48 | + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader; 49 | 50 | /** 51 | The shared image downloader used to download images. 52 | */ 53 | + (AFImageDownloader *)sharedImageDownloader; 54 | 55 | ///-------------------- 56 | /// @name Setting Image 57 | ///-------------------- 58 | 59 | /** 60 | Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. 61 | 62 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 63 | 64 | By default, URL requests have a `Accept` header field value of "image / *", a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 65 | 66 | @param url The URL used for the image request. 67 | */ 68 | - (void)setImageWithURL:(NSURL *)url; 69 | 70 | /** 71 | Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. 72 | 73 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 74 | 75 | By default, URL requests have a `Accept` header field value of "image / *", a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 76 | 77 | @param url The URL used for the image request. 78 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 79 | */ 80 | - (void)setImageWithURL:(NSURL *)url 81 | placeholderImage:(nullable UIImage *)placeholderImage; 82 | 83 | /** 84 | Asynchronously downloads an image from the specified URL request, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. 85 | 86 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 87 | 88 | If a success block is specified, it is the responsibility of the block to set the image of the image view before returning. If no success block is specified, the default behavior of setting the image with `self.image = image` is applied. 89 | 90 | @param urlRequest The URL request used for the image request. 91 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 92 | @param success A block to be executed when the image data task finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. 93 | @param failure A block object to be executed when the image data task finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. 94 | */ 95 | - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 96 | placeholderImage:(nullable UIImage *)placeholderImage 97 | success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success 98 | failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; 99 | 100 | /** 101 | Cancels any executing image operation for the receiver, if one exists. 102 | */ 103 | - (void)cancelImageDownloadTask; 104 | 105 | @end 106 | 107 | NS_ASSUME_NONNULL_END 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIKit+AFNetworking.h 2 | // 3 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #if TARGET_OS_IOS || TARGET_OS_TV 24 | #import 25 | 26 | #ifndef _UIKIT_AFNETWORKING_ 27 | #define _UIKIT_AFNETWORKING_ 28 | 29 | #if TARGET_OS_IOS 30 | #import "AFAutoPurgingImageCache.h" 31 | #import "AFImageDownloader.h" 32 | #import "AFNetworkActivityIndicatorManager.h" 33 | #import "UIRefreshControl+AFNetworking.h" 34 | #import "UIWebView+AFNetworking.h" 35 | #endif 36 | 37 | #import "UIActivityIndicatorView+AFNetworking.h" 38 | #import "UIButton+AFNetworking.h" 39 | #import "UIImageView+AFNetworking.h" 40 | #import "UIProgressView+AFNetworking.h" 41 | #endif /* _UIKIT_AFNETWORKING_ */ 42 | #endif 43 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIProgressView+AFNetworking.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | 28 | #import 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIProgressView` class. The methods in this category provide support for binding the progress to the upload and download progress of a session task. 35 | */ 36 | @interface UIProgressView (AFNetworking) 37 | 38 | ///------------------------------------ 39 | /// @name Setting Session Task Progress 40 | ///------------------------------------ 41 | 42 | /** 43 | Binds the progress to the upload progress of the specified session task. 44 | 45 | @param task The session task. 46 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 47 | */ 48 | - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task 49 | animated:(BOOL)animated; 50 | 51 | /** 52 | Binds the progress to the download progress of the specified session task. 53 | 54 | @param task The session task. 55 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 56 | */ 57 | - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task 58 | animated:(BOOL)animated; 59 | 60 | @end 61 | 62 | NS_ASSUME_NONNULL_END 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIProgressView+AFNetworking.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "UIProgressView+AFNetworking.h" 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | 28 | #import "AFURLSessionManager.h" 29 | 30 | static void * AFTaskCountOfBytesSentContext = &AFTaskCountOfBytesSentContext; 31 | static void * AFTaskCountOfBytesReceivedContext = &AFTaskCountOfBytesReceivedContext; 32 | 33 | #pragma mark - 34 | 35 | @implementation UIProgressView (AFNetworking) 36 | 37 | - (BOOL)af_uploadProgressAnimated { 38 | return [(NSNumber *)objc_getAssociatedObject(self, @selector(af_uploadProgressAnimated)) boolValue]; 39 | } 40 | 41 | - (void)af_setUploadProgressAnimated:(BOOL)animated { 42 | objc_setAssociatedObject(self, @selector(af_uploadProgressAnimated), @(animated), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 43 | } 44 | 45 | - (BOOL)af_downloadProgressAnimated { 46 | return [(NSNumber *)objc_getAssociatedObject(self, @selector(af_downloadProgressAnimated)) boolValue]; 47 | } 48 | 49 | - (void)af_setDownloadProgressAnimated:(BOOL)animated { 50 | objc_setAssociatedObject(self, @selector(af_downloadProgressAnimated), @(animated), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 51 | } 52 | 53 | #pragma mark - 54 | 55 | - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task 56 | animated:(BOOL)animated 57 | { 58 | [task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext]; 59 | [task addObserver:self forKeyPath:@"countOfBytesSent" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext]; 60 | 61 | [self af_setUploadProgressAnimated:animated]; 62 | } 63 | 64 | - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task 65 | animated:(BOOL)animated 66 | { 67 | [task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext]; 68 | [task addObserver:self forKeyPath:@"countOfBytesReceived" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext]; 69 | 70 | [self af_setDownloadProgressAnimated:animated]; 71 | } 72 | 73 | #pragma mark - NSKeyValueObserving 74 | 75 | - (void)observeValueForKeyPath:(NSString *)keyPath 76 | ofObject:(id)object 77 | change:(__unused NSDictionary *)change 78 | context:(void *)context 79 | { 80 | if (context == AFTaskCountOfBytesSentContext || context == AFTaskCountOfBytesReceivedContext) { 81 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) { 82 | if ([object countOfBytesExpectedToSend] > 0) { 83 | dispatch_async(dispatch_get_main_queue(), ^{ 84 | [self setProgress:[object countOfBytesSent] / ([object countOfBytesExpectedToSend] * 1.0f) animated:self.af_uploadProgressAnimated]; 85 | }); 86 | } 87 | } 88 | 89 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) { 90 | if ([object countOfBytesExpectedToReceive] > 0) { 91 | dispatch_async(dispatch_get_main_queue(), ^{ 92 | [self setProgress:[object countOfBytesReceived] / ([object countOfBytesExpectedToReceive] * 1.0f) animated:self.af_downloadProgressAnimated]; 93 | }); 94 | } 95 | } 96 | 97 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) { 98 | if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) { 99 | @try { 100 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))]; 101 | 102 | if (context == AFTaskCountOfBytesSentContext) { 103 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))]; 104 | } 105 | 106 | if (context == AFTaskCountOfBytesReceivedContext) { 107 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))]; 108 | } 109 | } 110 | @catch (NSException * __unused exception) {} 111 | } 112 | } 113 | } 114 | } 115 | 116 | @end 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIRefreshControl+AFNetworking.m 2 | // 3 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if TARGET_OS_IOS 28 | 29 | #import 30 | 31 | NS_ASSUME_NONNULL_BEGIN 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically beginning and ending refreshing depending on the loading state of a session task. 35 | */ 36 | @interface UIRefreshControl (AFNetworking) 37 | 38 | ///----------------------------------- 39 | /// @name Refreshing for Session Tasks 40 | ///----------------------------------- 41 | 42 | /** 43 | Binds the refreshing state to the state of the specified task. 44 | 45 | @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. 46 | */ 47 | - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIRefreshControl+AFNetworking.m 2 | // 3 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIRefreshControl+AFNetworking.h" 24 | #import 25 | 26 | #if TARGET_OS_IOS 27 | 28 | #import "AFURLSessionManager.h" 29 | 30 | @interface AFRefreshControlNotificationObserver : NSObject 31 | @property (readonly, nonatomic, weak) UIRefreshControl *refreshControl; 32 | - (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl; 33 | 34 | - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; 35 | 36 | @end 37 | 38 | @implementation UIRefreshControl (AFNetworking) 39 | 40 | - (AFRefreshControlNotificationObserver *)af_notificationObserver { 41 | AFRefreshControlNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); 42 | if (notificationObserver == nil) { 43 | notificationObserver = [[AFRefreshControlNotificationObserver alloc] initWithActivityRefreshControl:self]; 44 | objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 45 | } 46 | return notificationObserver; 47 | } 48 | 49 | - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { 50 | [[self af_notificationObserver] setRefreshingWithStateOfTask:task]; 51 | } 52 | 53 | @end 54 | 55 | @implementation AFRefreshControlNotificationObserver 56 | 57 | - (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl 58 | { 59 | self = [super init]; 60 | if (self) { 61 | _refreshControl = refreshControl; 62 | } 63 | return self; 64 | } 65 | 66 | - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { 67 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 68 | 69 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; 70 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; 71 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; 72 | 73 | if (task) { 74 | #pragma clang diagnostic push 75 | #pragma clang diagnostic ignored "-Wreceiver-is-weak" 76 | #pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" 77 | if (task.state == NSURLSessionTaskStateRunning) { 78 | [self.refreshControl beginRefreshing]; 79 | 80 | [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingTaskDidResumeNotification object:task]; 81 | [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidCompleteNotification object:task]; 82 | [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidSuspendNotification object:task]; 83 | } else { 84 | [self.refreshControl endRefreshing]; 85 | } 86 | #pragma clang diagnostic pop 87 | } 88 | } 89 | 90 | #pragma mark - 91 | 92 | - (void)af_beginRefreshing { 93 | dispatch_async(dispatch_get_main_queue(), ^{ 94 | #pragma clang diagnostic push 95 | #pragma clang diagnostic ignored "-Wreceiver-is-weak" 96 | [self.refreshControl beginRefreshing]; 97 | #pragma clang diagnostic pop 98 | }); 99 | } 100 | 101 | - (void)af_endRefreshing { 102 | dispatch_async(dispatch_get_main_queue(), ^{ 103 | #pragma clang diagnostic push 104 | #pragma clang diagnostic ignored "-Wreceiver-is-weak" 105 | [self.refreshControl endRefreshing]; 106 | #pragma clang diagnostic pop 107 | }); 108 | } 109 | 110 | #pragma mark - 111 | 112 | - (void)dealloc { 113 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 114 | 115 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; 116 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; 117 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; 118 | } 119 | 120 | @end 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIWebView+AFNetworking.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS 27 | 28 | #import 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | @class AFHTTPSessionManager; 33 | 34 | /** 35 | This category adds methods to the UIKit framework's `UIWebView` class. The methods in this category provide increased control over the request cycle, including progress monitoring and success / failure handling. 36 | 37 | @discussion When using these category methods, make sure to assign `delegate` for the web view, which implements `–webView:shouldStartLoadWithRequest:navigationType:` appropriately. This allows for tapped links to be loaded through AFNetworking, and can ensure that `canGoBack` & `canGoForward` update their values correctly. 38 | */ 39 | @interface UIWebView (AFNetworking) 40 | 41 | /** 42 | The session manager used to download all requests. 43 | */ 44 | @property (nonatomic, strong) AFHTTPSessionManager *sessionManager; 45 | 46 | /** 47 | Asynchronously loads the specified request. 48 | 49 | @param request A URL request identifying the location of the content to load. This must not be `nil`. 50 | @param progress A progress object monitoring the current download progress. 51 | @param success A block object to be executed when the request finishes loading successfully. This block returns the HTML string to be loaded by the web view, and takes two arguments: the response, and the response string. 52 | @param failure A block object to be executed when the data task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. 53 | */ 54 | - (void)loadRequest:(NSURLRequest *)request 55 | progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress 56 | success:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success 57 | failure:(nullable void (^)(NSError *error))failure; 58 | 59 | /** 60 | Asynchronously loads the data associated with a particular request with a specified MIME type and text encoding. 61 | 62 | @param request A URL request identifying the location of the content to load. This must not be `nil`. 63 | @param MIMEType The MIME type of the content. Defaults to the content type of the response if not specified. 64 | @param textEncodingName The IANA encoding name, as in `utf-8` or `utf-16`. Defaults to the response text encoding if not specified. 65 | @param progress A progress object monitoring the current download progress. 66 | @param success A block object to be executed when the request finishes loading successfully. This block returns the data to be loaded by the web view and takes two arguments: the response, and the downloaded data. 67 | @param failure A block object to be executed when the data task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. 68 | */ 69 | - (void)loadRequest:(NSURLRequest *)request 70 | MIMEType:(nullable NSString *)MIMEType 71 | textEncodingName:(nullable NSString *)textEncodingName 72 | progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress 73 | success:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))success 74 | failure:(nullable void (^)(NSError *error))failure; 75 | 76 | @end 77 | 78 | NS_ASSUME_NONNULL_END 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/FMDB/LICENSE.txt: -------------------------------------------------------------------------------- 1 | If you are using FMDB in your project, I'd love to hear about it. Let Gus know 2 | by sending an email to gus@flyingmeat.com. 3 | 4 | And if you happen to come across either Gus Mueller or Rob Ryan in a bar, you 5 | might consider purchasing a drink of their choosing if FMDB has been useful to 6 | you. 7 | 8 | Finally, and shortly, this is the MIT License. 9 | 10 | Copyright (c) 2008-2014 Flying Meat Inc. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/FMDB/src/fmdb/FMDB.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | FOUNDATION_EXPORT double FMDBVersionNumber; 4 | FOUNDATION_EXPORT const unsigned char FMDBVersionString[]; 5 | 6 | #import "FMDatabase.h" 7 | #import "FMResultSet.h" 8 | #import "FMDatabaseAdditions.h" 9 | #import "FMDatabaseQueue.h" 10 | #import "FMDatabasePool.h" 11 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJExtension.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 代码地址:https://github.com/CoderMJLee/MJExtension 8 | // 代码地址:http://code4app.com/ios/%E5%AD%97%E5%85%B8-JSON-%E4%B8%8E%E6%A8%A1%E5%9E%8B%E7%9A%84%E8%BD%AC%E6%8D%A2/5339992a933bf062608b4c57 9 | 10 | #import "NSObject+MJCoding.h" 11 | #import "NSObject+MJProperty.h" 12 | #import "NSObject+MJClass.h" 13 | #import "NSObject+MJKeyValue.h" 14 | #import "NSString+MJExtension.h" 15 | #import "MJExtensionConst.h" -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJExtensionConst.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __MJExtensionConst__H__ 3 | #define __MJExtensionConst__H__ 4 | 5 | #import 6 | 7 | // 过期 8 | #define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead) 9 | 10 | // 构建错误 11 | #define MJExtensionBuildError(clazz, msg) \ 12 | NSError *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; \ 13 | [clazz setMj_error:error]; 14 | 15 | // 日志输出 16 | #ifdef DEBUG 17 | #define MJExtensionLog(...) NSLog(__VA_ARGS__) 18 | #else 19 | #define MJExtensionLog(...) 20 | #endif 21 | 22 | /** 23 | * 断言 24 | * @param condition 条件 25 | * @param returnValue 返回值 26 | */ 27 | #define MJExtensionAssertError(condition, returnValue, clazz, msg) \ 28 | [clazz setMj_error:nil]; \ 29 | if ((condition) == NO) { \ 30 | MJExtensionBuildError(clazz, msg); \ 31 | return returnValue;\ 32 | } 33 | 34 | #define MJExtensionAssert2(condition, returnValue) \ 35 | if ((condition) == NO) return returnValue; 36 | 37 | /** 38 | * 断言 39 | * @param condition 条件 40 | */ 41 | #define MJExtensionAssert(condition) MJExtensionAssert2(condition, ) 42 | 43 | /** 44 | * 断言 45 | * @param param 参数 46 | * @param returnValue 返回值 47 | */ 48 | #define MJExtensionAssertParamNotNil2(param, returnValue) \ 49 | MJExtensionAssert2((param) != nil, returnValue) 50 | 51 | /** 52 | * 断言 53 | * @param param 参数 54 | */ 55 | #define MJExtensionAssertParamNotNil(param) MJExtensionAssertParamNotNil2(param, ) 56 | 57 | /** 58 | * 打印所有的属性 59 | */ 60 | #define MJLogAllIvars \ 61 | -(NSString *)description \ 62 | { \ 63 | return [self mj_keyValues].description; \ 64 | } 65 | #define MJExtensionLogAllProperties MJLogAllIvars 66 | 67 | /** 68 | * 类型(属性类型) 69 | */ 70 | extern NSString *const MJPropertyTypeInt; 71 | extern NSString *const MJPropertyTypeShort; 72 | extern NSString *const MJPropertyTypeFloat; 73 | extern NSString *const MJPropertyTypeDouble; 74 | extern NSString *const MJPropertyTypeLong; 75 | extern NSString *const MJPropertyTypeLongLong; 76 | extern NSString *const MJPropertyTypeChar; 77 | extern NSString *const MJPropertyTypeBOOL1; 78 | extern NSString *const MJPropertyTypeBOOL2; 79 | extern NSString *const MJPropertyTypePointer; 80 | 81 | extern NSString *const MJPropertyTypeIvar; 82 | extern NSString *const MJPropertyTypeMethod; 83 | extern NSString *const MJPropertyTypeBlock; 84 | extern NSString *const MJPropertyTypeClass; 85 | extern NSString *const MJPropertyTypeSEL; 86 | extern NSString *const MJPropertyTypeId; 87 | 88 | #endif -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJExtensionConst.m: -------------------------------------------------------------------------------- 1 | #ifndef __MJExtensionConst__M__ 2 | #define __MJExtensionConst__M__ 3 | 4 | #import 5 | 6 | /** 7 | * 成员变量类型(属性类型) 8 | */ 9 | NSString *const MJPropertyTypeInt = @"i"; 10 | NSString *const MJPropertyTypeShort = @"s"; 11 | NSString *const MJPropertyTypeFloat = @"f"; 12 | NSString *const MJPropertyTypeDouble = @"d"; 13 | NSString *const MJPropertyTypeLong = @"l"; 14 | NSString *const MJPropertyTypeLongLong = @"q"; 15 | NSString *const MJPropertyTypeChar = @"c"; 16 | NSString *const MJPropertyTypeBOOL1 = @"c"; 17 | NSString *const MJPropertyTypeBOOL2 = @"b"; 18 | NSString *const MJPropertyTypePointer = @"*"; 19 | 20 | NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}"; 21 | NSString *const MJPropertyTypeMethod = @"^{objc_method=}"; 22 | NSString *const MJPropertyTypeBlock = @"@?"; 23 | NSString *const MJPropertyTypeClass = @"#"; 24 | NSString *const MJPropertyTypeSEL = @":"; 25 | NSString *const MJPropertyTypeId = @"@"; 26 | 27 | #endif -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJFoundation.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJFoundation.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 14/7/16. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MJFoundation : NSObject 12 | + (BOOL)isClassFromFoundation:(Class)c; 13 | @end 14 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJFoundation.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJFoundation.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 14/7/16. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJFoundation.h" 10 | #import "MJExtensionConst.h" 11 | #import 12 | 13 | static NSSet *foundationClasses_; 14 | 15 | @implementation MJFoundation 16 | 17 | + (NSSet *)foundationClasses 18 | { 19 | if (foundationClasses_ == nil) { 20 | // 集合中没有NSObject,因为几乎所有的类都是继承自NSObject,具体是不是NSObject需要特殊判断 21 | foundationClasses_ = [NSSet setWithObjects: 22 | [NSURL class], 23 | [NSDate class], 24 | [NSValue class], 25 | [NSData class], 26 | [NSError class], 27 | [NSArray class], 28 | [NSDictionary class], 29 | [NSString class], 30 | [NSAttributedString class], nil]; 31 | } 32 | return foundationClasses_; 33 | } 34 | 35 | + (BOOL)isClassFromFoundation:(Class)c 36 | { 37 | if (c == [NSObject class] || c == [NSManagedObject class]) return YES; 38 | 39 | __block BOOL result = NO; 40 | [[self foundationClasses] enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) { 41 | if ([c isSubclassOfClass:foundationClass]) { 42 | result = YES; 43 | *stop = YES; 44 | } 45 | }]; 46 | return result; 47 | } 48 | @end 49 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJProperty.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 包装一个成员属性 8 | 9 | #import 10 | #import 11 | #import "MJPropertyType.h" 12 | #import "MJPropertyKey.h" 13 | 14 | /** 15 | * 包装一个成员 16 | */ 17 | @interface MJProperty : NSObject 18 | /** 成员属性 */ 19 | @property (nonatomic, assign) objc_property_t property; 20 | /** 成员属性的名字 */ 21 | @property (nonatomic, readonly) NSString *name; 22 | 23 | /** 成员属性的类型 */ 24 | @property (nonatomic, readonly) MJPropertyType *type; 25 | /** 成员属性来源于哪个类(可能是父类) */ 26 | @property (nonatomic, assign) Class srcClass; 27 | 28 | /**** 同一个成员属性 - 父类和子类的行为可能不一致(originKey、propertyKeys、objectClassInArray) ****/ 29 | /** 设置最原始的key */ 30 | - (void)setOriginKey:(id)originKey forClass:(Class)c; 31 | /** 对应着字典中的多级key(里面存放的数组,数组里面都是MJPropertyKey对象) */ 32 | - (NSArray *)propertyKeysForClass:(Class)c; 33 | 34 | /** 模型数组中的模型类型 */ 35 | - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c; 36 | - (Class)objectClassInArrayForClass:(Class)c; 37 | /**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/ 38 | 39 | /** 40 | * 设置object的成员变量值 41 | */ 42 | - (void)setValue:(id)value forObject:(id)object; 43 | /** 44 | * 得到object的成员属性值 45 | */ 46 | - (id)valueForObject:(id)object; 47 | 48 | /** 49 | * 初始化 50 | */ 51 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJProperty.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJProperty.h" 10 | #import "MJFoundation.h" 11 | #import "MJExtensionConst.h" 12 | #import 13 | 14 | @interface MJProperty() 15 | @property (strong, nonatomic) NSMutableDictionary *propertyKeysDict; 16 | @property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict; 17 | @end 18 | 19 | @implementation MJProperty 20 | 21 | #pragma mark - 初始化 22 | - (instancetype)init 23 | { 24 | if (self = [super init]) { 25 | _propertyKeysDict = [NSMutableDictionary dictionary]; 26 | _objectClassInArrayDict = [NSMutableDictionary dictionary]; 27 | } 28 | return self; 29 | } 30 | 31 | #pragma mark - 缓存 32 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property 33 | { 34 | MJProperty *propertyObj = objc_getAssociatedObject(self, property); 35 | if (propertyObj == nil) { 36 | propertyObj = [[self alloc] init]; 37 | propertyObj.property = property; 38 | objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 39 | } 40 | return propertyObj; 41 | } 42 | 43 | #pragma mark - 公共方法 44 | - (void)setProperty:(objc_property_t)property 45 | { 46 | _property = property; 47 | 48 | MJExtensionAssertParamNotNil(property); 49 | 50 | // 1.属性名 51 | _name = @(property_getName(property)); 52 | 53 | // 2.成员类型 54 | NSString *attrs = @(property_getAttributes(property)); 55 | NSUInteger dotLoc = [attrs rangeOfString:@","].location; 56 | NSString *code = nil; 57 | NSUInteger loc = 1; 58 | if (dotLoc == NSNotFound) { // 没有, 59 | code = [attrs substringFromIndex:loc]; 60 | } else { 61 | code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc)]; 62 | } 63 | _type = [MJPropertyType cachedTypeWithCode:code]; 64 | } 65 | 66 | /** 67 | * 获得成员变量的值 68 | */ 69 | - (id)valueForObject:(id)object 70 | { 71 | if (self.type.KVCDisabled) return [NSNull null]; 72 | return [object valueForKey:self.name]; 73 | } 74 | 75 | /** 76 | * 设置成员变量的值 77 | */ 78 | - (void)setValue:(id)value forObject:(id)object 79 | { 80 | if (self.type.KVCDisabled || value == nil) return; 81 | [object setValue:value forKey:self.name]; 82 | } 83 | 84 | /** 85 | * 通过字符串key创建对应的keys 86 | */ 87 | - (NSArray *)propertyKeysWithStringKey:(NSString *)stringKey 88 | { 89 | if (stringKey.length == 0) return nil; 90 | 91 | NSMutableArray *propertyKeys = [NSMutableArray array]; 92 | // 如果有多级映射 93 | NSArray *oldKeys = [stringKey componentsSeparatedByString:@"."]; 94 | 95 | for (NSString *oldKey in oldKeys) { 96 | NSUInteger start = [oldKey rangeOfString:@"["].location; 97 | if (start != NSNotFound) { // 有索引的key 98 | NSString *prefixKey = [oldKey substringToIndex:start]; 99 | NSString *indexKey = prefixKey; 100 | if (prefixKey.length) { 101 | MJPropertyKey *propertyKey = [[MJPropertyKey alloc] init]; 102 | propertyKey.name = prefixKey; 103 | [propertyKeys addObject:propertyKey]; 104 | 105 | indexKey = [oldKey stringByReplacingOccurrencesOfString:prefixKey withString:@""]; 106 | } 107 | 108 | /** 解析索引 **/ 109 | // 元素 110 | NSArray *cmps = [[indexKey stringByReplacingOccurrencesOfString:@"[" withString:@""] componentsSeparatedByString:@"]"]; 111 | for (NSInteger i = 0; i 10 | 11 | typedef enum { 12 | MJPropertyKeyTypeDictionary = 0, // 字典的key 13 | MJPropertyKeyTypeArray // 数组的key 14 | } MJPropertyKeyType; 15 | 16 | /** 17 | * 属性的key 18 | */ 19 | @interface MJPropertyKey : NSObject 20 | /** key的名字 */ 21 | @property (copy, nonatomic) NSString *name; 22 | /** key的种类,可能是@"10",可能是@"age" */ 23 | @property (assign, nonatomic) MJPropertyKeyType type; 24 | 25 | /** 26 | * 根据当前的key,也就是name,从object(字典或者数组)中取值 27 | */ 28 | - (id)valueInObject:(id)object; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJPropertyKey.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJPropertyKey.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/8/11. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJPropertyKey.h" 10 | 11 | @implementation MJPropertyKey 12 | 13 | - (id)valueInObject:(id)object 14 | { 15 | if ([object isKindOfClass:[NSDictionary class]] && self.type == MJPropertyKeyTypeDictionary) { 16 | return object[self.name]; 17 | } else if ([object isKindOfClass:[NSArray class]] && self.type == MJPropertyKeyTypeArray) { 18 | NSArray *array = object; 19 | NSUInteger index = self.name.intValue; 20 | if (index < array.count) return array[index]; 21 | return nil; 22 | } 23 | return nil; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJPropertyType.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJPropertyType.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 包装一种类型 8 | 9 | #import 10 | 11 | /** 12 | * 包装一种类型 13 | */ 14 | @interface MJPropertyType : NSObject 15 | /** 类型标识符 */ 16 | @property (nonatomic, copy) NSString *code; 17 | 18 | /** 是否为id类型 */ 19 | @property (nonatomic, readonly, getter=isIdType) BOOL idType; 20 | 21 | /** 是否为基本数字类型:int、float等 */ 22 | @property (nonatomic, readonly, getter=isNumberType) BOOL numberType; 23 | 24 | /** 是否为BOOL类型 */ 25 | @property (nonatomic, readonly, getter=isBoolType) BOOL boolType; 26 | 27 | /** 对象类型(如果是基本数据类型,此值为nil) */ 28 | @property (nonatomic, readonly) Class typeClass; 29 | 30 | /** 类型是否来自于Foundation框架,比如NSString、NSArray */ 31 | @property (nonatomic, readonly, getter = isFromFoundation) BOOL fromFoundation; 32 | /** 类型是否不支持KVC */ 33 | @property (nonatomic, readonly, getter = isKVCDisabled) BOOL KVCDisabled; 34 | 35 | /** 36 | * 获得缓存的类型对象 37 | */ 38 | + (instancetype)cachedTypeWithCode:(NSString *)code; 39 | @end -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/MJPropertyType.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJPropertyType.m 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJPropertyType.h" 10 | #import "MJExtension.h" 11 | #import "MJFoundation.h" 12 | #import "MJExtensionConst.h" 13 | 14 | @implementation MJPropertyType 15 | 16 | static NSMutableDictionary *types_; 17 | + (void)initialize 18 | { 19 | types_ = [NSMutableDictionary dictionary]; 20 | } 21 | 22 | + (instancetype)cachedTypeWithCode:(NSString *)code 23 | { 24 | MJExtensionAssertParamNotNil2(code, nil); 25 | @synchronized (self) { 26 | MJPropertyType *type = types_[code]; 27 | if (type == nil) { 28 | type = [[self alloc] init]; 29 | type.code = code; 30 | types_[code] = type; 31 | } 32 | return type; 33 | } 34 | } 35 | 36 | #pragma mark - 公共方法 37 | - (void)setCode:(NSString *)code 38 | { 39 | _code = code; 40 | 41 | MJExtensionAssertParamNotNil(code); 42 | 43 | if ([code isEqualToString:MJPropertyTypeId]) { 44 | _idType = YES; 45 | } else if (code.length == 0) { 46 | _KVCDisabled = YES; 47 | } else if (code.length > 3 && [code hasPrefix:@"@\""]) { 48 | // 去掉@"和",截取中间的类型名称 49 | _code = [code substringWithRange:NSMakeRange(2, code.length - 3)]; 50 | _typeClass = NSClassFromString(_code); 51 | _fromFoundation = [MJFoundation isClassFromFoundation:_typeClass]; 52 | _numberType = [_typeClass isSubclassOfClass:[NSNumber class]]; 53 | 54 | } else if ([code isEqualToString:MJPropertyTypeSEL] || 55 | [code isEqualToString:MJPropertyTypeIvar] || 56 | [code isEqualToString:MJPropertyTypeMethod]) { 57 | _KVCDisabled = YES; 58 | } 59 | 60 | // 是否为数字类型 61 | NSString *lowerCode = _code.lowercaseString; 62 | NSArray *numberTypes = @[MJPropertyTypeInt, MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar]; 63 | if ([numberTypes containsObject:lowerCode]) { 64 | _numberType = YES; 65 | 66 | if ([lowerCode isEqualToString:MJPropertyTypeBOOL1] 67 | || [lowerCode isEqualToString:MJPropertyTypeBOOL2]) { 68 | _boolType = YES; 69 | } 70 | } 71 | } 72 | @end 73 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSObject+MJClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJClass.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/8/11. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 遍历所有类的block(父类) 13 | */ 14 | typedef void (^MJClassesEnumeration)(Class c, BOOL *stop); 15 | 16 | /** 这个数组中的属性名才会进行字典和模型的转换 */ 17 | typedef NSArray * (^MJAllowedPropertyNames)(); 18 | /** 这个数组中的属性名才会进行归档 */ 19 | typedef NSArray * (^MJAllowedCodingPropertyNames)(); 20 | 21 | /** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ 22 | typedef NSArray * (^MJIgnoredPropertyNames)(); 23 | /** 这个数组中的属性名将会被忽略:不进行归档 */ 24 | typedef NSArray * (^MJIgnoredCodingPropertyNames)(); 25 | 26 | /** 27 | * 类相关的扩展 28 | */ 29 | @interface NSObject (MJClass) 30 | /** 31 | * 遍历所有的类 32 | */ 33 | + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration; 34 | + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration; 35 | 36 | #pragma mark - 属性白名单配置 37 | /** 38 | * 这个数组中的属性名才会进行字典和模型的转换 39 | * 40 | * @param allowedPropertyNames 这个数组中的属性名才会进行字典和模型的转换 41 | */ 42 | + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; 43 | 44 | /** 45 | * 这个数组中的属性名才会进行字典和模型的转换 46 | */ 47 | + (NSMutableArray *)mj_totalAllowedPropertyNames; 48 | 49 | #pragma mark - 属性黑名单配置 50 | /** 51 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 52 | * 53 | * @param ignoredPropertyNames 这个数组中的属性名将会被忽略:不进行字典和模型的转换 54 | */ 55 | + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames; 56 | 57 | /** 58 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 59 | */ 60 | + (NSMutableArray *)mj_totalIgnoredPropertyNames; 61 | 62 | #pragma mark - 归档属性白名单配置 63 | /** 64 | * 这个数组中的属性名才会进行归档 65 | * 66 | * @param allowedCodingPropertyNames 这个数组中的属性名才会进行归档 67 | */ 68 | + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames; 69 | 70 | /** 71 | * 这个数组中的属性名才会进行字典和模型的转换 72 | */ 73 | + (NSMutableArray *)mj_totalAllowedCodingPropertyNames; 74 | 75 | #pragma mark - 归档属性黑名单配置 76 | /** 77 | * 这个数组中的属性名将会被忽略:不进行归档 78 | * 79 | * @param ignoredCodingPropertyNames 这个数组中的属性名将会被忽略:不进行归档 80 | */ 81 | + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames; 82 | 83 | /** 84 | * 这个数组中的属性名将会被忽略:不进行归档 85 | */ 86 | + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames; 87 | 88 | #pragma mark - 内部使用 89 | + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key; 90 | @end 91 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSObject+MJClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJClass.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/8/11. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJClass.h" 10 | #import "NSObject+MJCoding.h" 11 | #import "NSObject+MJKeyValue.h" 12 | #import "MJFoundation.h" 13 | #import 14 | 15 | static const char MJAllowedPropertyNamesKey = '\0'; 16 | static const char MJIgnoredPropertyNamesKey = '\0'; 17 | static const char MJAllowedCodingPropertyNamesKey = '\0'; 18 | static const char MJIgnoredCodingPropertyNamesKey = '\0'; 19 | 20 | static NSMutableDictionary *allowedPropertyNamesDict_; 21 | static NSMutableDictionary *ignoredPropertyNamesDict_; 22 | static NSMutableDictionary *allowedCodingPropertyNamesDict_; 23 | static NSMutableDictionary *ignoredCodingPropertyNamesDict_; 24 | 25 | @implementation NSObject (MJClass) 26 | 27 | + (void)load 28 | { 29 | allowedPropertyNamesDict_ = [NSMutableDictionary dictionary]; 30 | ignoredPropertyNamesDict_ = [NSMutableDictionary dictionary]; 31 | allowedCodingPropertyNamesDict_ = [NSMutableDictionary dictionary]; 32 | ignoredCodingPropertyNamesDict_ = [NSMutableDictionary dictionary]; 33 | } 34 | 35 | + (NSMutableDictionary *)dictForKey:(const void *)key 36 | { 37 | @synchronized (self) { 38 | if (key == &MJAllowedPropertyNamesKey) return allowedPropertyNamesDict_; 39 | if (key == &MJIgnoredPropertyNamesKey) return ignoredPropertyNamesDict_; 40 | if (key == &MJAllowedCodingPropertyNamesKey) return allowedCodingPropertyNamesDict_; 41 | if (key == &MJIgnoredCodingPropertyNamesKey) return ignoredCodingPropertyNamesDict_; 42 | return nil; 43 | } 44 | } 45 | 46 | + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration 47 | { 48 | // 1.没有block就直接返回 49 | if (enumeration == nil) return; 50 | 51 | // 2.停止遍历的标记 52 | BOOL stop = NO; 53 | 54 | // 3.当前正在遍历的类 55 | Class c = self; 56 | 57 | // 4.开始遍历每一个类 58 | while (c && !stop) { 59 | // 4.1.执行操作 60 | enumeration(c, &stop); 61 | 62 | // 4.2.获得父类 63 | c = class_getSuperclass(c); 64 | 65 | if ([MJFoundation isClassFromFoundation:c]) break; 66 | } 67 | } 68 | 69 | + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration 70 | { 71 | // 1.没有block就直接返回 72 | if (enumeration == nil) return; 73 | 74 | // 2.停止遍历的标记 75 | BOOL stop = NO; 76 | 77 | // 3.当前正在遍历的类 78 | Class c = self; 79 | 80 | // 4.开始遍历每一个类 81 | while (c && !stop) { 82 | // 4.1.执行操作 83 | enumeration(c, &stop); 84 | 85 | // 4.2.获得父类 86 | c = class_getSuperclass(c); 87 | } 88 | } 89 | 90 | #pragma mark - 属性黑名单配置 91 | + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames 92 | { 93 | [self mj_setupBlockReturnValue:ignoredPropertyNames key:&MJIgnoredPropertyNamesKey]; 94 | } 95 | 96 | + (NSMutableArray *)mj_totalIgnoredPropertyNames 97 | { 98 | return [self mj_totalObjectsWithSelector:@selector(mj_ignoredPropertyNames) key:&MJIgnoredPropertyNamesKey]; 99 | } 100 | 101 | #pragma mark - 归档属性黑名单配置 102 | + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames 103 | { 104 | [self mj_setupBlockReturnValue:ignoredCodingPropertyNames key:&MJIgnoredCodingPropertyNamesKey]; 105 | } 106 | 107 | + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames 108 | { 109 | return [self mj_totalObjectsWithSelector:@selector(mj_ignoredCodingPropertyNames) key:&MJIgnoredCodingPropertyNamesKey]; 110 | } 111 | 112 | #pragma mark - 属性白名单配置 113 | + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; 114 | { 115 | [self mj_setupBlockReturnValue:allowedPropertyNames key:&MJAllowedPropertyNamesKey]; 116 | } 117 | 118 | + (NSMutableArray *)mj_totalAllowedPropertyNames 119 | { 120 | return [self mj_totalObjectsWithSelector:@selector(mj_allowedPropertyNames) key:&MJAllowedPropertyNamesKey]; 121 | } 122 | 123 | #pragma mark - 归档属性白名单配置 124 | + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames 125 | { 126 | [self mj_setupBlockReturnValue:allowedCodingPropertyNames key:&MJAllowedCodingPropertyNamesKey]; 127 | } 128 | 129 | + (NSMutableArray *)mj_totalAllowedCodingPropertyNames 130 | { 131 | return [self mj_totalObjectsWithSelector:@selector(mj_allowedCodingPropertyNames) key:&MJAllowedCodingPropertyNamesKey]; 132 | } 133 | #pragma mark - block和方法处理:存储block的返回值 134 | + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key 135 | { 136 | if (block) { 137 | objc_setAssociatedObject(self, key, block(), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 138 | } else { 139 | objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 140 | } 141 | 142 | // 清空数据 143 | [[self dictForKey:key] removeAllObjects]; 144 | } 145 | 146 | + (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key 147 | { 148 | NSMutableArray *array = [self dictForKey:key][NSStringFromClass(self)]; 149 | if (array) return array; 150 | 151 | // 创建、存储 152 | [self dictForKey:key][NSStringFromClass(self)] = array = [NSMutableArray array]; 153 | 154 | if ([self respondsToSelector:selector]) { 155 | #pragma clang diagnostic push 156 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 157 | NSArray *subArray = [self performSelector:selector]; 158 | #pragma clang diagnostic pop 159 | if (subArray) { 160 | [array addObjectsFromArray:subArray]; 161 | } 162 | } 163 | 164 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 165 | NSArray *subArray = objc_getAssociatedObject(c, key); 166 | [array addObjectsFromArray:subArray]; 167 | }]; 168 | return array; 169 | } 170 | @end 171 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSObject+MJCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJCoding.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJExtensionConst.h" 11 | 12 | /** 13 | * Codeing协议 14 | */ 15 | @protocol MJCoding 16 | @optional 17 | /** 18 | * 这个数组中的属性名才会进行归档 19 | */ 20 | + (NSArray *)mj_allowedCodingPropertyNames; 21 | /** 22 | * 这个数组中的属性名将会被忽略:不进行归档 23 | */ 24 | + (NSArray *)mj_ignoredCodingPropertyNames; 25 | @end 26 | 27 | @interface NSObject (MJCoding) 28 | /** 29 | * 解码(从文件中解析对象) 30 | */ 31 | - (void)mj_decode:(NSCoder *)decoder; 32 | /** 33 | * 编码(将对象写入文件中) 34 | */ 35 | - (void)mj_encode:(NSCoder *)encoder; 36 | @end 37 | 38 | /** 39 | 归档的实现 40 | */ 41 | #define MJCodingImplementation \ 42 | - (id)initWithCoder:(NSCoder *)decoder \ 43 | { \ 44 | if (self = [super init]) { \ 45 | [self mj_decode:decoder]; \ 46 | } \ 47 | return self; \ 48 | } \ 49 | \ 50 | - (void)encodeWithCoder:(NSCoder *)encoder \ 51 | { \ 52 | [self mj_encode:encoder]; \ 53 | } 54 | 55 | #define MJExtensionCodingImplementation MJCodingImplementation -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSObject+MJCoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJCoding.m 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJCoding.h" 10 | #import "NSObject+MJClass.h" 11 | #import "NSObject+MJProperty.h" 12 | #import "MJProperty.h" 13 | 14 | @implementation NSObject (MJCoding) 15 | 16 | - (void)mj_encode:(NSCoder *)encoder 17 | { 18 | Class clazz = [self class]; 19 | 20 | NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames]; 21 | NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames]; 22 | 23 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { 24 | // 检测是否被忽略 25 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; 26 | if ([ignoredCodingPropertyNames containsObject:property.name]) return; 27 | 28 | id value = [property valueForObject:self]; 29 | if (value == nil) return; 30 | [encoder encodeObject:value forKey:property.name]; 31 | }]; 32 | } 33 | 34 | - (void)mj_decode:(NSCoder *)decoder 35 | { 36 | Class clazz = [self class]; 37 | 38 | NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames]; 39 | NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames]; 40 | 41 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { 42 | // 检测是否被忽略 43 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; 44 | if ([ignoredCodingPropertyNames containsObject:property.name]) return; 45 | 46 | id value = [decoder decodeObjectForKey:property.name]; 47 | if (value == nil) { // 兼容以前的MJExtension版本 48 | value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]]; 49 | } 50 | if (value == nil) return; 51 | [property setValue:value forObject:self]; 52 | }]; 53 | } 54 | @end 55 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSObject+MJProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJProperty.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJExtensionConst.h" 11 | 12 | @class MJProperty; 13 | 14 | /** 15 | * 遍历成员变量用的block 16 | * 17 | * @param property 成员的包装对象 18 | * @param stop YES代表停止遍历,NO代表继续遍历 19 | */ 20 | typedef void (^MJPropertiesEnumeration)(MJProperty *property, BOOL *stop); 21 | 22 | /** 将属性名换为其他key去字典中取值 */ 23 | typedef NSDictionary * (^MJReplacedKeyFromPropertyName)(); 24 | typedef id (^MJReplacedKeyFromPropertyName121)(NSString *propertyName); 25 | /** 数组中需要转换的模型类 */ 26 | typedef NSDictionary * (^MJObjectClassInArray)(); 27 | /** 用于过滤字典中的值 */ 28 | typedef id (^MJNewValueFromOldValue)(id object, id oldValue, MJProperty *property); 29 | 30 | /** 31 | * 成员属性相关的扩展 32 | */ 33 | @interface NSObject (MJProperty) 34 | #pragma mark - 遍历 35 | /** 36 | * 遍历所有的成员 37 | */ 38 | + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration; 39 | 40 | #pragma mark - 新值配置 41 | /** 42 | * 用于过滤字典中的值 43 | * 44 | * @param newValueFormOldValue 用于过滤字典中的值 45 | */ 46 | + (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue; 47 | + (id)mj_getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property; 48 | 49 | #pragma mark - key配置 50 | /** 51 | * 将属性名换为其他key去字典中取值 52 | * 53 | * @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值 54 | */ 55 | + (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName; 56 | /** 57 | * 将属性名换为其他key去字典中取值 58 | * 59 | * @param replacedKeyFromPropertyName121 将属性名换为其他key去字典中取值 60 | */ 61 | + (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121; 62 | 63 | #pragma mark - array model class配置 64 | /** 65 | * 数组中需要转换的模型类 66 | * 67 | * @param objectClassInArray 数组中需要转换的模型类 68 | */ 69 | + (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray; 70 | @end 71 | 72 | @interface NSObject (MJPropertyDeprecated_v_2_5_16) 73 | + (void)enumerateProperties:(MJPropertiesEnumeration)enumeration MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 74 | + (void)setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 75 | + (id)getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 76 | + (void)setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 77 | + (void)setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121 MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 78 | + (void)setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 79 | @end -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSString+MJExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MJExtension.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/6/7. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJExtensionConst.h" 11 | 12 | @interface NSString (MJExtension) 13 | /** 14 | * 驼峰转下划线(loveYou -> love_you) 15 | */ 16 | - (NSString *)mj_underlineFromCamel; 17 | /** 18 | * 下划线转驼峰(love_you -> loveYou) 19 | */ 20 | - (NSString *)mj_camelFromUnderline; 21 | /** 22 | * 首字母变大写 23 | */ 24 | - (NSString *)mj_firstCharUpper; 25 | /** 26 | * 首字母变小写 27 | */ 28 | - (NSString *)mj_firstCharLower; 29 | 30 | - (BOOL)mj_isPureInt; 31 | 32 | - (NSURL *)mj_url; 33 | @end 34 | 35 | @interface NSString (MJExtensionDeprecated_v_2_5_16) 36 | - (NSString *)underlineFromCamel MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 37 | - (NSString *)camelFromUnderline MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 38 | - (NSString *)firstCharUpper MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 39 | - (NSString *)firstCharLower MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 40 | - (BOOL)isPureInt MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 41 | - (NSURL *)url MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 42 | @end 43 | -------------------------------------------------------------------------------- /HWDownloadDemo/Vender/MJExtension/MJExtension/NSString+MJExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MJExtension.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/6/7. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSString+MJExtension.h" 10 | 11 | @implementation NSString (MJExtension) 12 | - (NSString *)mj_underlineFromCamel 13 | { 14 | if (self.length == 0) return self; 15 | NSMutableString *string = [NSMutableString string]; 16 | for (NSUInteger i = 0; i= 2) [string appendString:[cmp substringFromIndex:1]]; 40 | } else { 41 | [string appendString:cmp]; 42 | } 43 | } 44 | return string; 45 | } 46 | 47 | - (NSString *)mj_firstCharLower 48 | { 49 | if (self.length == 0) return self; 50 | NSMutableString *string = [NSMutableString string]; 51 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].lowercaseString]; 52 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; 53 | return string; 54 | } 55 | 56 | - (NSString *)mj_firstCharUpper 57 | { 58 | if (self.length == 0) return self; 59 | NSMutableString *string = [NSMutableString string]; 60 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].uppercaseString]; 61 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; 62 | return string; 63 | } 64 | 65 | - (BOOL)mj_isPureInt 66 | { 67 | NSScanner *scan = [NSScanner scannerWithString:self]; 68 | int val; 69 | return [scan scanInt:&val] && [scan isAtEnd]; 70 | } 71 | 72 | - (NSURL *)mj_url 73 | { 74 | // [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"!$&'()*+,-./:;=?@_~%#[]"]]; 75 | #pragma clang diagnostic push 76 | #pragma clang diagnostic ignored"-Wdeprecated-declarations" 77 | return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))]; 78 | #pragma clang diagnostic pop 79 | } 80 | @end 81 | 82 | @implementation NSString (MJExtensionDeprecated_v_2_5_16) 83 | - (NSString *)underlineFromCamel 84 | { 85 | return self.mj_underlineFromCamel; 86 | } 87 | 88 | - (NSString *)camelFromUnderline 89 | { 90 | return self.mj_camelFromUnderline; 91 | } 92 | 93 | - (NSString *)firstCharLower 94 | { 95 | return self.mj_firstCharLower; 96 | } 97 | 98 | - (NSString *)firstCharUpper 99 | { 100 | return self.mj_firstCharUpper; 101 | } 102 | 103 | - (BOOL)isPureInt 104 | { 105 | return self.mj_isPureInt; 106 | } 107 | 108 | - (NSURL *)url 109 | { 110 | return self.mj_url; 111 | } 112 | @end 113 | -------------------------------------------------------------------------------- /HWDownloadDemoTests/HWDownloadDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadDemoTests.m 3 | // HWDownloadDemoTests 4 | // 5 | // Created by wangqibin on 2018/5/21. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWDownloadDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation HWDownloadDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /HWDownloadDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /HWDownloadDemoUITests/HWDownloadDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // HWDownloadDemoUITests.m 3 | // HWDownloadDemoUITests 4 | // 5 | // Created by wangqibin on 2018/5/21. 6 | // Copyright © 2018年 hero. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HWDownloadDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation HWDownloadDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /HWDownloadDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HWDownloadDemo 2 | 文件下载功能,包含大文件下载,后台下载,杀死进程,重新启动时继续下载,设置下载并发数,监听网络改变等。 3 | CSDN博客:https://blog.csdn.net/hero_wqb/article/details/80407478 4 | --------------------------------------------------------------------------------