├── Demo2
├── BG.png
├── cute_girl.jpg
├── whiteplaceholder.png
├── PathCover
│ ├── Resources
│ │ ├── circle.png
│ │ ├── meicon.png
│ │ ├── circle@2x.png
│ │ ├── pullrefresh.aif
│ │ └── MenuBackground@2x.png
│ ├── XHSoundManager.h
│ ├── XHWaterDropRefresh.h
│ ├── XHSoundManager.m
│ ├── XHPathCover.h
│ └── XHWaterDropRefresh.m
├── MJRefresh
│ ├── MJRefresh.bundle
│ │ └── arrow@2x.png
│ ├── MJRefresh.h
│ ├── MJRefreshLegendFooter.h
│ ├── MJRefreshLegendHeader.h
│ ├── MJRefreshGifFooter.h
│ ├── MJRefreshGifHeader.h
│ ├── UIView+MJExtension.h
│ ├── UIScrollView+MJExtension.h
│ ├── MJRefreshConst.m
│ ├── MJRefreshComponent.h
│ ├── MJRefreshFooter.h
│ ├── MJRefreshHeader.h
│ ├── UIView+MJExtension.m
│ ├── MJRefreshConst.h
│ ├── MJRefreshLegendFooter.m
│ ├── MJRefreshComponent.m
│ ├── MJRefreshGifFooter.m
│ ├── UIScrollView+MJExtension.m
│ ├── MJRefreshLegendHeader.m
│ ├── MJRefreshGifHeader.m
│ ├── UIScrollView+MJRefresh.h
│ ├── UIScrollView+MJRefresh.m
│ └── MJRefreshFooter.m
├── ProgressHUD
│ ├── ProgressHUD.bundle
│ │ ├── progresshud-error@2x.png
│ │ └── progresshud-success@2x.png
│ └── ProgressHUD.h
├── UIviewExtension.swift
├── bridging.h
├── Demo2.xcdatamodeld
│ ├── .xccurrentversion
│ └── Demo2.xcdatamodel
│ │ └── contents
├── SDWebImage
│ ├── UIImage+MultiFormat.h
│ ├── SDWebImageOperation.h
│ ├── UIImage+GIF.h
│ ├── SDWebImageDecoder.h
│ ├── UIImage+WebP.h
│ ├── NSData+ImageContentType.h
│ ├── UIView+WebCacheOperation.h
│ ├── NSData+ImageContentType.m
│ ├── SDWebImageCompat.m
│ ├── SDWebImageDecoder.m
│ ├── SDWebImageCompat.h
│ ├── UIView+WebCacheOperation.m
│ ├── UIImage+WebP.m
│ ├── SDWebImageDownloaderOperation.h
│ ├── UIImage+MultiFormat.m
│ ├── SDWebImagePrefetcher.h
│ ├── UIImageView+HighlightedWebCache.m
│ ├── MKAnnotationView+WebCache.m
│ ├── UIImageView+HighlightedWebCache.h
│ ├── UIImage+GIF.m
│ ├── SDWebImagePrefetcher.m
│ ├── MKAnnotationView+WebCache.h
│ ├── SDWebImageDownloader.h
│ ├── SDImageCache.h
│ └── UIImageView+WebCache.h
├── HZIndicatorView.h
├── HZPhotoBrowserView.h
├── XActionSheet.h
├── HZPhotoBrowser.h
├── HZPhotoBrowserConfig.h
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── LineView.swift
├── HZIndicatorView.m
├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.xib
├── XActionSheet.m
├── AppDelegate.swift
├── ViewController.swift
└── HZPhotoBrowserView.m
├── Demo2.xcodeproj
├── xcuserdata
│ └── xlx.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── Demo2.xcscheme
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ └── xlx.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ └── Demo2.xccheckout
└── Demo2Tests
├── Info.plist
└── Demo2Tests.swift
/Demo2/BG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/BG.png
--------------------------------------------------------------------------------
/Demo2/cute_girl.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/cute_girl.jpg
--------------------------------------------------------------------------------
/Demo2/whiteplaceholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/whiteplaceholder.png
--------------------------------------------------------------------------------
/Demo2/PathCover/Resources/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/PathCover/Resources/circle.png
--------------------------------------------------------------------------------
/Demo2/PathCover/Resources/meicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/PathCover/Resources/meicon.png
--------------------------------------------------------------------------------
/Demo2/PathCover/Resources/circle@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/PathCover/Resources/circle@2x.png
--------------------------------------------------------------------------------
/Demo2/PathCover/Resources/pullrefresh.aif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/PathCover/Resources/pullrefresh.aif
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefresh.bundle/arrow@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/MJRefresh/MJRefresh.bundle/arrow@2x.png
--------------------------------------------------------------------------------
/Demo2/PathCover/Resources/MenuBackground@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/PathCover/Resources/MenuBackground@2x.png
--------------------------------------------------------------------------------
/Demo2/ProgressHUD/ProgressHUD.bundle/progresshud-error@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/ProgressHUD/ProgressHUD.bundle/progresshud-error@2x.png
--------------------------------------------------------------------------------
/Demo2/ProgressHUD/ProgressHUD.bundle/progresshud-success@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2/ProgressHUD/ProgressHUD.bundle/progresshud-success@2x.png
--------------------------------------------------------------------------------
/Demo2/UIviewExtension.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 |
5 | extension UIView {
6 | func sayHello(){
7 | println("哈喽,大家好,花川学院的学员们")
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/Demo2.xcodeproj/xcuserdata/xlx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Demo2/bridging.h:
--------------------------------------------------------------------------------
1 | #import "MJRefresh.h"
2 | #import "ProgressHUD.h"
3 | #import "XHPathCover.h"
4 | #import "UIImageView+WebCache.h"
5 | #import "HZPhotoBrowser.h"
6 | #import "XActionSheet.h"
--------------------------------------------------------------------------------
/Demo2.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo2.xcodeproj/project.xcworkspace/xcuserdata/xlx.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superxlx/Demo2/HEAD/Demo2.xcodeproj/project.xcworkspace/xcuserdata/xlx.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Demo2/Demo2.xcdatamodeld/.xccurrentversion:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | _XCCurrentVersionName
6 | Demo2.xcdatamodel
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImage+MultiFormat.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+MultiFormat.h
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 07/06/13.
6 | // Copyright (c) 2013 Dailymotion. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (MultiFormat)
12 |
13 | + (UIImage *)sd_imageWithData:(NSData *)data;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo2/HZIndicatorView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HZIndicatorView.h
3 | // photoBrowser
4 | //
5 | // Created by huangzhenyu on 15/6/23.
6 | // Copyright (c) 2015年 eamon. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HZIndicatorView : UIView
12 | @property (nonatomic, assign) CGFloat progress;
13 | @property (nonatomic, assign) int viewMode;//显示模式
14 | @end
15 |
--------------------------------------------------------------------------------
/Demo2/Demo2.xcdatamodeld/Demo2.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Demo2/PathCover/XHSoundManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // XHSoundManager.h
3 | // XHPathCover
4 | //
5 | // Created by 曾 宪华 on 14-2-7.
6 | // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface XHSoundManager : NSObject
12 |
13 | + (instancetype)sharedInstance;
14 |
15 | - (void)playRefreshSound;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageOperation.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 |
11 | @protocol SDWebImageOperation
12 |
13 | - (void)cancel;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefresh.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 |
4 | #import "UIScrollView+MJRefresh.h"
5 | #import "MJRefreshGifHeader.h"
6 | #import "MJRefreshLegendHeader.h"
7 | #import "MJRefreshGifFooter.h"
8 | #import "MJRefreshLegendFooter.h"
9 | #import "MJRefreshConst.h"
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImage+GIF.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+GIF.h
3 | // LBGIFImage
4 | //
5 | // Created by Laurin Brandner on 06.01.12.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (GIF)
12 |
13 | + (UIImage *)sd_animatedGIFNamed:(NSString *)name;
14 |
15 | + (UIImage *)sd_animatedGIFWithData:(NSData *)data;
16 |
17 | - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshLegendFooter.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshLegendFooter.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/5.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshFooter.h"
11 |
12 | @interface MJRefreshLegendFooter : MJRefreshFooter
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshLegendHeader.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshLegendHeader.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | // 传统的下拉刷新控件:箭头 + 圈圈
9 |
10 | #import "MJRefreshHeader.h"
11 |
12 | @interface MJRefreshLegendHeader : MJRefreshHeader
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageDecoder.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * Created by james on 9/28/11.
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 |
11 | #import
12 | #import "SDWebImageCompat.h"
13 |
14 | @interface UIImage (ForceDecode)
15 |
16 | + (UIImage *)decodedImageWithImage:(UIImage *)image;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshGifFooter.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshGifFooter.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/5.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshFooter.h"
11 |
12 | @interface MJRefreshGifFooter : MJRefreshFooter
13 | /** 正在刷新时的动画图片 */
14 | @property (strong, nonatomic) NSArray *refreshingImages;
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImage+WebP.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+WebP.h
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 07/06/13.
6 | // Copyright (c) 2013 Dailymotion. All rights reserved.
7 | //
8 |
9 | #ifdef SD_WEBP
10 |
11 | #import
12 |
13 | // Fix for issue #416 Undefined symbols for architecture armv7 since WebP introduction when deploying to device
14 | void WebPInitPremultiplyNEON(void);
15 |
16 | void WebPInitUpsamplersNEON(void);
17 |
18 | void VP8DspInitNEON(void);
19 |
20 | @interface UIImage (WebP)
21 |
22 | + (UIImage *)sd_imageWithWebPData:(NSData *)data;
23 |
24 | @end
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshGifHeader.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshGifHeader.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | // 带有gif图片功能的下拉刷新控件
9 |
10 | #import "MJRefreshHeader.h"
11 |
12 | @interface MJRefreshGifHeader : MJRefreshHeader
13 | /** 设置state状态下的动画图片images */
14 | - (void)setImages:(NSArray *)images forState:(MJRefreshHeaderState)state;
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo2/HZPhotoBrowserView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HZPhotoBrowserView.h
3 | // photoBrowser
4 | //
5 | // Created by huangzhenyu on 15/6/23.
6 | // Copyright (c) 2015年 eamon. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HZPhotoBrowserView : UIView
12 | @property (nonatomic,strong) UIScrollView *scrollview;
13 | @property (nonatomic,strong) UIImageView *imageview;
14 | @property (nonatomic, assign) CGFloat progress;
15 | @property (nonatomic, assign) BOOL beginLoadingImage;
16 |
17 | //单击回调
18 | @property (nonatomic, strong) void (^singleTapBlock)(UITapGestureRecognizer *recognizer);
19 |
20 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
21 | @end
22 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/NSData+ImageContentType.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Fabrice Aneche on 06/01/14.
3 | // Copyright (c) 2014 Dailymotion. All rights reserved.
4 | //
5 |
6 | #import
7 |
8 | @interface NSData (ImageContentType)
9 |
10 | /**
11 | * Compute the content type for an image data
12 | *
13 | * @param data the input data
14 | *
15 | * @return the content type as string (i.e. image/jpeg, image/gif)
16 | */
17 | + (NSString *)sd_contentTypeForImageData:(NSData *)data;
18 |
19 | @end
20 |
21 |
22 | @interface NSData (ImageContentTypeDeprecated)
23 |
24 | + (NSString *)contentTypeForImageData:(NSData *)data __deprecated_msg("Use `sd_contentTypeForImageData:`");
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Demo2.xcodeproj/xcuserdata/xlx.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Demo2.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 2A02EACB1B5D50B100DAB871
16 |
17 | primary
18 |
19 |
20 | 2A02EAE31B5D50B100DAB871
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/UIView+MJExtension.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // UIView+Extension.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 14-5-28.
7 | // Copyright (c) 2014年 itcast. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 | @interface UIView (MJExtension)
13 | @property (assign, nonatomic) CGFloat mj_x;
14 | @property (assign, nonatomic) CGFloat mj_y;
15 | @property (assign, nonatomic) CGFloat mj_w;
16 | @property (assign, nonatomic) CGFloat mj_h;
17 | @property (assign, nonatomic) CGSize mj_size;
18 | @property (assign, nonatomic) CGPoint mj_origin;
19 | @end
20 |
--------------------------------------------------------------------------------
/Demo2/XActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // XActionSheet.h
3 | // Demo2
4 | //
5 | // Created by xlx on 15/7/29.
6 | // Copyright (c) 2015年 xlx. All rights reserved.
7 | //
8 |
9 | #import
10 | @class XActionSheet;
11 | @protocol XActionSheetDelegate
12 | @optional
13 | -(void)buttonClick:(NSInteger)index;
14 |
15 | @end
16 | @interface XActionSheet : UIViewController
17 |
18 | - (void)addCancelButton:(NSString *)Title;
19 | - (void)addButtonwithTitle:(NSString *)Title;
20 | - (void)addButtonWithTitleArray:(NSArray *)array;
21 |
22 | @property (nonatomic, strong) UIView *layView;
23 | @property (nonatomic, strong) UIButton *CancelButton;
24 | @property (nonatomic, strong) NSMutableArray *btnArray;
25 |
26 | @property (nonatomic, assign) iddelegate;
27 | @end
28 |
--------------------------------------------------------------------------------
/Demo2Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.xlx.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Demo2/HZPhotoBrowser.h:
--------------------------------------------------------------------------------
1 | //
2 | // HZPhotoBrowser.h
3 | // photoBrowser
4 | //
5 | // Created by huangzhenyu on 15/6/23.
6 | // Copyright (c) 2015年 eamon. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HZPhotoBrowserView.h"
11 |
12 | @class HZPhotoBrowser;
13 |
14 | @protocol HZPhotoBrowserDelegate
15 |
16 | - (UIImage *)photoBrowser:(HZPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index;
17 | - (NSURL *)photoBrowser:(HZPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index;
18 | @end
19 |
20 | @interface HZPhotoBrowser : UIViewController
21 |
22 | @property (nonatomic, weak) UIView *sourceImagesContainerView;
23 | @property (nonatomic, assign) int currentImageIndex;
24 | @property (nonatomic, assign) NSInteger imageCount;//图片总数
25 |
26 | @property (nonatomic, weak) id delegate;
27 |
28 | - (void)show;
29 | @end
30 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/UIScrollView+MJExtension.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // UIScrollView+Extension.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 14-5-28.
7 | // Copyright (c) 2014年 itcast. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 | @interface UIScrollView (MJExtension)
13 | @property (assign, nonatomic) CGFloat mj_insetT;
14 | @property (assign, nonatomic) CGFloat mj_insetB;
15 | @property (assign, nonatomic) CGFloat mj_insetL;
16 | @property (assign, nonatomic) CGFloat mj_insetR;
17 |
18 | @property (assign, nonatomic) CGFloat mj_offsetX;
19 | @property (assign, nonatomic) CGFloat mj_offsetY;
20 |
21 | @property (assign, nonatomic) CGFloat mj_contentSizeW;
22 | @property (assign, nonatomic) CGFloat mj_contentSizeH;
23 | @end
24 |
--------------------------------------------------------------------------------
/Demo2/PathCover/XHWaterDropRefresh.h:
--------------------------------------------------------------------------------
1 | //
2 | // XHWaterDropRefresh.h
3 | // XHPathCover
4 | //
5 | // Created by 曾 宪华 on 14-2-7.
6 | // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface XHWaterDropRefresh : UIView
12 |
13 | @property (nonatomic, assign) CGFloat radius; // default is 5.
14 | @property (nonatomic, assign) CGFloat maxOffset; // default is 70
15 | @property (nonatomic, assign) CGFloat deformationLength; // default is 0.4 (between 0.1 -- 0.9)
16 | @property (nonatomic, assign) CGFloat offsetHeight;
17 | @property (nonatomic, strong) UIImage *refreshCircleImage;
18 | @property (nonatomic, readonly) BOOL isRefreshing;
19 |
20 | - (void)stopRefresh;
21 | - (void)startRefreshAnimation;
22 |
23 | @property (nonatomic, copy) void(^handleRefreshEvent)(void) ;
24 | @property (nonatomic) float currentOffset;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Demo2Tests/Demo2Tests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Demo2Tests.swift
3 | // Demo2Tests
4 | //
5 | // Created by xlx on 15/7/20.
6 | // Copyright (c) 2015年 xlx. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import XCTest
11 |
12 | class Demo2Tests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | XCTAssert(true, "Pass")
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measureBlock() {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Demo2/PathCover/XHSoundManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // XHSoundManager.m
3 | // XHPathCover
4 | //
5 | // Created by 曾 宪华 on 14-2-7.
6 | // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
7 | //
8 |
9 | #import "XHSoundManager.h"
10 | #import
11 |
12 | @interface XHSoundManager () {
13 | SystemSoundID refreshSound;
14 | }
15 |
16 | @end
17 |
18 | @implementation XHSoundManager
19 |
20 | + (instancetype)sharedInstance {
21 | static XHSoundManager *instance;
22 | static dispatch_once_t onceToken;
23 | dispatch_once(&onceToken, ^{
24 | instance = [[XHSoundManager alloc] init];
25 | });
26 | return instance;
27 | }
28 |
29 | - (id)init {
30 | self = [super init];
31 | if (self) {
32 | NSURL *url = [[NSBundle mainBundle] URLForResource:@"pullrefresh" withExtension:@"aif"];
33 | AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url) , &refreshSound);
34 | }
35 | return self;
36 | }
37 |
38 | - (void)playRefreshSound {
39 | AudioServicesPlaySystemSound(refreshSound);
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshConst.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | #import
4 |
5 | const CGFloat MJRefreshHeaderHeight = 54.0;
6 | const CGFloat MJRefreshFooterHeight = 44.0;
7 | const CGFloat MJRefreshFastAnimationDuration = 0.25;
8 | const CGFloat MJRefreshSlowAnimationDuration = 0.4;
9 |
10 | NSString *const MJRefreshHeaderUpdatedTimeKey = @"MJRefreshHeaderUpdatedTimeKey";
11 | NSString *const MJRefreshContentOffset = @"contentOffset";
12 | NSString *const MJRefreshContentSize = @"contentSize";
13 | NSString *const MJRefreshPanState = @"pan.state";
14 |
15 | NSString *const MJRefreshHeaderStateIdleText = @"下拉可以刷新";
16 | NSString *const MJRefreshHeaderStatePullingText = @"松开立即刷新";
17 | NSString *const MJRefreshHeaderStateRefreshingText = @"正在刷新数据中...";
18 |
19 | NSString *const MJRefreshFooterStateIdleText = @"点击加载更多";
20 | NSString *const MJRefreshFooterStateRefreshingText = @"正在加载更多的数据...";
21 | NSString *const MJRefreshFooterStateNoMoreDataText = @"已经全部加载完毕";
--------------------------------------------------------------------------------
/Demo2/HZPhotoBrowserConfig.h:
--------------------------------------------------------------------------------
1 | //
2 | // HZPhotoBrowserConfig.h
3 | // photoBrowser
4 | //
5 | // Created by huangzhenyu on 15/6/23.
6 | // Copyright (c) 2015年 eamon. All rights reserved.
7 | //
8 |
9 | typedef enum {
10 | HZIndicatorViewModeLoopDiagram, // 环形
11 | HZIndicatorViewModePieDiagram // 饼型
12 | } HZIndicatorViewMode;
13 |
14 | #define kAPPWidth [UIScreen mainScreen].bounds.size.width
15 | #define kAppHeight [UIScreen mainScreen].bounds.size.height
16 |
17 | //图片缩放比例
18 | #define kMinZoomScale 0.6f
19 | #define kMaxZoomScale 2.0f
20 |
21 | //是否支持横屏
22 | #define shouldSupportLandscape YES
23 | #define kIsFullWidthForLandScape YES //是否在横屏的时候直接满宽度,而不是满高度,一般是在有长图需求的时候设置为YES
24 |
25 | #define kIndicatorViewBackgroundColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7]
26 | #define kPhotoBrowserBackgrounColor [UIColor colorWithRed:0 green:0 blue:0 alpha:1]
27 |
28 | // 图片间的间距
29 | #define kPhotoBrowserImageViewMargin 10
30 |
31 | // 图片下载进度指示器内部控件间的间距
32 | #define kIndicatorViewItemMargin 10
33 |
34 | // browser消失的动画时长
35 | #define kPhotoBrowserHideDuration 0.4f
36 |
37 | // browser出现的动画时长
38 | #define kPhotoBrowserShowDuration 0.4f
39 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIView+WebCacheOperation.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 | #import "SDWebImageManager.h"
11 |
12 | @interface UIView (WebCacheOperation)
13 |
14 | /**
15 | * Set the image load operation (storage in a UIView based dictionary)
16 | *
17 | * @param operation the operation
18 | * @param key key for storing the operation
19 | */
20 | - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key;
21 |
22 | /**
23 | * Cancel all operations for the current UIView and key
24 | *
25 | * @param key key for identifying the operations
26 | */
27 | - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key;
28 |
29 | /**
30 | * Just remove the operations corresponding to the current UIView and key without cancelling them
31 | *
32 | * @param key key for identifying the operations
33 | */
34 | - (void)sd_removeImageLoadOperationWithKey:(NSString *)key;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshComponent.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshComponent.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | // 刷新组件:基本的开始刷新和结束刷新行为
9 |
10 | #import
11 |
12 | @interface MJRefreshComponent : UIView
13 | {
14 | UIEdgeInsets _scrollViewOriginalInset;
15 | __weak UIScrollView *_scrollView;
16 | }
17 |
18 | #pragma mark - 文字处理
19 | /** 文字颜色 */
20 | @property (strong, nonatomic) UIColor *textColor;
21 | /** 字体大小 */
22 | @property (strong, nonatomic) UIFont *font;
23 |
24 | #pragma mark - 刷新处理
25 | /** 正在刷新的回调 */
26 | @property (copy, nonatomic) void (^refreshingBlock)();
27 | /** 设置回调对象和回调方法 */
28 | - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action;
29 | @property (weak, nonatomic) id refreshingTarget;
30 | @property (assign, nonatomic) SEL refreshingAction;
31 | /** 进入刷新状态 */
32 | - (void)beginRefreshing;
33 | /** 结束刷新状态 */
34 | - (void)endRefreshing;
35 | /** 是否正在刷新 */
36 | - (BOOL)isRefreshing;
37 | @end
38 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshFooter.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshFooter.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/5.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshComponent.h"
11 |
12 | typedef enum {
13 | MJRefreshFooterStateIdle = 1, // 普通闲置状态
14 | MJRefreshFooterStateRefreshing, // 正在刷新中的状态
15 | MJRefreshFooterStateNoMoreData // 所有数据加载完毕,没有更多的数据了
16 | } MJRefreshFooterState;
17 |
18 | @interface MJRefreshFooter : MJRefreshComponent
19 | /** 提示没有更多的数据 */
20 | - (void)noticeNoMoreData;
21 | /** 重置没有更多的数据(消除没有更多数据的状态) */
22 | - (void)resetNoMoreData;
23 |
24 | /** 刷新控件的状态(交给子类重写) */
25 | @property (assign, nonatomic) MJRefreshFooterState state;
26 |
27 | /** 是否隐藏状态标签 */
28 | @property (assign, nonatomic, getter=isStateHidden) BOOL stateHidden;
29 |
30 | /**
31 | * 设置state状态下的状态文字内容title
32 | */
33 | - (void)setTitle:(NSString *)title forState:(MJRefreshFooterState)state;
34 |
35 | /** 是否自动刷新(默认为YES) */
36 | @property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh;
37 |
38 | /** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */
39 | @property (assign, nonatomic) CGFloat appearencePercentTriggerAutoRefresh;
40 | @end
41 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/NSData+ImageContentType.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Fabrice Aneche on 06/01/14.
3 | // Copyright (c) 2014 Dailymotion. All rights reserved.
4 | //
5 |
6 | #import "NSData+ImageContentType.h"
7 |
8 |
9 | @implementation NSData (ImageContentType)
10 |
11 | + (NSString *)sd_contentTypeForImageData:(NSData *)data {
12 | uint8_t c;
13 | [data getBytes:&c length:1];
14 | switch (c) {
15 | case 0xFF:
16 | return @"image/jpeg";
17 | case 0x89:
18 | return @"image/png";
19 | case 0x47:
20 | return @"image/gif";
21 | case 0x49:
22 | case 0x4D:
23 | return @"image/tiff";
24 | case 0x52:
25 | // R as RIFF for WEBP
26 | if ([data length] < 12) {
27 | return nil;
28 | }
29 |
30 | NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
31 | if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
32 | return @"image/webp";
33 | }
34 |
35 | return nil;
36 | }
37 | return nil;
38 | }
39 |
40 | @end
41 |
42 |
43 | @implementation NSData (ImageContentTypeDeprecated)
44 |
45 | + (NSString *)contentTypeForImageData:(NSData *)data {
46 | return [self sd_contentTypeForImageData:data];
47 | }
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/Demo2/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshHeader.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshHeader.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | // 下拉刷新控件:负责监控用户下拉的状态
9 |
10 | #import "MJRefreshComponent.h"
11 |
12 | // 下拉刷新控件的状态
13 | typedef enum {
14 | /** 普通闲置状态 */
15 | MJRefreshHeaderStateIdle = 1,
16 | /** 松开就可以进行刷新的状态 */
17 | MJRefreshHeaderStatePulling,
18 | /** 正在刷新中的状态 */
19 | MJRefreshHeaderStateRefreshing,
20 | /** 即将刷新的状态 */
21 | MJRefreshHeaderStateWillRefresh
22 | } MJRefreshHeaderState;
23 |
24 | @interface MJRefreshHeader : MJRefreshComponent
25 | /** 利用这个key来保存上次的刷新时间(不同界面的刷新控件应该用不同的dateKey,以区分不同界面的刷新时间) */
26 | @property (copy, nonatomic) NSString *dateKey;
27 |
28 | /** 利用这个block来决定显示的更新时间 */
29 | @property (copy, nonatomic) NSString *(^updatedTimeTitle)(NSDate *updatedTime);
30 |
31 | /**
32 | * 设置state状态下的状态文字内容title(别直接拿stateLabel修改文字)
33 | */
34 | - (void)setTitle:(NSString *)title forState:(MJRefreshHeaderState)state;
35 | /** 刷新控件的状态 */
36 | @property (assign, nonatomic) MJRefreshHeaderState state;
37 |
38 | #pragma mark - 文字控件的可见性处理
39 | /** 是否隐藏状态标签 */
40 | @property (assign, nonatomic, getter=isStateHidden) BOOL stateHidden;
41 | /** 是否隐藏刷新时间标签 */
42 | @property (assign, nonatomic, getter=isUpdatedTimeHidden) BOOL updatedTimeHidden;
43 |
44 | #pragma mark - 交给子类重写
45 | /** 下拉的百分比(交给子类重写) */
46 | @property (assign, nonatomic) CGFloat pullingPercent;
47 | @end
48 |
--------------------------------------------------------------------------------
/Demo2.xcodeproj/project.xcworkspace/xcshareddata/Demo2.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 866E8258-B2D2-4292-9E08-7A6879059963
9 | IDESourceControlProjectName
10 | Demo2
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | FCDDB4F675848B2FA8A74043A711B1BA9883CDE2
14 | https://github.com/superxlx/Demo2.git
15 |
16 | IDESourceControlProjectPath
17 | Demo2.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | FCDDB4F675848B2FA8A74043A711B1BA9883CDE2
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/superxlx/Demo2.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | FCDDB4F675848B2FA8A74043A711B1BA9883CDE2
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | FCDDB4F675848B2FA8A74043A711B1BA9883CDE2
36 | IDESourceControlWCCName
37 | XActionSheet
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Demo2/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.xlx.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
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 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageCompat.m:
--------------------------------------------------------------------------------
1 | //
2 | // SDWebImageCompat.m
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 11/12/12.
6 | // Copyright (c) 2012 Dailymotion. All rights reserved.
7 | //
8 |
9 | #import "SDWebImageCompat.h"
10 |
11 | #if !__has_feature(objc_arc)
12 | #error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
13 | #endif
14 |
15 | inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) {
16 | if (!image) {
17 | return nil;
18 | }
19 |
20 | if ([image.images count] > 0) {
21 | NSMutableArray *scaledImages = [NSMutableArray array];
22 |
23 | for (UIImage *tempImage in image.images) {
24 | [scaledImages addObject:SDScaledImageForKey(key, tempImage)];
25 | }
26 |
27 | return [UIImage animatedImageWithImages:scaledImages duration:image.duration];
28 | }
29 | else {
30 | if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
31 | CGFloat scale = [UIScreen mainScreen].scale;
32 | if (key.length >= 8) {
33 | NSRange range = [key rangeOfString:@"@2x."];
34 | if (range.location != NSNotFound) {
35 | scale = 2.0;
36 | }
37 |
38 | range = [key rangeOfString:@"@3x."];
39 | if (range.location != NSNotFound) {
40 | scale = 3.0;
41 | }
42 | }
43 |
44 | UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
45 | image = scaledImage;
46 | }
47 | return image;
48 | }
49 | }
50 |
51 | NSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain";
52 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/UIView+MJExtension.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // UIView+Extension.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 14-5-28.
7 | // Copyright (c) 2014年 itcast. All rights reserved.
8 | //
9 |
10 | #import "UIView+MJExtension.h"
11 |
12 | @implementation UIView (MJExtension)
13 | - (void)setMj_x:(CGFloat)mj_x
14 | {
15 | CGRect frame = self.frame;
16 | frame.origin.x = mj_x;
17 | self.frame = frame;
18 | }
19 |
20 | - (CGFloat)mj_x
21 | {
22 | return self.frame.origin.x;
23 | }
24 |
25 | - (void)setMj_y:(CGFloat)mj_y
26 | {
27 | CGRect frame = self.frame;
28 | frame.origin.y = mj_y;
29 | self.frame = frame;
30 | }
31 |
32 | - (CGFloat)mj_y
33 | {
34 | return self.frame.origin.y;
35 | }
36 |
37 | - (void)setMj_w:(CGFloat)mj_w
38 | {
39 | CGRect frame = self.frame;
40 | frame.size.width = mj_w;
41 | self.frame = frame;
42 | }
43 |
44 | - (CGFloat)mj_w
45 | {
46 | return self.frame.size.width;
47 | }
48 |
49 | - (void)setMj_h:(CGFloat)mj_h
50 | {
51 | CGRect frame = self.frame;
52 | frame.size.height = mj_h;
53 | self.frame = frame;
54 | }
55 |
56 | - (CGFloat)mj_h
57 | {
58 | return self.frame.size.height;
59 | }
60 |
61 | - (void)setMj_size:(CGSize)mj_size
62 | {
63 | CGRect frame = self.frame;
64 | frame.size = mj_size;
65 | self.frame = frame;
66 | }
67 |
68 | - (CGSize)mj_size
69 | {
70 | return self.frame.size;
71 | }
72 |
73 | - (void)setMj_origin:(CGPoint)mj_origin
74 | {
75 | CGRect frame = self.frame;
76 | frame.origin = mj_origin;
77 | self.frame = frame;
78 | }
79 |
80 | - (CGPoint)mj_origin
81 | {
82 | return self.frame.origin;
83 | }
84 | @end
85 |
--------------------------------------------------------------------------------
/Demo2/LineView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LineView.swift
3 | // Demo2
4 | //
5 | // Created by xlx on 15/7/27.
6 | // Copyright (c) 2015年 xlx. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LineView: UIView {
12 |
13 | var labelTile = ["动态","关注","粉丝","文章","文集"]
14 | override func drawRect(rect: CGRect) {
15 | var context = UIGraphicsGetCurrentContext()
16 | CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.3)
17 | CGContextSetLineWidth(context, 0.5)
18 |
19 | for var i = 1 ; i <= 4 ; i++ {
20 | CGContextMoveToPoint(context, (CGFloat)(i)*rect.width/5, 10)
21 | CGContextAddLineToPoint(context, (CGFloat)(i)*rect.width/5, rect.height - 10)
22 | }
23 |
24 | CGContextMoveToPoint(context, 0, 5)
25 | CGContextAddLineToPoint(context, rect.width, 5)
26 |
27 | CGContextMoveToPoint(context, 0, rect.height - 5)
28 | CGContextAddLineToPoint(context, rect.width, rect.height - 5)
29 |
30 | CGContextStrokePath(context)
31 |
32 | }
33 |
34 | override init(frame: CGRect) {
35 | super.init(frame: frame)
36 | self.backgroundColor = UIColor.whiteColor()
37 | for var i = 0 ; i<5 ; i++ {
38 | var label = UILabel(frame: CGRectMake((CGFloat)(i) * frame.width / 5, frame.height / 3, frame.width / 5, frame.height / 3 * 2))
39 |
40 | label.text = labelTile[i]
41 | label.textColor = UIColor.grayColor()
42 | label.font = UIFont.systemFontOfSize(13)
43 | label.textAlignment = NSTextAlignment.Center
44 | self.addSubview(label)
45 |
46 | }
47 |
48 |
49 | }
50 |
51 | required init(coder aDecoder: NSCoder) {
52 | fatalError("init(coder:) has not been implemented")
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshConst.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | #import
4 |
5 | // 日志输出
6 | #ifdef DEBUG
7 | #define MJLog(...) NSLog(__VA_ARGS__)
8 | #else
9 | #define MJLog(...)
10 | #endif
11 |
12 | // 过期提醒
13 | #define MJDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
14 |
15 | // 运行时objc_msgSend
16 | #define msgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__)
17 | #define msgTarget(target) (__bridge void *)(target)
18 |
19 | // RGB颜色
20 | #define MJColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
21 |
22 | // 文字颜色
23 | #define MJRefreshLabelTextColor MJColor(100, 100, 100)
24 |
25 | // 字体大小
26 | #define MJRefreshLabelFont [UIFont boldSystemFontOfSize:13]
27 |
28 | // 图片路径
29 | #define MJRefreshSrcName(file) [@"MJRefresh.bundle" stringByAppendingPathComponent:file]
30 |
31 | // 常量
32 | UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight;
33 | UIKIT_EXTERN const CGFloat MJRefreshFooterHeight;
34 | UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration;
35 | UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration;
36 |
37 | UIKIT_EXTERN NSString *const MJRefreshHeaderUpdatedTimeKey;
38 | UIKIT_EXTERN NSString *const MJRefreshContentOffset;
39 | UIKIT_EXTERN NSString *const MJRefreshContentSize;
40 | UIKIT_EXTERN NSString *const MJRefreshPanState;
41 |
42 | UIKIT_EXTERN NSString *const MJRefreshHeaderStateIdleText;
43 | UIKIT_EXTERN NSString *const MJRefreshHeaderStatePullingText;
44 | UIKIT_EXTERN NSString *const MJRefreshHeaderStateRefreshingText;
45 |
46 | UIKIT_EXTERN NSString *const MJRefreshFooterStateIdleText;
47 | UIKIT_EXTERN NSString *const MJRefreshFooterStateRefreshingText;
48 | UIKIT_EXTERN NSString *const MJRefreshFooterStateNoMoreDataText;
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageDecoder.m:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * Created by james on 9/28/11.
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 |
11 | #import "SDWebImageDecoder.h"
12 |
13 | @implementation UIImage (ForceDecode)
14 |
15 | + (UIImage *)decodedImageWithImage:(UIImage *)image {
16 | // do not decode animated images
17 | if (image.images) { return image; }
18 |
19 | CGImageRef imageRef = image.CGImage;
20 |
21 | CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
22 | BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
23 | alpha == kCGImageAlphaLast ||
24 | alpha == kCGImageAlphaPremultipliedFirst ||
25 | alpha == kCGImageAlphaPremultipliedLast);
26 |
27 | if (anyAlpha) { return image; }
28 |
29 | size_t width = CGImageGetWidth(imageRef);
30 | size_t height = CGImageGetHeight(imageRef);
31 |
32 | CGContextRef context = CGBitmapContextCreate(NULL, width,
33 | height,
34 | CGImageGetBitsPerComponent(imageRef),
35 | 0,
36 | CGImageGetColorSpace(imageRef),
37 | kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
38 |
39 | // Draw the image into the context and retrieve the new image, which will now have an alpha layer
40 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
41 | CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(context);
42 | UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha];
43 |
44 | CGContextRelease(context);
45 | CGImageRelease(imageRefWithAlpha);
46 |
47 | return imageWithAlpha;
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageCompat.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | * (c) Jamie Pinkham
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | #import
11 |
12 | #ifdef __OBJC_GC__
13 | #error SDWebImage does not support Objective-C Garbage Collection
14 | #endif
15 |
16 | #if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0
17 | #error SDWebImage doesn't support Deployement Target version < 5.0
18 | #endif
19 |
20 | #if !TARGET_OS_IPHONE
21 | #import
22 | #ifndef UIImage
23 | #define UIImage NSImage
24 | #endif
25 | #ifndef UIImageView
26 | #define UIImageView NSImageView
27 | #endif
28 | #else
29 |
30 | #import
31 |
32 | #endif
33 |
34 | #ifndef NS_ENUM
35 | #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
36 | #endif
37 |
38 | #ifndef NS_OPTIONS
39 | #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
40 | #endif
41 |
42 | #if OS_OBJECT_USE_OBJC
43 | #undef SDDispatchQueueRelease
44 | #undef SDDispatchQueueSetterSementics
45 | #define SDDispatchQueueRelease(q)
46 | #define SDDispatchQueueSetterSementics strong
47 | #else
48 | #undef SDDispatchQueueRelease
49 | #undef SDDispatchQueueSetterSementics
50 | #define SDDispatchQueueRelease(q) (dispatch_release(q))
51 | #define SDDispatchQueueSetterSementics assign
52 | #endif
53 |
54 | extern UIImage *SDScaledImageForKey(NSString *key, UIImage *image);
55 |
56 | typedef void(^SDWebImageNoParamsBlock)();
57 |
58 | extern NSString *const SDWebImageErrorDomain;
59 |
60 | #define dispatch_main_sync_safe(block)\
61 | if ([NSThread isMainThread]) {\
62 | block();\
63 | } else {\
64 | dispatch_sync(dispatch_get_main_queue(), block);\
65 | }
66 |
67 | #define dispatch_main_async_safe(block)\
68 | if ([NSThread isMainThread]) {\
69 | block();\
70 | } else {\
71 | dispatch_async(dispatch_get_main_queue(), block);\
72 | }
73 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIView+WebCacheOperation.m:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import "UIView+WebCacheOperation.h"
10 | #import "objc/runtime.h"
11 |
12 | static char loadOperationKey;
13 |
14 | @implementation UIView (WebCacheOperation)
15 |
16 | - (NSMutableDictionary *)operationDictionary {
17 | NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey);
18 | if (operations) {
19 | return operations;
20 | }
21 | operations = [NSMutableDictionary dictionary];
22 | objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
23 | return operations;
24 | }
25 |
26 | - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key {
27 | [self sd_cancelImageLoadOperationWithKey:key];
28 | NSMutableDictionary *operationDictionary = [self operationDictionary];
29 | [operationDictionary setObject:operation forKey:key];
30 | }
31 |
32 | - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key {
33 | // Cancel in progress downloader from queue
34 | NSMutableDictionary *operationDictionary = [self operationDictionary];
35 | id operations = [operationDictionary objectForKey:key];
36 | if (operations) {
37 | if ([operations isKindOfClass:[NSArray class]]) {
38 | for (id operation in operations) {
39 | if (operation) {
40 | [operation cancel];
41 | }
42 | }
43 | } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){
44 | [(id) operations cancel];
45 | }
46 | [operationDictionary removeObjectForKey:key];
47 | }
48 | }
49 |
50 | - (void)sd_removeImageLoadOperationWithKey:(NSString *)key {
51 | NSMutableDictionary *operationDictionary = [self operationDictionary];
52 | [operationDictionary removeObjectForKey:key];
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshLegendFooter.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshLegendFooter.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/5.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshLegendFooter.h"
11 | #import "MJRefreshConst.h"
12 | #import "UIView+MJExtension.h"
13 | #import "UIScrollView+MJExtension.h"
14 |
15 | @interface MJRefreshLegendFooter()
16 | @property (nonatomic, weak) UIActivityIndicatorView *activityView;
17 | @end
18 |
19 | @implementation MJRefreshLegendFooter
20 | #pragma mark - 懒加载
21 | - (UIActivityIndicatorView *)activityView
22 | {
23 | if (!_activityView) {
24 | UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
25 | [self addSubview:_activityView = activityView];
26 | }
27 | return _activityView;
28 | }
29 |
30 | #pragma mark - 初始化方法
31 | - (void)layoutSubviews
32 | {
33 | [super layoutSubviews];
34 |
35 | // 指示器
36 | if (self.stateHidden) {
37 | self.activityView.center = CGPointMake(self.mj_w * 0.5, self.mj_h * 0.5);
38 | } else {
39 | self.activityView.center = CGPointMake(self.mj_w * 0.5 - 100, self.mj_h * 0.5);
40 | }
41 | }
42 |
43 | #pragma mark - 公共方法
44 | - (void)setState:(MJRefreshFooterState)state
45 | {
46 | if (self.state == state) return;
47 |
48 | switch (state) {
49 | case MJRefreshFooterStateIdle:
50 | [self.activityView stopAnimating];
51 | break;
52 |
53 | case MJRefreshFooterStateRefreshing:
54 | [self.activityView startAnimating];
55 | break;
56 |
57 | case MJRefreshFooterStateNoMoreData:
58 | [self.activityView stopAnimating];
59 | break;
60 |
61 | default:
62 | break;
63 | }
64 |
65 | // super里面有回调,应该在最后面调用
66 | [super setState:state];
67 | }
68 | @end
69 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshComponent.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshComponent.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshComponent.h"
11 | #import "MJRefreshConst.h"
12 | #import "UIView+MJExtension.h"
13 |
14 | @interface MJRefreshComponent()
15 | /** 记录scrollView刚开始的inset */
16 | @property (assign, nonatomic) UIEdgeInsets scrollViewOriginalInset;
17 | /** 父控件 */
18 | @property (weak, nonatomic) UIScrollView *scrollView;
19 | @end
20 |
21 | @implementation MJRefreshComponent
22 | #pragma mark - 初始化
23 | - (instancetype)initWithFrame:(CGRect)frame
24 | {
25 | if (self = [super initWithFrame:frame]) {
26 | // 基本属性
27 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
28 | self.backgroundColor = [UIColor clearColor];
29 |
30 | // 默认文字颜色和字体大小
31 | self.textColor = MJRefreshLabelTextColor;
32 | self.font = MJRefreshLabelFont;
33 | }
34 | return self;
35 | }
36 |
37 | - (void)willMoveToSuperview:(UIView *)newSuperview
38 | {
39 | [super willMoveToSuperview:newSuperview];
40 |
41 | // 旧的父控件
42 | [self.superview removeObserver:self forKeyPath:MJRefreshContentOffset context:nil];
43 |
44 | if (newSuperview) { // 新的父控件
45 | [newSuperview addObserver:self forKeyPath:MJRefreshContentOffset options:NSKeyValueObservingOptionNew context:nil];
46 |
47 | // 设置宽度
48 | self.mj_w = newSuperview.mj_w;
49 | // 设置位置
50 | self.mj_x = 0;
51 |
52 | // 记录UIScrollView
53 | self.scrollView = (UIScrollView *)newSuperview;
54 | // 设置永远支持垂直弹簧效果
55 | self.scrollView.alwaysBounceVertical = YES;
56 | // 记录UIScrollView最开始的contentInset
57 | self.scrollViewOriginalInset = self.scrollView.contentInset;
58 | }
59 | }
60 |
61 | #pragma mark - 公共方法
62 | - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action
63 | {
64 | self.refreshingTarget = target;
65 | self.refreshingAction = action;
66 | }
67 |
68 | - (void)beginRefreshing
69 | {
70 |
71 | }
72 |
73 | - (void)endRefreshing
74 | {
75 |
76 | }
77 |
78 | - (BOOL)isRefreshing {
79 | return NO;
80 | }
81 | @end
82 |
--------------------------------------------------------------------------------
/Demo2/ProgressHUD/ProgressHUD.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2014 Related Code - http://relatedcode.com
3 | //
4 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10 | // THE SOFTWARE.
11 |
12 | #import
13 |
14 | //-------------------------------------------------------------------------------------------------------------------------------------------------
15 | #define HUD_STATUS_FONT [UIFont boldSystemFontOfSize:16]
16 | #define HUD_STATUS_COLOR [UIColor blackColor]
17 |
18 | #define HUD_SPINNER_COLOR [UIColor colorWithRed:185.0/255.0 green:220.0/255.0 blue:47.0/255.0 alpha:1.0]
19 | #define HUD_BACKGROUND_COLOR [UIColor colorWithWhite:0.0 alpha:0.1]
20 | #define HUD_WINDOW_COLOR [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.2]
21 |
22 | #define HUD_IMAGE_SUCCESS [UIImage imageNamed:@"ProgressHUD.bundle/progresshud-success.png"]
23 | #define HUD_IMAGE_ERROR [UIImage imageNamed:@"ProgressHUD.bundle/progresshud-error.png"]
24 |
25 | //-------------------------------------------------------------------------------------------------------------------------------------------------
26 | @interface ProgressHUD : UIView
27 | //-------------------------------------------------------------------------------------------------------------------------------------------------
28 |
29 | + (ProgressHUD *)shared;
30 |
31 | + (void)dismiss;
32 |
33 | + (void)show:(NSString *)status;
34 | + (void)show:(NSString *)status Interaction:(BOOL)Interaction;
35 |
36 | + (void)showSuccess:(NSString *)status;
37 | + (void)showSuccess:(NSString *)status Interaction:(BOOL)Interaction;
38 |
39 | + (void)showError:(NSString *)status;
40 | + (void)showError:(NSString *)status Interaction:(BOOL)Interaction;
41 |
42 | @property (nonatomic, assign) BOOL interaction;
43 |
44 | @property (nonatomic, retain) UIWindow *window;
45 | @property (nonatomic, retain) UIView *background;
46 | @property (nonatomic, retain) UIToolbar *hud;
47 | @property (nonatomic, retain) UIActivityIndicatorView *spinner;
48 | @property (nonatomic, retain) UIImageView *image;
49 | @property (nonatomic, retain) UILabel *label;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImage+WebP.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+WebP.m
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 07/06/13.
6 | // Copyright (c) 2013 Dailymotion. All rights reserved.
7 | //
8 |
9 | #ifdef SD_WEBP
10 | #import "UIImage+WebP.h"
11 | #import "webp/decode.h"
12 |
13 | // Callback for CGDataProviderRelease
14 | static void FreeImageData(void *info, const void *data, size_t size)
15 | {
16 | free((void *)data);
17 | }
18 |
19 | @implementation UIImage (WebP)
20 |
21 | + (UIImage *)sd_imageWithWebPData:(NSData *)data {
22 | WebPDecoderConfig config;
23 | if (!WebPInitDecoderConfig(&config)) {
24 | return nil;
25 | }
26 |
27 | if (WebPGetFeatures(data.bytes, data.length, &config.input) != VP8_STATUS_OK) {
28 | return nil;
29 | }
30 |
31 | config.output.colorspace = config.input.has_alpha ? MODE_rgbA : MODE_RGB;
32 | config.options.use_threads = 1;
33 |
34 | // Decode the WebP image data into a RGBA value array.
35 | if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK) {
36 | return nil;
37 | }
38 |
39 | int width = config.input.width;
40 | int height = config.input.height;
41 | if (config.options.use_scaling) {
42 | width = config.options.scaled_width;
43 | height = config.options.scaled_height;
44 | }
45 |
46 | // Construct a UIImage from the decoded RGBA value array.
47 | CGDataProviderRef provider =
48 | CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData);
49 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
50 | CGBitmapInfo bitmapInfo = config.input.has_alpha ? kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast : 0;
51 | size_t components = config.input.has_alpha ? 4 : 3;
52 | CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
53 | CGImageRef imageRef = CGImageCreate(width, height, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
54 |
55 | CGColorSpaceRelease(colorSpaceRef);
56 | CGDataProviderRelease(provider);
57 |
58 | UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
59 | CGImageRelease(imageRef);
60 |
61 | return image;
62 | }
63 |
64 | @end
65 |
66 | #if !COCOAPODS
67 | // Functions to resolve some undefined symbols when using WebP and force_load flag
68 | void WebPInitPremultiplyNEON(void) {}
69 | void WebPInitUpsamplersNEON(void) {}
70 | void VP8DspInitNEON(void) {}
71 | #endif
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/Demo2/PathCover/XHPathCover.h:
--------------------------------------------------------------------------------
1 | //
2 | // XHPathConver.h
3 | // XHPathCover
4 | //
5 | // Created by 曾 宪华 on 14-2-7.
6 | // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | // user info key for Dictionary
12 | extern NSString *const XHUserNameKey;
13 | extern NSString *const XHBirthdayKey;
14 |
15 | @interface XHPathCover : UIView
16 |
17 | // parallax background
18 | @property (nonatomic, strong) UIImageView *bannerImageView;
19 | @property (nonatomic, strong) UIImageView *bannerImageViewWithImageEffects;
20 |
21 | // user info
22 | @property (nonatomic, strong) UIButton *avatarButton;
23 | @property (nonatomic, strong) UILabel *userNameLabel;
24 | @property (nonatomic, strong) UILabel *birthdayLabel;
25 |
26 |
27 | //scrollView call back
28 | @property (nonatomic) BOOL touching;
29 | @property (nonatomic) CGFloat offsetY;
30 |
31 | // parallax background origin Y for parallaxHeight
32 | @property (nonatomic, assign) CGFloat parallaxHeight; // default is 170, this height was not self heigth.
33 |
34 | @property (nonatomic, assign) BOOL isZoomingEffect; // default is NO, if isZoomingEffect is YES, will be dissmiss parallax effect
35 | @property (nonatomic, assign) BOOL isLightEffect; // default is YES
36 | @property (nonatomic, assign) CGFloat lightEffectPadding; // default is 80
37 | @property (nonatomic, assign) CGFloat lightEffectAlpha; // default is 1.12 (between 1 - 2)
38 |
39 | @property (nonatomic, copy) void(^handleRefreshEvent)(void);
40 |
41 | @property (nonatomic, copy) void(^handleTapBackgroundImageEvent)(void);
42 |
43 | // stop Refresh
44 | - (void)stopRefresh;
45 |
46 | // background image
47 | - (void)setBackgroundImage:(UIImage *)backgroundImage;
48 | // custom set url for subClass, There is not work
49 | - (void)setBackgroundImageUrlString:(NSString *)backgroundImageUrlString;
50 |
51 | // avatar image
52 | - (void)setAvatarImage:(UIImage *)avatarImage;
53 | // custom set url for subClass, There is not work
54 | - (void)setAvatarUrlString:(NSString *)avatarUrlString;
55 |
56 | // set info, Example : NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"Jack", @"userName", @"1990-10-19", @"birthday", nil];
57 | - (void)setInfo:(NSDictionary *)info;
58 |
59 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
60 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView;
61 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
62 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
63 | @end
64 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshGifFooter.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshGifFooter.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/5.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshGifFooter.h"
11 | #import "MJRefreshConst.h"
12 | #import "UIView+MJExtension.h"
13 | #import "UIScrollView+MJExtension.h"
14 |
15 | @interface MJRefreshGifFooter()
16 | /** 播放动画图片的控件 */
17 | @property (weak, nonatomic) UIImageView *gifView;
18 | @end
19 |
20 | @implementation MJRefreshGifFooter
21 | #pragma mark - 懒加载
22 | - (UIImageView *)gifView
23 | {
24 | if (!_gifView) {
25 | UIImageView *gifView = [[UIImageView alloc] init];
26 | [self addSubview:_gifView = gifView];
27 | }
28 | return _gifView;
29 | }
30 |
31 | #pragma mark - 初始化方法
32 | - (void)layoutSubviews
33 | {
34 | [super layoutSubviews];
35 |
36 | // 指示器
37 | self.gifView.frame = self.bounds;
38 | if (self.stateHidden) {
39 | self.gifView.contentMode = UIViewContentModeCenter;
40 | } else {
41 | self.gifView.contentMode = UIViewContentModeRight;
42 | self.gifView.mj_w = self.mj_w * 0.5 - 90;
43 | }
44 | }
45 |
46 | #pragma mark - 公共方法
47 | - (void)setState:(MJRefreshFooterState)state
48 | {
49 | if (self.state == state) return;
50 |
51 | switch (state) {
52 | case MJRefreshFooterStateIdle:
53 | self.gifView.hidden = YES;
54 | [self.gifView stopAnimating];
55 | break;
56 |
57 | case MJRefreshFooterStateRefreshing:
58 | self.gifView.hidden = NO;
59 | [self.gifView startAnimating];
60 | break;
61 |
62 | case MJRefreshFooterStateNoMoreData:
63 | self.gifView.hidden = YES;
64 | [self.gifView stopAnimating];
65 | break;
66 |
67 | default:
68 | break;
69 | }
70 |
71 | // super里面有回调,应该在最后面调用
72 | [super setState:state];
73 | }
74 |
75 | - (void)setRefreshingImages:(NSArray *)refreshingImages
76 | {
77 | _refreshingImages = refreshingImages;
78 |
79 | self.gifView.animationImages = refreshingImages;
80 | self.gifView.animationDuration = refreshingImages.count * 0.1;
81 |
82 | // 根据图片设置控件的高度
83 | UIImage *image = [refreshingImages firstObject];
84 | if (image.size.height > self.mj_h) {
85 | _scrollView.mj_insetB -= self.mj_h;
86 | self.mj_h = image.size.height;
87 | _scrollView.mj_insetB += self.mj_h;
88 | }
89 | }
90 | @end
91 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/UIScrollView+MJExtension.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // UIScrollView+Extension.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 14-5-28.
7 | // Copyright (c) 2014年 itcast. All rights reserved.
8 | //
9 |
10 | #import "UIScrollView+MJExtension.h"
11 |
12 | @implementation UIScrollView (MJExtension)
13 | - (void)setMj_insetT:(CGFloat)mj_insetT
14 | {
15 | UIEdgeInsets inset = self.contentInset;
16 | inset.top = mj_insetT;
17 | self.contentInset = inset;
18 | }
19 |
20 | - (CGFloat)mj_insetT
21 | {
22 | return self.contentInset.top;
23 | }
24 |
25 | - (void)setMj_insetB:(CGFloat)mj_insetB
26 | {
27 | UIEdgeInsets inset = self.contentInset;
28 | inset.bottom = mj_insetB;
29 | self.contentInset = inset;
30 | }
31 |
32 | - (CGFloat)mj_insetB
33 | {
34 | return self.contentInset.bottom;
35 | }
36 |
37 | - (void)setMj_insetL:(CGFloat)mj_insetL
38 | {
39 | UIEdgeInsets inset = self.contentInset;
40 | inset.left = mj_insetL;
41 | self.contentInset = inset;
42 | }
43 |
44 | - (CGFloat)mj_insetL
45 | {
46 | return self.contentInset.left;
47 | }
48 |
49 | - (void)setMj_insetR:(CGFloat)mj_insetR
50 | {
51 | UIEdgeInsets inset = self.contentInset;
52 | inset.right = mj_insetR;
53 | self.contentInset = inset;
54 | }
55 |
56 | - (CGFloat)mj_insetR
57 | {
58 | return self.contentInset.right;
59 | }
60 |
61 | - (void)setMj_offsetX:(CGFloat)mj_offsetX
62 | {
63 | CGPoint offset = self.contentOffset;
64 | offset.x = mj_offsetX;
65 | self.contentOffset = offset;
66 | }
67 |
68 | - (CGFloat)mj_offsetX
69 | {
70 | return self.contentOffset.x;
71 | }
72 |
73 | - (void)setMj_offsetY:(CGFloat)mj_offsetY
74 | {
75 | CGPoint offset = self.contentOffset;
76 | offset.y = mj_offsetY;
77 | self.contentOffset = offset;
78 | }
79 |
80 | - (CGFloat)mj_offsetY
81 | {
82 | return self.contentOffset.y;
83 | }
84 |
85 | - (void)setMj_contentSizeW:(CGFloat)mj_contentSizeW
86 | {
87 | CGSize size = self.contentSize;
88 | size.width = mj_contentSizeW;
89 | self.contentSize = size;
90 | }
91 |
92 | - (CGFloat)mj_contentSizeW
93 | {
94 | return self.contentSize.width;
95 | }
96 |
97 | - (void)setMj_contentSizeH:(CGFloat)mj_contentSizeH
98 | {
99 | CGSize size = self.contentSize;
100 | size.height = mj_contentSizeH;
101 | self.contentSize = size;
102 | }
103 |
104 | - (CGFloat)mj_contentSizeH
105 | {
106 | return self.contentSize.height;
107 | }
108 | @end
109 |
--------------------------------------------------------------------------------
/Demo2/HZIndicatorView.m:
--------------------------------------------------------------------------------
1 | //
2 | // HZIndicatorView.m
3 | // photoBrowser
4 | //
5 | // Created by huangzhenyu on 15/6/23.
6 | // Copyright (c) 2015年 eamon. All rights reserved.
7 | //
8 |
9 | #import "HZIndicatorView.h"
10 | #import "HZPhotoBrowserConfig.h"
11 |
12 | @implementation HZIndicatorView
13 |
14 | - (instancetype)initWithFrame:(CGRect)frame
15 | {
16 | if (self = [super initWithFrame:frame]) {
17 | self.backgroundColor = kIndicatorViewBackgroundColor;
18 | self.clipsToBounds = YES;
19 | self.viewMode = HZIndicatorViewModeLoopDiagram;//圆
20 | }
21 | return self;
22 | }
23 |
24 | - (void)setProgress:(CGFloat)progress
25 | {
26 | _progress = progress;
27 | [self setNeedsDisplay];
28 | if (progress >= 1) {
29 | [self removeFromSuperview];
30 | }
31 | }
32 |
33 | - (void)setFrame:(CGRect)frame
34 | {
35 | frame.size.width = 42;
36 | frame.size.height = 42;
37 | self.layer.cornerRadius = 21;
38 | [super setFrame:frame];
39 | }
40 |
41 | - (void)drawRect:(CGRect)rect
42 | {
43 | CGContextRef ctx = UIGraphicsGetCurrentContext();
44 |
45 | CGFloat xCenter = rect.size.width * 0.5;
46 | CGFloat yCenter = rect.size.height * 0.5;
47 | [[UIColor whiteColor] set];
48 |
49 | switch (self.viewMode) {
50 | case HZIndicatorViewModePieDiagram:
51 | {
52 | CGFloat radius = MIN(rect.size.width * 0.5, rect.size.height * 0.5) - kIndicatorViewItemMargin;
53 |
54 |
55 | CGFloat w = radius * 2 + kIndicatorViewItemMargin;
56 | CGFloat h = w;
57 | CGFloat x = (rect.size.width - w) * 0.5;
58 | CGFloat y = (rect.size.height - h) * 0.5;
59 | CGContextAddEllipseInRect(ctx, CGRectMake(x, y, w, h));
60 | CGContextFillPath(ctx);
61 |
62 | [kIndicatorViewBackgroundColor set];
63 | CGContextMoveToPoint(ctx, xCenter, yCenter);
64 | CGContextAddLineToPoint(ctx, xCenter, 0);
65 | CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.001; // 初始值
66 | CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 1);
67 | CGContextClosePath(ctx);
68 |
69 | CGContextFillPath(ctx);
70 | }
71 | break;
72 |
73 | default:
74 | {
75 | CGContextSetLineWidth(ctx, 4);
76 | CGContextSetLineCap(ctx, kCGLineCapRound);
77 | CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2 + 0.05; // 初始值0.05
78 | CGFloat radius = MIN(rect.size.width, rect.size.height) * 0.5 - kIndicatorViewItemMargin;
79 | CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 0);
80 | CGContextStrokePath(ctx);
81 | }
82 | break;
83 | }
84 | }
85 | @end
86 |
--------------------------------------------------------------------------------
/Demo2/Base.lproj/Main.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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageDownloaderOperation.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 | #import "SDWebImageDownloader.h"
11 | #import "SDWebImageOperation.h"
12 |
13 | extern NSString *const SDWebImageDownloadStartNotification;
14 | extern NSString *const SDWebImageDownloadReceiveResponseNotification;
15 | extern NSString *const SDWebImageDownloadStopNotification;
16 | extern NSString *const SDWebImageDownloadFinishNotification;
17 |
18 | @interface SDWebImageDownloaderOperation : NSOperation
19 |
20 | /**
21 | * The request used by the operation's connection.
22 | */
23 | @property (strong, nonatomic, readonly) NSURLRequest *request;
24 |
25 |
26 | @property (assign, nonatomic) BOOL shouldDecompressImages;
27 |
28 | /**
29 | * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default.
30 | *
31 | * This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`.
32 | */
33 | @property (nonatomic, assign) BOOL shouldUseCredentialStorage;
34 |
35 | /**
36 | * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`.
37 | *
38 | * This will be overridden by any shared credentials that exist for the username or password of the request URL, if present.
39 | */
40 | @property (nonatomic, strong) NSURLCredential *credential;
41 |
42 | /**
43 | * The SDWebImageDownloaderOptions for the receiver.
44 | */
45 | @property (assign, nonatomic, readonly) SDWebImageDownloaderOptions options;
46 |
47 | /**
48 | * The expected size of data.
49 | */
50 | @property (assign, nonatomic) NSInteger expectedSize;
51 |
52 | /**
53 | * The response returned by the operation's connection.
54 | */
55 | @property (strong, nonatomic) NSURLResponse *response;
56 |
57 | /**
58 | * Initializes a `SDWebImageDownloaderOperation` object
59 | *
60 | * @see SDWebImageDownloaderOperation
61 | *
62 | * @param request the URL request
63 | * @param options downloader options
64 | * @param progressBlock the block executed when a new chunk of data arrives.
65 | * @note the progress block is executed on a background queue
66 | * @param completedBlock the block executed when the download is done.
67 | * @note the completed block is executed on the main queue for success. If errors are found, there is a chance the block will be executed on a background queue
68 | * @param cancelBlock the block executed if the download (operation) is cancelled
69 | *
70 | * @return the initialized instance
71 | */
72 | - (id)initWithRequest:(NSURLRequest *)request
73 | options:(SDWebImageDownloaderOptions)options
74 | progress:(SDWebImageDownloaderProgressBlock)progressBlock
75 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock
76 | cancelled:(SDWebImageNoParamsBlock)cancelBlock;
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshLegendHeader.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshLegendHeader.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshLegendHeader.h"
11 | #import "MJRefreshConst.h"
12 | #import "UIView+MJExtension.h"
13 |
14 | @interface MJRefreshLegendHeader()
15 | @property (nonatomic, weak) UIImageView *arrowImage;
16 | @property (nonatomic, weak) UIActivityIndicatorView *activityView;
17 | @end
18 |
19 | @implementation MJRefreshLegendHeader
20 | #pragma mark - 懒加载
21 | - (UIImageView *)arrowImage
22 | {
23 | if (!_arrowImage) {
24 | UIImageView *arrowImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:MJRefreshSrcName(@"arrow.png")]];
25 | [self addSubview:_arrowImage = arrowImage];
26 | }
27 | return _arrowImage;
28 | }
29 |
30 | - (UIActivityIndicatorView *)activityView
31 | {
32 | if (!_activityView) {
33 | UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
34 | activityView.bounds = self.arrowImage.bounds;
35 | [self addSubview:_activityView = activityView];
36 | }
37 | return _activityView;
38 | }
39 |
40 | #pragma mark - 初始化
41 | - (void)layoutSubviews
42 | {
43 | [super layoutSubviews];
44 |
45 | // 箭头
46 | CGFloat arrowX = (self.stateHidden && self.updatedTimeHidden) ? self.mj_w * 0.5 : (self.mj_w * 0.5 - 100);
47 | self.arrowImage.center = CGPointMake(arrowX, self.mj_h * 0.5);
48 |
49 | // 指示器
50 | self.activityView.center = self.arrowImage.center;
51 | }
52 |
53 | #pragma mark - 公共方法
54 | #pragma mark 设置状态
55 | - (void)setState:(MJRefreshHeaderState)state
56 | {
57 | if (self.state == state) return;
58 |
59 | // 旧状态
60 | MJRefreshHeaderState oldState = self.state;
61 |
62 | switch (state) {
63 | case MJRefreshHeaderStateIdle: {
64 | if (oldState == MJRefreshHeaderStateRefreshing) {
65 | self.arrowImage.transform = CGAffineTransformIdentity;
66 |
67 | [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
68 | self.activityView.alpha = 0.0;
69 | } completion:^(BOOL finished) {
70 | self.arrowImage.alpha = 1.0;
71 | self.activityView.alpha = 1.0;
72 | [self.activityView stopAnimating];
73 | }];
74 | } else {
75 | [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
76 | self.arrowImage.transform = CGAffineTransformIdentity;
77 | }];
78 | }
79 | break;
80 | }
81 |
82 | case MJRefreshHeaderStatePulling: {
83 | [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
84 | self.arrowImage.transform = CGAffineTransformMakeRotation(0.000001 - M_PI);
85 | }];
86 | break;
87 | }
88 |
89 | case MJRefreshHeaderStateRefreshing: {
90 | [self.activityView startAnimating];
91 | self.arrowImage.alpha = 0.0;
92 | break;
93 | }
94 |
95 | default:
96 | break;
97 | }
98 |
99 | // super里面有回调,应该在最后面调用
100 | [super setState:state];
101 | }
102 |
103 | @end
104 |
--------------------------------------------------------------------------------
/Demo2/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImage+MultiFormat.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+MultiFormat.m
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 07/06/13.
6 | // Copyright (c) 2013 Dailymotion. All rights reserved.
7 | //
8 |
9 | #import "UIImage+MultiFormat.h"
10 | #import "UIImage+GIF.h"
11 | #import "NSData+ImageContentType.h"
12 | #import
13 |
14 | #ifdef SD_WEBP
15 | #import "UIImage+WebP.h"
16 | #endif
17 |
18 | @implementation UIImage (MultiFormat)
19 |
20 | + (UIImage *)sd_imageWithData:(NSData *)data {
21 | if (!data) {
22 | return nil;
23 | }
24 |
25 | UIImage *image;
26 | NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
27 | if ([imageContentType isEqualToString:@"image/gif"]) {
28 | image = [UIImage sd_animatedGIFWithData:data];
29 | }
30 | #ifdef SD_WEBP
31 | else if ([imageContentType isEqualToString:@"image/webp"])
32 | {
33 | image = [UIImage sd_imageWithWebPData:data];
34 | }
35 | #endif
36 | else {
37 | image = [[UIImage alloc] initWithData:data];
38 | UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
39 | if (orientation != UIImageOrientationUp) {
40 | image = [UIImage imageWithCGImage:image.CGImage
41 | scale:image.scale
42 | orientation:orientation];
43 | }
44 | }
45 |
46 |
47 | return image;
48 | }
49 |
50 |
51 | +(UIImageOrientation)sd_imageOrientationFromImageData:(NSData *)imageData {
52 | UIImageOrientation result = UIImageOrientationUp;
53 | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
54 | if (imageSource) {
55 | CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
56 | if (properties) {
57 | CFTypeRef val;
58 | int exifOrientation;
59 | val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
60 | if (val) {
61 | CFNumberGetValue(val, kCFNumberIntType, &exifOrientation);
62 | result = [self sd_exifOrientationToiOSOrientation:exifOrientation];
63 | } // else - if it's not set it remains at up
64 | CFRelease((CFTypeRef) properties);
65 | } else {
66 | //NSLog(@"NO PROPERTIES, FAIL");
67 | }
68 | CFRelease(imageSource);
69 | }
70 | return result;
71 | }
72 |
73 | #pragma mark EXIF orientation tag converter
74 | // Convert an EXIF image orientation to an iOS one.
75 | // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html
76 | + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation {
77 | UIImageOrientation orientation = UIImageOrientationUp;
78 | switch (exifOrientation) {
79 | case 1:
80 | orientation = UIImageOrientationUp;
81 | break;
82 |
83 | case 3:
84 | orientation = UIImageOrientationDown;
85 | break;
86 |
87 | case 8:
88 | orientation = UIImageOrientationLeft;
89 | break;
90 |
91 | case 6:
92 | orientation = UIImageOrientationRight;
93 | break;
94 |
95 | case 2:
96 | orientation = UIImageOrientationUpMirrored;
97 | break;
98 |
99 | case 4:
100 | orientation = UIImageOrientationDownMirrored;
101 | break;
102 |
103 | case 5:
104 | orientation = UIImageOrientationLeftMirrored;
105 | break;
106 |
107 | case 7:
108 | orientation = UIImageOrientationRightMirrored;
109 | break;
110 | default:
111 | break;
112 | }
113 | return orientation;
114 | }
115 |
116 |
117 |
118 | @end
119 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImagePrefetcher.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 | #import "SDWebImageManager.h"
11 |
12 | @class SDWebImagePrefetcher;
13 |
14 | @protocol SDWebImagePrefetcherDelegate
15 |
16 | @optional
17 |
18 | /**
19 | * Called when an image was prefetched.
20 | *
21 | * @param imagePrefetcher The current image prefetcher
22 | * @param imageURL The image url that was prefetched
23 | * @param finishedCount The total number of images that were prefetched (successful or not)
24 | * @param totalCount The total number of images that were to be prefetched
25 | */
26 | - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount;
27 |
28 | /**
29 | * Called when all images are prefetched.
30 | * @param imagePrefetcher The current image prefetcher
31 | * @param totalCount The total number of images that were prefetched (whether successful or not)
32 | * @param skippedCount The total number of images that were skipped
33 | */
34 | - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount;
35 |
36 | @end
37 |
38 | typedef void(^SDWebImagePrefetcherProgressBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls);
39 | typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls);
40 |
41 | /**
42 | * Prefetch some URLs in the cache for future use. Images are downloaded in low priority.
43 | */
44 | @interface SDWebImagePrefetcher : NSObject
45 |
46 | /**
47 | * The web image manager
48 | */
49 | @property (strong, nonatomic, readonly) SDWebImageManager *manager;
50 |
51 | /**
52 | * Maximum number of URLs to prefetch at the same time. Defaults to 3.
53 | */
54 | @property (nonatomic, assign) NSUInteger maxConcurrentDownloads;
55 |
56 | /**
57 | * SDWebImageOptions for prefetcher. Defaults to SDWebImageLowPriority.
58 | */
59 | @property (nonatomic, assign) SDWebImageOptions options;
60 |
61 | /**
62 | * Queue options for Prefetcher. Defaults to Main Queue.
63 | */
64 | @property (nonatomic, assign) dispatch_queue_t prefetcherQueue;
65 |
66 | @property (weak, nonatomic) id delegate;
67 |
68 | /**
69 | * Return the global image prefetcher instance.
70 | */
71 | + (SDWebImagePrefetcher *)sharedImagePrefetcher;
72 |
73 | /**
74 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,
75 | * currently one image is downloaded at a time,
76 | * and skips images for failed downloads and proceed to the next image in the list
77 | *
78 | * @param urls list of URLs to prefetch
79 | */
80 | - (void)prefetchURLs:(NSArray *)urls;
81 |
82 | /**
83 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,
84 | * currently one image is downloaded at a time,
85 | * and skips images for failed downloads and proceed to the next image in the list
86 | *
87 | * @param urls list of URLs to prefetch
88 | * @param progressBlock block to be called when progress updates;
89 | * first parameter is the number of completed (successful or not) requests,
90 | * second parameter is the total number of images originally requested to be prefetched
91 | * @param completionBlock block to be called when prefetching is completed
92 | * first param is the number of completed (successful or not) requests,
93 | * second parameter is the number of skipped requests
94 | */
95 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock;
96 |
97 | /**
98 | * Remove and cancel queued list
99 | */
100 | - (void)cancelPrefetching;
101 |
102 |
103 | @end
104 |
--------------------------------------------------------------------------------
/Demo2/XActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // XActionSheet.m
3 | // Demo2
4 | //
5 | // Created by xlx on 15/7/29.
6 | // Copyright (c) 2015年 xlx. All rights reserved.
7 | //
8 |
9 | #import "XActionSheet.h"
10 |
11 | @interface XActionSheet ()
12 | {
13 | CGFloat width;
14 | CGFloat height;
15 | }
16 | @end
17 |
18 | @implementation XActionSheet
19 | - (id)init{
20 | self = [super init];
21 | self.modalPresentationStyle = UIModalPresentationOverFullScreen;
22 | self.view.backgroundColor = [UIColor clearColor];
23 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
24 | [self.view addGestureRecognizer:tap];
25 |
26 | _btnArray = [[NSMutableArray alloc]init];
27 | width = self.view.bounds.size.width;
28 | height = self.view.bounds.size.height;
29 | return self;
30 | }
31 | - (void)viewDidLoad {
32 | [super viewDidLoad];
33 | }
34 |
35 | - (void)didReceiveMemoryWarning {
36 | [super didReceiveMemoryWarning];
37 | // Dispose of any resources that can be recreated.
38 | }
39 |
40 | - (void)tap{
41 | [self dismissViewControllerAnimated:true completion:^{
42 |
43 | }];
44 | }
45 | /**
46 | * 添加取消按钮
47 | */
48 | -(void)addCancelButton:(NSString *)Title{
49 | if (!_layView) {
50 | _layView = [[UIView alloc]initWithFrame:CGRectMake(width * 0.1,height - ( _btnArray.count * 40 + 40 + 30), width * 0.8, _btnArray.count * 40 + 40 + 20)];
51 | _layView.layer.cornerRadius = 5;
52 | _layView.alpha = 0.8;
53 | _layView.layer.masksToBounds = true;
54 | [self.view addSubview:_layView];
55 | }else{
56 | CGFloat nowHeight = _layView.bounds.size.height;
57 | nowHeight += 50;
58 | _layView.frame = CGRectMake(width * 0.1, height - nowHeight, width * 0.8, nowHeight);
59 | }
60 | if (!_CancelButton) {
61 | _CancelButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 40 * _btnArray.count + 10, width * 0.8, 40)];
62 | [_CancelButton setTitle:Title forState:normal];
63 | _CancelButton.layer.cornerRadius = 5;
64 | _CancelButton.layer.masksToBounds = true;
65 | _CancelButton.backgroundColor = [UIColor brownColor];
66 | [_CancelButton addTarget:self action:@selector(tap) forControlEvents:UIControlEventTouchUpInside];
67 | [_layView addSubview:_CancelButton];
68 | }else{
69 | [_CancelButton setTitle:Title forState:normal];
70 | }
71 | }
72 | /**
73 | * 添加按钮
74 | */
75 | -(void)addButtonwithTitle:(NSString *)Title{
76 | if (!_layView) {
77 | _layView = [[UIView alloc]initWithFrame:CGRectMake(width * 0.1,height - ( 40 + 10), width * 0.8, _btnArray.count * 40 + 40 + 20)];
78 | _layView.layer.cornerRadius = 5;
79 | _layView.alpha = 0.8;
80 | _layView.layer.masksToBounds = true;
81 | [self.view addSubview:_layView];
82 | }else{
83 | CGFloat nowHeight = _layView.bounds.size.height;
84 | nowHeight += 40;
85 | _layView.frame = CGRectMake(width * 0.1, height - nowHeight, width * 0.8, nowHeight);
86 | }
87 |
88 | UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, _btnArray.count * 40, width * 0.8, 39)];
89 | btn.tag = _btnArray.count;
90 | [btn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
91 | btn.backgroundColor = [UIColor colorWithRed:(CGFloat)52/255 green:(CGFloat)170/255 blue:(CGFloat)135/255 alpha:1];
92 | [btn setTitle:Title forState:normal];
93 | [_btnArray addObject:btn];
94 | [_layView addSubview:btn];
95 |
96 | CGFloat cancelY = _CancelButton.frame.origin.y;
97 | _CancelButton.frame = CGRectMake(0, cancelY + 40, width * 0.8, 40);
98 | }
99 | - (void)addButtonWithTitleArray:(NSArray *)array{
100 | for (NSString *Title in array) {
101 | [self addButtonwithTitle:Title];
102 | }
103 | }
104 | /**
105 | * 按钮点击动作
106 | */
107 | - (void)buttonClick:(id)sender{
108 | [self dismissViewControllerAnimated:true completion:^{
109 |
110 | }];
111 | UIButton *btn = (UIButton *)sender;
112 | [_delegate buttonClick:btn.tag];
113 | }
114 |
115 |
116 | @end
117 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshGifHeader.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshGifHeader.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshGifHeader.h"
11 | #import "MJRefreshConst.h"
12 | #import "UIView+MJExtension.h"
13 |
14 | @interface MJRefreshGifHeader()
15 | /** 所有状态对应的动画图片 */
16 | @property (strong, nonatomic) NSMutableDictionary *stateImages;
17 |
18 | /** 播放动画图片的控件 */
19 | @property (weak, nonatomic) UIImageView *gifView;
20 | @end
21 |
22 | @implementation MJRefreshGifHeader
23 | #pragma mark - 懒加载
24 | - (NSMutableDictionary *)stateImages
25 | {
26 | if (!_stateImages) {
27 | self.stateImages = [NSMutableDictionary dictionary];
28 | }
29 | return _stateImages;
30 | }
31 |
32 | - (UIImageView *)gifView
33 | {
34 | if (!_gifView) {
35 | UIImageView *gifView = [[UIImageView alloc] init];
36 | [self addSubview:_gifView = gifView];
37 | }
38 | return _gifView;
39 | }
40 |
41 | #pragma mark - 初始化
42 | - (void)layoutSubviews
43 | {
44 | [super layoutSubviews];
45 |
46 | self.gifView.frame = self.bounds;
47 | if (self.stateHidden && self.updatedTimeHidden) {
48 | self.gifView.contentMode = UIViewContentModeCenter;
49 | } else {
50 | self.gifView.contentMode = UIViewContentModeRight;
51 | self.gifView.mj_w = self.mj_w * 0.5 - 90;
52 | }
53 | }
54 |
55 | #pragma mark - 公共方法
56 | #pragma mark 设置状态
57 | - (void)setState:(MJRefreshHeaderState)state
58 | {
59 | if (self.state == state) return;
60 |
61 | // 旧状态
62 | MJRefreshHeaderState oldState = self.state;
63 |
64 | NSArray *images = self.stateImages[@(state)];
65 | if (images.count != 0) {
66 | switch (state) {
67 | case MJRefreshHeaderStateIdle: {
68 | if (oldState == MJRefreshHeaderStateRefreshing) {
69 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJRefreshSlowAnimationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
70 | self.pullingPercent = 0.0;
71 | });
72 | } else {
73 | self.pullingPercent = self.pullingPercent;
74 | }
75 | break;
76 | }
77 |
78 | case MJRefreshHeaderStatePulling:
79 | case MJRefreshHeaderStateRefreshing: {
80 | [self.gifView stopAnimating];
81 | if (images.count == 1) { // 单张图片
82 | self.gifView.image = [images lastObject];
83 | } else { // 多张图片
84 | self.gifView.animationImages = images;
85 | self.gifView.animationDuration = images.count * 0.1;
86 | [self.gifView startAnimating];
87 | }
88 | break;
89 | }
90 |
91 | default:
92 | break;
93 | }
94 | }
95 |
96 | // super里面有回调,应该在最后面调用
97 | [super setState:state];
98 | }
99 |
100 | - (void)setPullingPercent:(CGFloat)pullingPercent
101 | {
102 | [super setPullingPercent:pullingPercent];
103 |
104 | NSArray *images = self.stateImages[@(self.state)];
105 | switch (self.state) {
106 | case MJRefreshHeaderStateIdle: {
107 | [self.gifView stopAnimating];
108 | NSUInteger index = images.count * self.pullingPercent;
109 | if (index >= images.count) index = images.count - 1;
110 | self.gifView.image = images[index];
111 | break;
112 | }
113 | default:
114 | break;
115 | }
116 | }
117 |
118 | - (void)setImages:(NSArray *)images forState:(MJRefreshHeaderState)state
119 | {
120 | if (images == nil) return;
121 |
122 | self.stateImages[@(state)] = images;
123 |
124 | // 根据图片设置控件的高度
125 | UIImage *image = [images firstObject];
126 | if (image.size.height > self.mj_h) {
127 | self.mj_h = image.size.height;
128 | }
129 | }
130 | @end
131 |
--------------------------------------------------------------------------------
/Demo2.xcodeproj/xcuserdata/xlx.xcuserdatad/xcschemes/Demo2.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImageView+HighlightedWebCache.m:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import "UIImageView+HighlightedWebCache.h"
10 | #import "UIView+WebCacheOperation.h"
11 |
12 | #define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage"
13 |
14 | @implementation UIImageView (HighlightedWebCache)
15 |
16 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url {
17 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil];
18 | }
19 |
20 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options {
21 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil];
22 | }
23 |
24 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock {
25 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock];
26 | }
27 |
28 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock {
29 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock];
30 | }
31 |
32 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
33 | [self sd_cancelCurrentHighlightedImageLoad];
34 |
35 | if (url) {
36 | __weak __typeof(self)wself = self;
37 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
38 | if (!wself) return;
39 | dispatch_main_sync_safe (^
40 | {
41 | if (!wself) return;
42 | if (image) {
43 | wself.highlightedImage = image;
44 | [wself setNeedsLayout];
45 | }
46 | if (completedBlock && finished) {
47 | completedBlock(image, error, cacheType, url);
48 | }
49 | });
50 | }];
51 | [self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey];
52 | } else {
53 | dispatch_main_async_safe(^{
54 | NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
55 | if (completedBlock) {
56 | completedBlock(nil, error, SDImageCacheTypeNone, url);
57 | }
58 | });
59 | }
60 | }
61 |
62 | - (void)sd_cancelCurrentHighlightedImageLoad {
63 | [self sd_cancelImageLoadOperationWithKey:UIImageViewHighlightedWebCacheOperationKey];
64 | }
65 |
66 | @end
67 |
68 |
69 | @implementation UIImageView (HighlightedWebCacheDeprecated)
70 |
71 | - (void)setHighlightedImageWithURL:(NSURL *)url {
72 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil];
73 | }
74 |
75 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options {
76 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil];
77 | }
78 |
79 | - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
80 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
81 | if (completedBlock) {
82 | completedBlock(image, error, cacheType);
83 | }
84 | }];
85 | }
86 |
87 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
88 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
89 | if (completedBlock) {
90 | completedBlock(image, error, cacheType);
91 | }
92 | }];
93 | }
94 |
95 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock {
96 | [self sd_setHighlightedImageWithURL:url options:0 progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
97 | if (completedBlock) {
98 | completedBlock(image, error, cacheType);
99 | }
100 | }];
101 | }
102 |
103 | - (void)cancelCurrentHighlightedImageLoad {
104 | [self sd_cancelCurrentHighlightedImageLoad];
105 | }
106 |
107 | @end
108 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/MKAnnotationView+WebCache.m:
--------------------------------------------------------------------------------
1 | //
2 | // MKAnnotationView+WebCache.m
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 14/03/12.
6 | // Copyright (c) 2012 Dailymotion. All rights reserved.
7 | //
8 |
9 | #import "MKAnnotationView+WebCache.h"
10 | #import "objc/runtime.h"
11 | #import "UIView+WebCacheOperation.h"
12 |
13 | static char imageURLKey;
14 |
15 | @implementation MKAnnotationView (WebCache)
16 |
17 | - (NSURL *)sd_imageURL {
18 | return objc_getAssociatedObject(self, &imageURLKey);
19 | }
20 |
21 | - (void)sd_setImageWithURL:(NSURL *)url {
22 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:nil];
23 | }
24 |
25 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder {
26 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:nil];
27 | }
28 |
29 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
30 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil];
31 | }
32 |
33 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock {
34 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:completedBlock];
35 | }
36 |
37 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock {
38 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:completedBlock];
39 | }
40 |
41 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock {
42 | [self sd_cancelCurrentImageLoad];
43 |
44 | objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
45 | self.image = placeholder;
46 |
47 | if (url) {
48 | __weak __typeof(self)wself = self;
49 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
50 | if (!wself) return;
51 | dispatch_main_sync_safe(^{
52 | __strong MKAnnotationView *sself = wself;
53 | if (!sself) return;
54 | if (image) {
55 | sself.image = image;
56 | }
57 | if (completedBlock && finished) {
58 | completedBlock(image, error, cacheType, url);
59 | }
60 | });
61 | }];
62 | [self sd_setImageLoadOperation:operation forKey:@"MKAnnotationViewImage"];
63 | } else {
64 | dispatch_main_async_safe(^{
65 | NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
66 | if (completedBlock) {
67 | completedBlock(nil, error, SDImageCacheTypeNone, url);
68 | }
69 | });
70 | }
71 | }
72 |
73 | - (void)sd_cancelCurrentImageLoad {
74 | [self sd_cancelImageLoadOperationWithKey:@"MKAnnotationViewImage"];
75 | }
76 |
77 | @end
78 |
79 |
80 | @implementation MKAnnotationView (WebCacheDeprecated)
81 |
82 | - (NSURL *)imageURL {
83 | return [self sd_imageURL];
84 | }
85 |
86 | - (void)setImageWithURL:(NSURL *)url {
87 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:nil];
88 | }
89 |
90 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder {
91 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:nil];
92 | }
93 |
94 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
95 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil];
96 | }
97 |
98 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
99 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
100 | if (completedBlock) {
101 | completedBlock(image, error, cacheType);
102 | }
103 | }];
104 | }
105 |
106 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock {
107 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
108 | if (completedBlock) {
109 | completedBlock(image, error, cacheType);
110 | }
111 | }];
112 | }
113 |
114 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
115 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
116 | if (completedBlock) {
117 | completedBlock(image, error, cacheType);
118 | }
119 | }];
120 | }
121 |
122 | - (void)cancelCurrentImageLoad {
123 | [self sd_cancelCurrentImageLoad];
124 | }
125 |
126 | @end
127 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImageView+HighlightedWebCache.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 | #import "SDWebImageCompat.h"
11 | #import "SDWebImageManager.h"
12 |
13 | /**
14 | * Integrates SDWebImage async downloading and caching of remote images with UIImageView for highlighted state.
15 | */
16 | @interface UIImageView (HighlightedWebCache)
17 |
18 | /**
19 | * Set the imageView `highlightedImage` with an `url`.
20 | *
21 | * The download is asynchronous and cached.
22 | *
23 | * @param url The url for the image.
24 | */
25 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url;
26 |
27 | /**
28 | * Set the imageView `highlightedImage` with an `url` and custom options.
29 | *
30 | * The download is asynchronous and cached.
31 | *
32 | * @param url The url for the image.
33 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
34 | */
35 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options;
36 |
37 | /**
38 | * Set the imageView `highlightedImage` with an `url`.
39 | *
40 | * The download is asynchronous and cached.
41 | *
42 | * @param url The url for the image.
43 | * @param completedBlock A block called when operation has been completed. This block has no return value
44 | * and takes the requested UIImage as first parameter. In case of error the image parameter
45 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
46 | * indicating if the image was retrived from the local cache or from the network.
47 | * The fourth parameter is the original image url.
48 | */
49 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
50 |
51 | /**
52 | * Set the imageView `highlightedImage` with an `url` and custom options.
53 | *
54 | * The download is asynchronous and cached.
55 | *
56 | * @param url The url for the image.
57 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
58 | * @param completedBlock A block called when operation has been completed. This block has no return value
59 | * and takes the requested UIImage as first parameter. In case of error the image parameter
60 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
61 | * indicating if the image was retrived from the local cache or from the network.
62 | * The fourth parameter is the original image url.
63 | */
64 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
65 |
66 | /**
67 | * Set the imageView `highlightedImage` with an `url` and custom options.
68 | *
69 | * The download is asynchronous and cached.
70 | *
71 | * @param url The url for the image.
72 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
73 | * @param progressBlock A block called while image is downloading
74 | * @param completedBlock A block called when operation has been completed. This block has no return value
75 | * and takes the requested UIImage as first parameter. In case of error the image parameter
76 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
77 | * indicating if the image was retrived from the local cache or from the network.
78 | * The fourth parameter is the original image url.
79 | */
80 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
81 |
82 | /**
83 | * Cancel the current download
84 | */
85 | - (void)sd_cancelCurrentHighlightedImageLoad;
86 |
87 | @end
88 |
89 |
90 | @interface UIImageView (HighlightedWebCacheDeprecated)
91 |
92 | - (void)setHighlightedImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:`");
93 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:`");
94 | - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:completed:`");
95 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:completed:`");
96 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:progress:completed:`");
97 |
98 | - (void)cancelCurrentHighlightedImageLoad __deprecated_msg("Use `sd_cancelCurrentHighlightedImageLoad`");
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImage+GIF.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+GIF.m
3 | // LBGIFImage
4 | //
5 | // Created by Laurin Brandner on 06.01.12.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "UIImage+GIF.h"
10 | #import
11 |
12 | @implementation UIImage (GIF)
13 |
14 | + (UIImage *)sd_animatedGIFWithData:(NSData *)data {
15 | if (!data) {
16 | return nil;
17 | }
18 |
19 | CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
20 |
21 | size_t count = CGImageSourceGetCount(source);
22 |
23 | UIImage *animatedImage;
24 |
25 | if (count <= 1) {
26 | animatedImage = [[UIImage alloc] initWithData:data];
27 | }
28 | else {
29 | NSMutableArray *images = [NSMutableArray array];
30 |
31 | NSTimeInterval duration = 0.0f;
32 |
33 | for (size_t i = 0; i < count; i++) {
34 | CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
35 |
36 | duration += [self sd_frameDurationAtIndex:i source:source];
37 |
38 | [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
39 |
40 | CGImageRelease(image);
41 | }
42 |
43 | if (!duration) {
44 | duration = (1.0f / 10.0f) * count;
45 | }
46 |
47 | animatedImage = [UIImage animatedImageWithImages:images duration:duration];
48 | }
49 |
50 | CFRelease(source);
51 |
52 | return animatedImage;
53 | }
54 |
55 | + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
56 | float frameDuration = 0.1f;
57 | CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
58 | NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
59 | NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
60 |
61 | NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
62 | if (delayTimeUnclampedProp) {
63 | frameDuration = [delayTimeUnclampedProp floatValue];
64 | }
65 | else {
66 |
67 | NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
68 | if (delayTimeProp) {
69 | frameDuration = [delayTimeProp floatValue];
70 | }
71 | }
72 |
73 | // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
74 | // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
75 | // a duration of <= 10 ms. See and
76 | // for more information.
77 |
78 | if (frameDuration < 0.011f) {
79 | frameDuration = 0.100f;
80 | }
81 |
82 | CFRelease(cfFrameProperties);
83 | return frameDuration;
84 | }
85 |
86 | + (UIImage *)sd_animatedGIFNamed:(NSString *)name {
87 | CGFloat scale = [UIScreen mainScreen].scale;
88 |
89 | if (scale > 1.0f) {
90 | NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"];
91 |
92 | NSData *data = [NSData dataWithContentsOfFile:retinaPath];
93 |
94 | if (data) {
95 | return [UIImage sd_animatedGIFWithData:data];
96 | }
97 |
98 | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
99 |
100 | data = [NSData dataWithContentsOfFile:path];
101 |
102 | if (data) {
103 | return [UIImage sd_animatedGIFWithData:data];
104 | }
105 |
106 | return [UIImage imageNamed:name];
107 | }
108 | else {
109 | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
110 |
111 | NSData *data = [NSData dataWithContentsOfFile:path];
112 |
113 | if (data) {
114 | return [UIImage sd_animatedGIFWithData:data];
115 | }
116 |
117 | return [UIImage imageNamed:name];
118 | }
119 | }
120 |
121 | - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size {
122 | if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) {
123 | return self;
124 | }
125 |
126 | CGSize scaledSize = size;
127 | CGPoint thumbnailPoint = CGPointZero;
128 |
129 | CGFloat widthFactor = size.width / self.size.width;
130 | CGFloat heightFactor = size.height / self.size.height;
131 | CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor;
132 | scaledSize.width = self.size.width * scaleFactor;
133 | scaledSize.height = self.size.height * scaleFactor;
134 |
135 | if (widthFactor > heightFactor) {
136 | thumbnailPoint.y = (size.height - scaledSize.height) * 0.5;
137 | }
138 | else if (widthFactor < heightFactor) {
139 | thumbnailPoint.x = (size.width - scaledSize.width) * 0.5;
140 | }
141 |
142 | NSMutableArray *scaledImages = [NSMutableArray array];
143 |
144 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
145 |
146 | for (UIImage *image in self.images) {
147 | [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)];
148 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
149 |
150 | [scaledImages addObject:newImage];
151 | }
152 |
153 | UIGraphicsEndImageContext();
154 |
155 | return [UIImage animatedImageWithImages:scaledImages duration:self.duration];
156 | }
157 |
158 | @end
159 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImagePrefetcher.m:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import "SDWebImagePrefetcher.h"
10 |
11 | #if (!defined(DEBUG) && !defined (SD_VERBOSE)) || defined(SD_LOG_NONE)
12 | #define NSLog(...)
13 | #endif
14 |
15 | @interface SDWebImagePrefetcher ()
16 |
17 | @property (strong, nonatomic) SDWebImageManager *manager;
18 | @property (strong, nonatomic) NSArray *prefetchURLs;
19 | @property (assign, nonatomic) NSUInteger requestedCount;
20 | @property (assign, nonatomic) NSUInteger skippedCount;
21 | @property (assign, nonatomic) NSUInteger finishedCount;
22 | @property (assign, nonatomic) NSTimeInterval startedTime;
23 | @property (copy, nonatomic) SDWebImagePrefetcherCompletionBlock completionBlock;
24 | @property (copy, nonatomic) SDWebImagePrefetcherProgressBlock progressBlock;
25 |
26 | @end
27 |
28 | @implementation SDWebImagePrefetcher
29 |
30 | + (SDWebImagePrefetcher *)sharedImagePrefetcher {
31 | static dispatch_once_t once;
32 | static id instance;
33 | dispatch_once(&once, ^{
34 | instance = [self new];
35 | });
36 | return instance;
37 | }
38 |
39 | - (id)init {
40 | if ((self = [super init])) {
41 | _manager = [SDWebImageManager new];
42 | _options = SDWebImageLowPriority;
43 | _prefetcherQueue = dispatch_get_main_queue();
44 | self.maxConcurrentDownloads = 3;
45 | }
46 | return self;
47 | }
48 |
49 | - (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads {
50 | self.manager.imageDownloader.maxConcurrentDownloads = maxConcurrentDownloads;
51 | }
52 |
53 | - (NSUInteger)maxConcurrentDownloads {
54 | return self.manager.imageDownloader.maxConcurrentDownloads;
55 | }
56 |
57 | - (void)startPrefetchingAtIndex:(NSUInteger)index {
58 | if (index >= self.prefetchURLs.count) return;
59 | self.requestedCount++;
60 | [self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
61 | if (!finished) return;
62 | self.finishedCount++;
63 |
64 | if (image) {
65 | if (self.progressBlock) {
66 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
67 | }
68 | NSLog(@"Prefetched %@ out of %@", @(self.finishedCount), @(self.prefetchURLs.count));
69 | }
70 | else {
71 | if (self.progressBlock) {
72 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
73 | }
74 | NSLog(@"Prefetched %@ out of %@ (Failed)", @(self.finishedCount), @(self.prefetchURLs.count));
75 |
76 | // Add last failed
77 | self.skippedCount++;
78 | }
79 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) {
80 | [self.delegate imagePrefetcher:self
81 | didPrefetchURL:self.prefetchURLs[index]
82 | finishedCount:self.finishedCount
83 | totalCount:self.prefetchURLs.count
84 | ];
85 | }
86 | if (self.prefetchURLs.count > self.requestedCount) {
87 | dispatch_async(self.prefetcherQueue, ^{
88 | [self startPrefetchingAtIndex:self.requestedCount];
89 | });
90 | }
91 | else if (self.finishedCount == self.requestedCount) {
92 | [self reportStatus];
93 | if (self.completionBlock) {
94 | self.completionBlock(self.finishedCount, self.skippedCount);
95 | self.completionBlock = nil;
96 | }
97 | self.progressBlock = nil;
98 | }
99 | }];
100 | }
101 |
102 | - (void)reportStatus {
103 | NSUInteger total = [self.prefetchURLs count];
104 | NSLog(@"Finished prefetching (%@ successful, %@ skipped, timeElasped %.2f)", @(total - self.skippedCount), @(self.skippedCount), CFAbsoluteTimeGetCurrent() - self.startedTime);
105 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) {
106 | [self.delegate imagePrefetcher:self
107 | didFinishWithTotalCount:(total - self.skippedCount)
108 | skippedCount:self.skippedCount
109 | ];
110 | }
111 | }
112 |
113 | - (void)prefetchURLs:(NSArray *)urls {
114 | [self prefetchURLs:urls progress:nil completed:nil];
115 | }
116 |
117 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock {
118 | [self cancelPrefetching]; // Prevent duplicate prefetch request
119 | self.startedTime = CFAbsoluteTimeGetCurrent();
120 | self.prefetchURLs = urls;
121 | self.completionBlock = completionBlock;
122 | self.progressBlock = progressBlock;
123 |
124 | if(urls.count == 0){
125 | if(completionBlock){
126 | completionBlock(0,0);
127 | }
128 | }else{
129 | // Starts prefetching from the very first image on the list with the max allowed concurrency
130 | NSUInteger listCount = self.prefetchURLs.count;
131 | for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) {
132 | [self startPrefetchingAtIndex:i];
133 | }
134 | }
135 | }
136 |
137 | - (void)cancelPrefetching {
138 | self.prefetchURLs = nil;
139 | self.skippedCount = 0;
140 | self.requestedCount = 0;
141 | self.finishedCount = 0;
142 | [self.manager cancelAll];
143 | }
144 |
145 | @end
146 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/MKAnnotationView+WebCache.h:
--------------------------------------------------------------------------------
1 | //
2 | // MKAnnotationView+WebCache.h
3 | // SDWebImage
4 | //
5 | // Created by Olivier Poitrey on 14/03/12.
6 | // Copyright (c) 2012 Dailymotion. All rights reserved.
7 | //
8 |
9 | #import "MapKit/MapKit.h"
10 | #import "SDWebImageManager.h"
11 |
12 | /**
13 | * Integrates SDWebImage async downloading and caching of remote images with MKAnnotationView.
14 | */
15 | @interface MKAnnotationView (WebCache)
16 |
17 | /**
18 | * Get the current image URL.
19 | *
20 | * Note that because of the limitations of categories this property can get out of sync
21 | * if you use sd_setImage: directly.
22 | */
23 | - (NSURL *)sd_imageURL;
24 |
25 | /**
26 | * Set the imageView `image` with an `url`.
27 | *
28 | * The download is asynchronous and cached.
29 | *
30 | * @param url The url for the image.
31 | */
32 | - (void)sd_setImageWithURL:(NSURL *)url;
33 |
34 | /**
35 | * Set the imageView `image` with an `url` and a placeholder.
36 | *
37 | * The download is asynchronous and cached.
38 | *
39 | * @param url The url for the image.
40 | * @param placeholder The image to be set initially, until the image request finishes.
41 | * @see sd_setImageWithURL:placeholderImage:options:
42 | */
43 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
44 |
45 | /**
46 | * Set the imageView `image` with an `url`, placeholder and custom options.
47 | *
48 | * The download is asynchronous and cached.
49 | *
50 | * @param url The url for the image.
51 | * @param placeholder The image to be set initially, until the image request finishes.
52 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
53 | */
54 |
55 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
56 |
57 | /**
58 | * Set the imageView `image` with an `url`.
59 | *
60 | * The download is asynchronous and cached.
61 | *
62 | * @param url The url for the image.
63 | * @param completedBlock A block called when operation has been completed. This block has no return value
64 | * and takes the requested UIImage as first parameter. In case of error the image parameter
65 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
66 | * indicating if the image was retrived from the local cache or from the network.
67 | * The fourth parameter is the original image url.
68 | */
69 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
70 |
71 | /**
72 | * Set the imageView `image` with an `url`, placeholder.
73 | *
74 | * The download is asynchronous and cached.
75 | *
76 | * @param url The url for the image.
77 | * @param placeholder The image to be set initially, until the image request finishes.
78 | * @param completedBlock A block called when operation has been completed. This block has no return value
79 | * and takes the requested UIImage as first parameter. In case of error the image parameter
80 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
81 | * indicating if the image was retrived from the local cache or from the network.
82 | * The fourth parameter is the original image url.
83 | */
84 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
85 |
86 | /**
87 | * Set the imageView `image` with an `url`, placeholder and custom options.
88 | *
89 | * The download is asynchronous and cached.
90 | *
91 | * @param url The url for the image.
92 | * @param placeholder The image to be set initially, until the image request finishes.
93 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
94 | * @param completedBlock A block called when operation has been completed. This block has no return value
95 | * and takes the requested UIImage as first parameter. In case of error the image parameter
96 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
97 | * indicating if the image was retrived from the local cache or from the network.
98 | * The fourth parameter is the original image url.
99 | */
100 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
101 |
102 | /**
103 | * Cancel the current download
104 | */
105 | - (void)sd_cancelCurrentImageLoad;
106 |
107 | @end
108 |
109 |
110 | @interface MKAnnotationView (WebCacheDeprecated)
111 |
112 | - (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`");
113 |
114 | - (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`");
115 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`");
116 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:`");
117 |
118 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`");
119 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`");
120 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`");
121 |
122 | - (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`");
123 |
124 | @end
125 |
--------------------------------------------------------------------------------
/Demo2/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Demo2
4 | //
5 | // Created by xlx on 15/7/20.
6 | // Copyright (c) 2015年 xlx. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import CoreData
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 |
18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
19 | // Override point for customization after application launch.
20 | return true
21 | }
22 |
23 | func applicationWillResignActive(application: UIApplication) {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | func applicationDidEnterBackground(application: UIApplication) {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | func applicationWillEnterForeground(application: UIApplication) {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | func applicationDidBecomeActive(application: UIApplication) {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | func applicationWillTerminate(application: UIApplication) {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | // Saves changes in the application's managed object context before the application terminates.
44 | self.saveContext()
45 | }
46 |
47 | // MARK: - Core Data stack
48 |
49 | lazy var applicationDocumentsDirectory: NSURL = {
50 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.xlx.Demo2" in the application's documents Application Support directory.
51 | let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
52 | return urls[urls.count-1] as! NSURL
53 | }()
54 |
55 | lazy var managedObjectModel: NSManagedObjectModel = {
56 | // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
57 | let modelURL = NSBundle.mainBundle().URLForResource("Demo2", withExtension: "momd")!
58 | return NSManagedObjectModel(contentsOfURL: modelURL)!
59 | }()
60 |
61 | lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
62 | // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
63 | // Create the coordinator and store
64 | var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
65 | let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("Demo2.sqlite")
66 | var error: NSError? = nil
67 | var failureReason = "There was an error creating or loading the application's saved data."
68 | if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
69 | coordinator = nil
70 | // Report any error we got.
71 | var dict = [String: AnyObject]()
72 | dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
73 | dict[NSLocalizedFailureReasonErrorKey] = failureReason
74 | dict[NSUnderlyingErrorKey] = error
75 | error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
76 | // Replace this with code to handle the error appropriately.
77 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
78 | NSLog("Unresolved error \(error), \(error!.userInfo)")
79 | abort()
80 | }
81 |
82 | return coordinator
83 | }()
84 |
85 | lazy var managedObjectContext: NSManagedObjectContext? = {
86 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
87 | let coordinator = self.persistentStoreCoordinator
88 | if coordinator == nil {
89 | return nil
90 | }
91 | var managedObjectContext = NSManagedObjectContext()
92 | managedObjectContext.persistentStoreCoordinator = coordinator
93 | return managedObjectContext
94 | }()
95 |
96 | // MARK: - Core Data Saving support
97 |
98 | func saveContext () {
99 | if let moc = self.managedObjectContext {
100 | var error: NSError? = nil
101 | if moc.hasChanges && !moc.save(&error) {
102 | // Replace this implementation with code to handle the error appropriately.
103 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
104 | NSLog("Unresolved error \(error), \(error!.userInfo)")
105 | abort()
106 | }
107 | }
108 | }
109 |
110 | }
111 |
112 |
--------------------------------------------------------------------------------
/Demo2/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Demo2
4 | //
5 | // Created by xlx on 15/7/20.
6 | // Copyright (c) 2015年 xlx. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,HZPhotoBrowserDelegate,XActionSheetDelegate{
12 |
13 | var tableView:UITableView!
14 | var ObjectArray = [String]()
15 | var i = 0
16 |
17 | var head:XHPathCover!
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 | // Do any additional setup after loading the view, typically from a nib.
21 |
22 |
23 | self.tableView = UITableView(frame: self.view.frame)
24 | self.view.addSubview(self.tableView)
25 | self.tableView.delegate = self
26 | self.tableView.dataSource = self
27 | self.tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "cell")
28 | self.tableView.tableFooterView = UIView()
29 |
30 | for i ; i < 10 ; i++ {
31 | self.ObjectArray.append("\(i)")
32 | }
33 |
34 | // self.tableView.addLegendHeaderWithRefreshingTarget(self, refreshingAction: "headRefresh")
35 | self.tableView.addGifFooterWithRefreshingTarget(self, refreshingAction: "footRefresh")
36 |
37 | head = XHPathCover(frame: CGRectMake(0, 0, 320, 200))
38 | head.setBackgroundImage(UIImage(named: "BG"))
39 | head.setAvatarImage(UIImage(named: "cute_girl.jpg"))
40 | head.isZoomingEffect = true;
41 | head.setInfo(NSDictionary(objectsAndKeys: "StrongX",XHUserNameKey,"iOS工程师",XHBirthdayKey)as [NSObject:AnyObject])
42 | head.avatarButton.layer.cornerRadius = 33;
43 | head.avatarButton.layer.masksToBounds = true
44 | head.avatarButton.addTarget(self, action: "PhotoBrowser", forControlEvents: UIControlEvents.TouchUpInside)
45 | head.handleRefreshEvent = {
46 | self.headRefresh()
47 | }
48 |
49 | var Line = LineView(frame: CGRectMake(0, 200, 320, 60))
50 |
51 | var HeadView = UIView(frame: CGRectMake(0, 0, 320, 200 + 60))
52 |
53 | HeadView.addSubview(Line)
54 | HeadView.addSubview(head)
55 |
56 | tableView.tableHeaderView = HeadView
57 |
58 | head.sayHello()
59 |
60 | tableView.sayHello()
61 |
62 |
63 | }
64 |
65 | override func didReceiveMemoryWarning() {
66 | super.didReceiveMemoryWarning()
67 | // Dispose of any resources that can be recreated.
68 | }
69 | func scrollViewDidScroll(scrollView: UIScrollView) {
70 | head.scrollViewDidScroll(scrollView)
71 | }
72 | func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
73 | head.scrollViewDidEndDecelerating(scrollView)
74 | }
75 | func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
76 | head.scrollViewDidEndDragging(scrollView, willDecelerate: decelerate)
77 | }
78 | func scrollViewWillBeginDragging(scrollView: UIScrollView) {
79 | head.scrollViewWillBeginDragging(scrollView)
80 | }
81 | func numberOfSectionsInTableView(tableView: UITableView) -> Int {
82 | return 1
83 | }
84 |
85 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
86 | return ObjectArray.count
87 | }
88 | func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
89 | return 80
90 | }
91 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
92 | var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
93 |
94 | for view in cell.contentView.subviews {
95 | view.removeFromSuperview()
96 | }
97 |
98 | var image = UIImageView(frame: CGRectMake(10, 10, 60, 60))
99 | image.layer.cornerRadius = 30
100 | image.layer.masksToBounds = true
101 | image.sd_setImageWithURL(NSURL(string: "http://ac-hn8w3hlp.clouddn.com/fVju6pA4WGzVGNGsVdVXEzB.png"), placeholderImage: UIImage(named: "cute_girl.jpg"))
102 | cell.contentView.addSubview(image)
103 |
104 | var label = UILabel(frame: CGRectMake(80, 30, 100, 20))
105 | label.text = "这是第\(indexPath.row)行"
106 | cell.contentView.addSubview(label)
107 |
108 |
109 |
110 | return cell
111 | }
112 | func headRefresh(){
113 | ProgressHUD.show("亲爱的,别急嘛~~~")
114 | self.Delay(2, closure: { () -> () in
115 | self.ObjectArray.removeAll(keepCapacity: false)
116 | self.i = 0
117 | for self.i ; self.i < 10 ; self.i++ {
118 | self.ObjectArray.append("\(self.i)")
119 | }
120 | // self.tableView.header.endRefreshing()
121 | self.tableView.reloadData()
122 | self.head.stopRefresh()
123 | ProgressHUD.showSuccess("人家准备好了!")
124 | })
125 | }
126 | func footRefresh(){
127 | ProgressHUD.show("还有更多内容")
128 | self.Delay(2, closure: { () -> () in
129 | var j = self.i + 10
130 | for self.i ; self.i < j ; self.i++ {
131 | self.ObjectArray.append("\(self.i)")
132 | }
133 | self.tableView.footer.endRefreshing()
134 | self.tableView.reloadData()
135 | ProgressHUD.showSuccess("好了啦~~")
136 | })
137 | }
138 | func Delay(time:Double,closure:()->()){
139 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), closure)
140 | }
141 |
142 | func PhotoBrowser(){
143 | var action = XActionSheet()
144 | action.delegate = self
145 | // action.addButtonwithTitle("拍照")
146 | action.addCancelButton("取消")
147 | // action.addButtonwithTitle("相册")
148 | // action.addButtonwithTitle("查看高清大图")
149 | action.addButtonWithTitleArray(["拍照","相册","查看高清大图"])
150 | self.presentViewController(action, animated: true) { () -> Void in
151 |
152 | }
153 |
154 | }
155 | func photoBrowser(browser: HZPhotoBrowser!, placeholderImageForIndex index: Int) -> UIImage! {
156 | return head.avatarButton.currentImage
157 | }
158 | func photoBrowser(browser: HZPhotoBrowser!, highQualityImageURLForIndex index: Int) -> NSURL! {
159 | var url = NSURL(string: "http://ac-hn8w3hlp.clouddn.com/dGWm2GEFNFoisI6beHBUQjD.png")
160 | return url
161 | }
162 | func buttonClick(index: Int) {
163 | println("\(index)")
164 | if(index == 2){
165 | var BrowserVC = HZPhotoBrowser()
166 | BrowserVC.sourceImagesContainerView = head.avatarButton
167 | BrowserVC.imageCount = 1
168 | BrowserVC.currentImageIndex = 0
169 | BrowserVC.delegate = self
170 | BrowserVC.show()
171 |
172 | }
173 | }
174 | }
175 |
176 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/UIScrollView+MJRefresh.h:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // UIScrollView+MJRefresh.h
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | // 给ScrollView增加下拉刷新、上拉刷新的功能
9 |
10 | #import
11 | #import "MJRefreshConst.h"
12 |
13 | @class MJRefreshGifHeader, MJRefreshLegendHeader, MJRefreshHeader;
14 | @class MJRefreshGifFooter, MJRefreshLegendFooter, MJRefreshFooter;
15 |
16 | @interface UIScrollView (MJRefresh)
17 | #pragma mark - 访问下拉刷新控件
18 | /** 下拉刷新控件 */
19 | @property (strong, nonatomic, readonly) MJRefreshHeader *header;
20 | /** gif功能的下拉刷新控件 */
21 | @property (nonatomic, readonly) MJRefreshGifHeader *gifHeader;
22 | /** 传统的下拉刷新控件 */
23 | @property (nonatomic, readonly) MJRefreshLegendHeader *legendHeader;
24 |
25 | #pragma mark - 添加下拉刷新控件
26 | /**
27 | * 添加一个传统的下拉刷新控件
28 | *
29 | * @param block 进入刷新状态就会自动调用这个block
30 | */
31 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block;
32 | /**
33 | * 添加一个传统的下拉刷新控件
34 | *
35 | * @param block 进入刷新状态就会自动调用这个block
36 | * @param dateKey 用来记录刷新时间的key
37 | */
38 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey;
39 | /**
40 | * 添加一个传统的下拉刷新控件
41 | *
42 | * @param target 进入刷新状态就会自动调用target对象的action方法
43 | * @param action 进入刷新状态就会自动调用target对象的action方法
44 | */
45 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
46 | /**
47 | * 添加一个传统的下拉刷新控件
48 | *
49 | * @param target 进入刷新状态就会自动调用target对象的action方法
50 | * @param action 进入刷新状态就会自动调用target对象的action方法
51 | * @param dateKey 用来记录刷新时间的key
52 | */
53 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey;
54 | /**
55 | * 添加一个gif图片的下拉刷新控件
56 | *
57 | * @param block 进入刷新状态就会自动调用这个block
58 | */
59 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block;
60 | /**
61 | * 添加一个gif图片的下拉刷新控件
62 | *
63 | * @param block 进入刷新状态就会自动调用这个block
64 | * @param dateKey 用来记录刷新时间的key
65 | */
66 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey;
67 | /**
68 | * 添加一个gif图片的下拉刷新控件
69 | *
70 | * @param target 进入刷新状态就会自动调用target对象的action方法
71 | * @param action 进入刷新状态就会自动调用target对象的action方法
72 | */
73 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
74 | /**
75 | * 添加一个gif图片的下拉刷新控件
76 | *
77 | * @param target 进入刷新状态就会自动调用target对象的action方法
78 | * @param action 进入刷新状态就会自动调用target对象的action方法
79 | * @param dateKey 用来记录刷新时间的key
80 | */
81 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey;
82 |
83 | #pragma mark - 移除下拉刷新控件
84 | /**
85 | * 移除下拉刷新控件
86 | */
87 | - (void)removeHeader;
88 |
89 | #pragma mark - 访问上拉刷新控件
90 | /** 上拉刷新控件 */
91 | @property (strong, nonatomic, readonly) MJRefreshFooter *footer;
92 | /** gif功能的上拉刷新控件 */
93 | @property (nonatomic, readonly) MJRefreshGifFooter *gifFooter;
94 | /** 传统的上拉刷新控件 */
95 | @property (nonatomic, readonly) MJRefreshLegendFooter *legendFooter;
96 |
97 | #pragma mark - 添加上拉刷新控件
98 | /**
99 | * 添加一个传统的上拉刷新控件
100 | *
101 | * @param block 进入刷新状态就会自动调用这个block
102 | */
103 | - (MJRefreshLegendFooter *)addLegendFooterWithRefreshingBlock:(void (^)())block;
104 | /**
105 | * 添加一个传统的上拉刷新控件
106 | *
107 | * @param target 进入刷新状态就会自动调用target对象的action方法
108 | * @param action 进入刷新状态就会自动调用target对象的action方法
109 | */
110 | - (MJRefreshLegendFooter *)addLegendFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
111 | /**
112 | * 添加一个gif图片的上拉刷新控件
113 | *
114 | * @param block 进入刷新状态就会自动调用这个block
115 | */
116 | - (MJRefreshGifFooter *)addGifFooterWithRefreshingBlock:(void (^)())block;
117 | /**
118 | * 添加一个gif图片的上拉刷新控件
119 | *
120 | * @param target 进入刷新状态就会自动调用target对象的action方法
121 | * @param action 进入刷新状态就会自动调用target对象的action方法
122 | */
123 | - (MJRefreshGifFooter *)addGifFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
124 |
125 | #pragma mark - 移除上拉刷新控件
126 | /**
127 | * 移除上拉刷新控件
128 | */
129 | - (void)removeFooter;
130 | @end
131 |
132 | #pragma mark - 1.0.0版本以前的接口
133 | @interface UIScrollView(MJRefreshDeprecated)
134 | #pragma mark - 下拉刷新
135 | /**
136 | * 添加一个下拉刷新头部控件
137 | *
138 | * @param callback 回调
139 | */
140 | - (void)addHeaderWithCallback:(void (^)())callback MJDeprecated("建议使用addLegendHeaderWithRefreshingBlock:");
141 |
142 | /**
143 | * 添加一个下拉刷新头部控件
144 | *
145 | * @param callback 回调
146 | * @param dateKey 刷新时间保存的key值
147 | */
148 | - (void)addHeaderWithCallback:(void (^)())callback dateKey:(NSString*)dateKey MJDeprecated("建议使用addLegendHeaderWithRefreshingBlock:dateKey:");
149 |
150 | /**
151 | * 添加一个下拉刷新头部控件
152 | *
153 | * @param target 目标
154 | * @param action 回调方法
155 | */
156 | - (void)addHeaderWithTarget:(id)target action:(SEL)action MJDeprecated("建议使用addLegendHeaderWithRefreshingTarget:refreshingAction:");
157 |
158 | /**
159 | * 添加一个下拉刷新头部控件
160 | *
161 | * @param target 目标
162 | * @param action 回调方法
163 | * @param dateKey 刷新时间保存的key值
164 | */
165 | - (void)addHeaderWithTarget:(id)target action:(SEL)action dateKey:(NSString*)dateKey MJDeprecated("建议使用addLegendHeaderWithRefreshingTarget:refreshingAction:dateKey:");
166 |
167 | /**
168 | * 主动让下拉刷新头部控件进入刷新状态
169 | */
170 | - (void)headerBeginRefreshing MJDeprecated("建议使用[self.tableView.header beginRefreshing]");
171 |
172 | /**
173 | * 让下拉刷新头部控件停止刷新状态
174 | */
175 | - (void)headerEndRefreshing MJDeprecated("建议使用[self.tableView.header endRefreshing]");
176 |
177 | /**
178 | * 下拉刷新头部控件的可见性
179 | */
180 | @property (nonatomic, assign, getter = isHeaderHidden) BOOL headerHidden MJDeprecated("建议使用self.tableView.header.hidden");
181 |
182 | /**
183 | * 是否正在下拉刷新
184 | */
185 | @property (nonatomic, assign, readonly, getter = isHeaderRefreshing) BOOL headerRefreshing MJDeprecated("建议使用self.tableView.header.isRefreshing");
186 |
187 | #pragma mark - 上拉刷新
188 | /**
189 | * 添加一个上拉刷新尾部控件
190 | *
191 | * @param callback 回调
192 | */
193 | - (void)addFooterWithCallback:(void (^)())callback MJDeprecated("建议使用addLegendFooterWithRefreshingBlock:");
194 |
195 | /**
196 | * 添加一个上拉刷新尾部控件
197 | *
198 | * @param target 目标
199 | * @param action 回调方法
200 | */
201 | - (void)addFooterWithTarget:(id)target action:(SEL)action MJDeprecated("建议使用addLegendFooterWithRefreshingTarget:refreshingAction:");
202 |
203 | /**
204 | * 主动让上拉刷新尾部控件进入刷新状态
205 | */
206 | - (void)footerBeginRefreshing MJDeprecated("建议使用[self.tableView.footer beginRefreshing]");
207 |
208 | /**
209 | * 让上拉刷新尾部控件停止刷新状态
210 | */
211 | - (void)footerEndRefreshing MJDeprecated("建议使用[self.tableView.footer endRefreshing]");
212 |
213 | /**
214 | * 上拉刷新头部控件的可见性
215 | */
216 | @property (nonatomic, assign, getter = isFooterHidden) BOOL footerHidden MJDeprecated("建议使用self.tableView.footer.hidden");
217 |
218 | /**
219 | * 是否正在上拉刷新
220 | */
221 | @property (nonatomic, assign, readonly, getter = isFooterRefreshing) BOOL footerRefreshing MJDeprecated("建议使用self.tableView.footer.isRefreshing");
222 | @end
223 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDWebImageDownloader.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 | #import "SDWebImageCompat.h"
11 | #import "SDWebImageOperation.h"
12 |
13 | typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
14 | SDWebImageDownloaderLowPriority = 1 << 0,
15 | SDWebImageDownloaderProgressiveDownload = 1 << 1,
16 |
17 | /**
18 | * By default, request prevent the of NSURLCache. With this flag, NSURLCache
19 | * is used with default policies.
20 | */
21 | SDWebImageDownloaderUseNSURLCache = 1 << 2,
22 |
23 | /**
24 | * Call completion block with nil image/imageData if the image was read from NSURLCache
25 | * (to be combined with `SDWebImageDownloaderUseNSURLCache`).
26 | */
27 |
28 | SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
29 | /**
30 | * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for
31 | * extra time in background to let the request finish. If the background task expires the operation will be cancelled.
32 | */
33 |
34 | SDWebImageDownloaderContinueInBackground = 1 << 4,
35 |
36 | /**
37 | * Handles cookies stored in NSHTTPCookieStore by setting
38 | * NSMutableURLRequest.HTTPShouldHandleCookies = YES;
39 | */
40 | SDWebImageDownloaderHandleCookies = 1 << 5,
41 |
42 | /**
43 | * Enable to allow untrusted SSL ceriticates.
44 | * Useful for testing purposes. Use with caution in production.
45 | */
46 | SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6,
47 |
48 | /**
49 | * Put the image in the high priority queue.
50 | */
51 | SDWebImageDownloaderHighPriority = 1 << 7,
52 | };
53 |
54 | typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
55 | /**
56 | * Default value. All download operations will execute in queue style (first-in-first-out).
57 | */
58 | SDWebImageDownloaderFIFOExecutionOrder,
59 |
60 | /**
61 | * All download operations will execute in stack style (last-in-first-out).
62 | */
63 | SDWebImageDownloaderLIFOExecutionOrder
64 | };
65 |
66 | extern NSString *const SDWebImageDownloadStartNotification;
67 | extern NSString *const SDWebImageDownloadStopNotification;
68 |
69 | typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize);
70 |
71 | typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished);
72 |
73 | typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers);
74 |
75 | /**
76 | * Asynchronous downloader dedicated and optimized for image loading.
77 | */
78 | @interface SDWebImageDownloader : NSObject
79 |
80 | /**
81 | * Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
82 | * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
83 | */
84 | @property (assign, nonatomic) BOOL shouldDecompressImages;
85 |
86 | @property (assign, nonatomic) NSInteger maxConcurrentDownloads;
87 |
88 | /**
89 | * Shows the current amount of downloads that still need to be downloaded
90 | */
91 | @property (readonly, nonatomic) NSUInteger currentDownloadCount;
92 |
93 |
94 | /**
95 | * The timeout value (in seconds) for the download operation. Default: 15.0.
96 | */
97 | @property (assign, nonatomic) NSTimeInterval downloadTimeout;
98 |
99 |
100 | /**
101 | * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`.
102 | */
103 | @property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;
104 |
105 | /**
106 | * Singleton method, returns the shared instance
107 | *
108 | * @return global shared instance of downloader class
109 | */
110 | + (SDWebImageDownloader *)sharedDownloader;
111 |
112 | /**
113 | * Set username
114 | */
115 | @property (strong, nonatomic) NSString *username;
116 |
117 | /**
118 | * Set password
119 | */
120 | @property (strong, nonatomic) NSString *password;
121 |
122 | /**
123 | * Set filter to pick headers for downloading image HTTP request.
124 | *
125 | * This block will be invoked for each downloading image request, returned
126 | * NSDictionary will be used as headers in corresponding HTTP request.
127 | */
128 | @property (nonatomic, copy) SDWebImageDownloaderHeadersFilterBlock headersFilter;
129 |
130 | /**
131 | * Set a value for a HTTP header to be appended to each download HTTP request.
132 | *
133 | * @param value The value for the header field. Use `nil` value to remove the header.
134 | * @param field The name of the header field to set.
135 | */
136 | - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
137 |
138 | /**
139 | * Returns the value of the specified HTTP header field.
140 | *
141 | * @return The value associated with the header field field, or `nil` if there is no corresponding header field.
142 | */
143 | - (NSString *)valueForHTTPHeaderField:(NSString *)field;
144 |
145 | /**
146 | * Sets a subclass of `SDWebImageDownloaderOperation` as the default
147 | * `NSOperation` to be used each time SDWebImage constructs a request
148 | * operation to download an image.
149 | *
150 | * @param operationClass The subclass of `SDWebImageDownloaderOperation` to set
151 | * as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`.
152 | */
153 | - (void)setOperationClass:(Class)operationClass;
154 |
155 | /**
156 | * Creates a SDWebImageDownloader async downloader instance with a given URL
157 | *
158 | * The delegate will be informed when the image is finish downloaded or an error has happen.
159 | *
160 | * @see SDWebImageDownloaderDelegate
161 | *
162 | * @param url The URL to the image to download
163 | * @param options The options to be used for this download
164 | * @param progressBlock A block called repeatedly while the image is downloading
165 | * @param completedBlock A block called once the download is completed.
166 | * If the download succeeded, the image parameter is set, in case of error,
167 | * error parameter is set with the error. The last parameter is always YES
168 | * if SDWebImageDownloaderProgressiveDownload isn't use. With the
169 | * SDWebImageDownloaderProgressiveDownload option, this block is called
170 | * repeatedly with the partial image object and the finished argument set to NO
171 | * before to be called a last time with the full image and finished argument
172 | * set to YES. In case of error, the finished argument is always YES.
173 | *
174 | * @return A cancellable SDWebImageOperation
175 | */
176 | - (id )downloadImageWithURL:(NSURL *)url
177 | options:(SDWebImageDownloaderOptions)options
178 | progress:(SDWebImageDownloaderProgressBlock)progressBlock
179 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock;
180 |
181 | /**
182 | * Sets the download queue suspension state
183 | */
184 | - (void)setSuspended:(BOOL)suspended;
185 |
186 | @end
187 |
--------------------------------------------------------------------------------
/Demo2/PathCover/XHWaterDropRefresh.m:
--------------------------------------------------------------------------------
1 | //
2 | // XHWaterDropRefresh.m
3 | // XHPathCover
4 | //
5 | // Created by 曾 宪华 on 14-2-7.
6 | // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
7 | //
8 |
9 | #import "XHWaterDropRefresh.h"
10 | #import "XHSoundManager.h"
11 |
12 | @interface XHWaterDropRefresh () {
13 | BOOL _isRefresh;
14 | }
15 |
16 | @property (nonatomic, strong) CAShapeLayer *shapeLayer;
17 | @property (nonatomic, strong) CAShapeLayer *lineLayer;
18 | @property (nonatomic, strong) UIImageView *refreshView;
19 |
20 |
21 | @property (nonatomic, strong) NSTimer *timer;
22 |
23 | @end
24 |
25 | @implementation XHWaterDropRefresh
26 |
27 | #pragma mark - Propertys
28 |
29 | - (BOOL)isRefreshing {
30 | return _isRefresh;
31 | }
32 |
33 |
34 | #pragma mark - Life cycle
35 |
36 | - (id)initWithFrame:(CGRect)frame
37 | {
38 | self = [super initWithFrame:frame];
39 | if (self) {
40 | // Initialization code
41 | [self _setup];
42 | }
43 | return self;
44 | }
45 |
46 | - (id)initWithCoder:(NSCoder *)aDecoder
47 | {
48 | self = [super initWithCoder:aDecoder];
49 | if(self)
50 | {
51 | [self _setup];
52 | }
53 | return self;
54 | }
55 |
56 | - (void)dealloc {
57 | self.refreshCircleImage = nil;
58 |
59 | self.shapeLayer = nil;
60 | self.lineLayer = nil;
61 | self.refreshView = nil;
62 | }
63 |
64 | - (void)_setup {
65 | self.deformationLength = 0.4;
66 | self.maxOffset = 70; // 改变最大拉断距离
67 | self.radius = 5.; // 改变圆圈的半径
68 | self.offsetHeight = 20; // 改变线条的长度
69 |
70 | CGRect frame = self.frame;
71 | frame.size = CGSizeMake(30, 100); //固定 30 * 100 为什么要固定本身的大小呢?
72 | self.frame = frame;
73 |
74 | _lineLayer = [CAShapeLayer layer];
75 | _lineLayer.fillColor = [UIColor colorWithRed:222./255. green:216./255. blue:211./255. alpha:0.5].CGColor;
76 | [self.layer addSublayer:_lineLayer];
77 |
78 |
79 | _shapeLayer = [CAShapeLayer layer];
80 | _shapeLayer.fillColor = [UIColor colorWithRed:222./255. green:216./255. blue:211./255. alpha:1].CGColor;
81 | _shapeLayer.strokeColor = [[UIColor whiteColor] CGColor];
82 | _shapeLayer.lineWidth = 2;
83 | [self.layer addSublayer:_shapeLayer];
84 |
85 | self.currentOffset = 0;
86 | }
87 |
88 | #pragma mark - Publish Api
89 |
90 | - (void)stopRefresh {
91 | _isRefresh = NO;
92 |
93 | CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
94 | anim.fromValue = @(1);
95 | anim.toValue = @(0);
96 | anim.duration = 0.2;
97 | anim.delegate = self;
98 | [_refreshView.layer addAnimation:anim forKey:nil];
99 | _refreshView.layer.opacity = 0;
100 |
101 |
102 | anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
103 | anim.fromValue = @(0);
104 | anim.toValue = @(1);
105 | anim.beginTime = 0.2;
106 | anim.duration = 0.2;
107 | anim.delegate = self;
108 | [_shapeLayer addAnimation:anim forKey:nil];
109 | _shapeLayer.opacity = 0;
110 | }
111 |
112 |
113 | - (void)startRefreshAnimation {
114 | if(self.refreshView == nil) {
115 | _refreshView = [[UIImageView alloc] initWithImage:self.refreshCircleImage];
116 | CGRect refreshViewFrame = _refreshView.frame;
117 | refreshViewFrame.size = CGSizeMake(18, 18);
118 | [self addSubview:_refreshView];
119 | }
120 | _shapeLayer.opacity = 0;
121 |
122 | _refreshView.center = CGPointMake(15,self.frame.size.height - 20 - _radius);
123 | [_refreshView.layer removeAllAnimations];
124 | _refreshView.layer.opacity = 1;
125 |
126 | CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
127 | animation.duration = 1;
128 | animation.fromValue = @0;
129 | animation.toValue = @(M_PI*2);
130 | animation.repeatCount = INT_MAX;
131 |
132 | [_refreshView.layer addAnimation:animation forKey:@"rotation"];
133 | }
134 |
135 | #pragma mark - CGMutablePathRef Help Method
136 |
137 | - (CGMutablePathRef)createPathWithOffset:(float)currentOffset {
138 | CGMutablePathRef path = CGPathCreateMutable();
139 | float top = self.frame.size.height - 20 - _radius*2 - currentOffset;
140 | float wdiff = currentOffset * self.deformationLength; // 改变拉断之前,水滴的长度
141 |
142 | if(currentOffset == 0) {
143 | CGPathAddEllipseInRect(path, NULL, CGRectMake(15-_radius, top, _radius*2, _radius*2));
144 | } else {
145 | CGPathAddArc(path, NULL, 15, top+_radius, _radius, 0, M_PI, YES);
146 | float bottom = top + wdiff+_radius*2;
147 | if(currentOffset < 10) {
148 | CGPathAddCurveToPoint(path, NULL,15-_radius,bottom,15,bottom, 15,bottom);
149 | CGPathAddCurveToPoint(path, NULL, 15,bottom,15+_radius,bottom, 15+_radius, top+_radius);
150 | } else {
151 | CGPathAddCurveToPoint(path, NULL,15-_radius ,top +_radius, 15 - _radius ,bottom - _radius, 15, bottom);
152 | CGPathAddCurveToPoint(path,NULL, 15 + _radius, bottom - _radius, 15+_radius,top +_radius , 15+_radius, top+_radius);
153 | }
154 | }
155 | CGPathCloseSubpath(path);
156 |
157 | return path;
158 | }
159 |
160 | - (void)setCurrentOffset:(float)currentOffset {
161 | if(_isRefresh)
162 | return;
163 |
164 | [self privateSetCurrentOffset:currentOffset];
165 | }
166 |
167 | - (void)privateSetCurrentOffset:(float)currentOffset {
168 | currentOffset = currentOffset>0?0:currentOffset;
169 | currentOffset = -currentOffset;
170 | _currentOffset = currentOffset;
171 | if(currentOffset < _maxOffset) {
172 | float wdiff = currentOffset* 0.2;
173 | float top = self.frame.size.height - 20 - _radius*2 - currentOffset;
174 |
175 | CGMutablePathRef path = [self createPathWithOffset:currentOffset];
176 | _shapeLayer.path = path;
177 | CGPathRelease(path);
178 |
179 |
180 | CGMutablePathRef line = CGPathCreateMutable();
181 | float w = ((_maxOffset - currentOffset)/_maxOffset) + 1;
182 | CGPathAddRect(line, NULL, CGRectMake(15-w/2, top + wdiff + _radius*2,w, currentOffset-wdiff + self.offsetHeight)); // 最好的+20就是线条的长度
183 | _lineLayer.path = line;
184 |
185 | self.transform = CGAffineTransformMakeScale(0.8+0.2*(w-1), 1);
186 | } else {
187 | if(self.timer == nil)
188 | {
189 | _isRefresh = YES;
190 | self.transform = CGAffineTransformIdentity;
191 | self.timer = [NSTimer timerWithTimeInterval:0.02 target:self selector:@selector(resetWater) userInfo:nil repeats:YES];
192 | [[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
193 | [_timer fire];
194 | }
195 | }
196 | }
197 |
198 | - (void)resetWater {
199 | [self privateSetCurrentOffset:-(_currentOffset-(_maxOffset/8))];
200 | if(_currentOffset == 0) {
201 | [self.timer invalidate];
202 | self.timer = nil;
203 |
204 | // play refresh stop sound
205 | [[XHSoundManager sharedInstance] playRefreshSound];
206 |
207 | if(self.handleRefreshEvent != nil) {
208 | self.handleRefreshEvent();
209 | }
210 | [self startRefreshAnimation];
211 | }
212 | }
213 |
214 |
215 | - (void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag {
216 | if(anim.beginTime > 0) {
217 | _shapeLayer.opacity = 1;
218 | } else {
219 | [_refreshView.layer removeAllAnimations];
220 | }
221 | }
222 |
223 | /*
224 | // Only override drawRect: if you perform custom drawing.
225 | // An empty implementation adversely affects performance during animation.
226 | - (void)drawRect:(CGRect)rect
227 | {
228 | // Drawing code
229 | }
230 | */
231 |
232 | @end
233 |
--------------------------------------------------------------------------------
/Demo2/HZPhotoBrowserView.m:
--------------------------------------------------------------------------------
1 | //
2 | // HZPhotoBrowserView.m
3 | // photoBrowser
4 | //
5 | // Created by huangzhenyu on 15/6/23.
6 | // Copyright (c) 2015年 eamon. All rights reserved.
7 | //
8 |
9 | #import "HZPhotoBrowserView.h"
10 | #import "HZIndicatorView.h"
11 | #import "HZPhotoBrowserConfig.h"
12 | #import "UIImageView+WebCache.h"
13 |
14 | @interface HZPhotoBrowserView()
15 | @property (nonatomic,strong) HZIndicatorView *indicatorView;
16 | @property (nonatomic,strong) UITapGestureRecognizer *doubleTap;
17 | @property (nonatomic,strong) UITapGestureRecognizer *singleTap;
18 | @property (nonatomic, assign) BOOL hasLoadedImage;//图片下载成功为YES 否则为NO
19 | @property (nonatomic, strong) NSURL *imageUrl;
20 | @property (nonatomic, strong) UIImage *placeHolderImage;
21 | @property (nonatomic, strong) UIButton *reloadButton;
22 | @end
23 |
24 | @implementation HZPhotoBrowserView
25 | - (instancetype)initWithFrame:(CGRect)frame
26 | {
27 | if (self = [super initWithFrame:frame]) {
28 | [self addSubview:self.scrollview];
29 | //添加单双击事件
30 | [self addGestureRecognizer:self.doubleTap];
31 | [self addGestureRecognizer:self.singleTap];
32 | }
33 | return self;
34 | }
35 |
36 | - (UIScrollView *)scrollview
37 | {
38 | if (!_scrollview) {
39 | _scrollview = [[UIScrollView alloc] init];
40 | _scrollview.frame = CGRectMake(0, 0, kAPPWidth, kAppHeight);
41 | [_scrollview addSubview:self.imageview];
42 | _scrollview.delegate = self;
43 | _scrollview.clipsToBounds = YES;
44 | }
45 | return _scrollview;
46 | }
47 |
48 | - (UIImageView *)imageview
49 | {
50 | if (!_imageview) {
51 | _imageview = [[UIImageView alloc] init];
52 | _imageview.frame = CGRectMake(0, 0, kAPPWidth, kAppHeight);
53 | _imageview.userInteractionEnabled = YES;
54 | }
55 | return _imageview;
56 | }
57 |
58 | - (UITapGestureRecognizer *)doubleTap
59 | {
60 | if (!_doubleTap) {
61 | _doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
62 | _doubleTap.numberOfTapsRequired = 2;
63 | _doubleTap.numberOfTouchesRequired =1;
64 | }
65 | return _doubleTap;
66 | }
67 |
68 | - (UITapGestureRecognizer *)singleTap
69 | {
70 | if (!_singleTap) {
71 | _singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
72 | _singleTap.numberOfTapsRequired = 1;
73 | _singleTap.numberOfTouchesRequired = 1;
74 | //只能有一个手势存在
75 | [_singleTap requireGestureRecognizerToFail:self.doubleTap];
76 |
77 | }
78 | return _singleTap;
79 | }
80 |
81 | #pragma mark 双击
82 | - (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer
83 | {
84 | //图片加载完之后才能响应双击放大
85 | if (!self.hasLoadedImage) {
86 | return;
87 | }
88 | CGPoint touchPoint = [recognizer locationInView:self];
89 | if (self.scrollview.zoomScale <= 1.0) {
90 |
91 | CGFloat scaleX = touchPoint.x + self.scrollview.contentOffset.x;//需要放大的图片的X点
92 | CGFloat sacleY = touchPoint.y + self.scrollview.contentOffset.y;//需要放大的图片的Y点
93 | [self.scrollview zoomToRect:CGRectMake(scaleX, sacleY, 10, 10) animated:YES];
94 |
95 | } else {
96 | [self.scrollview setZoomScale:1.0 animated:YES]; //还原
97 | }
98 |
99 | }
100 | #pragma mark 单击
101 | - (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
102 | {
103 | if (self.singleTapBlock) {
104 | self.singleTapBlock(recognizer);
105 | }
106 | }
107 |
108 |
109 | - (void)setProgress:(CGFloat)progress
110 | {
111 | _progress = progress;
112 | _indicatorView.progress = progress;
113 | }
114 |
115 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder
116 | {
117 | if (_reloadButton) {
118 | [_reloadButton removeFromSuperview];
119 | }
120 | _imageUrl = url;
121 | _placeHolderImage = placeholder;
122 | //添加进度指示器
123 | HZIndicatorView *indicatorView = [[HZIndicatorView alloc] init];
124 | indicatorView.viewMode = HZIndicatorViewModeLoopDiagram;
125 | indicatorView.center = CGPointMake(kAPPWidth * 0.5, kAppHeight * 0.5);
126 | self.indicatorView = indicatorView;
127 | [self addSubview:indicatorView];
128 |
129 | //SDWebImage加载图片
130 | __weak __typeof(self)weakSelf = self;
131 | [_imageview sd_setImageWithURL:url placeholderImage:placeholder options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
132 | __strong __typeof(weakSelf)strongSelf = weakSelf;
133 | strongSelf.indicatorView.progress = (CGFloat)receivedSize / expectedSize;
134 |
135 | } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
136 | __strong __typeof(weakSelf)strongSelf = weakSelf;
137 | [_indicatorView removeFromSuperview];
138 |
139 | if (error) {
140 | //图片加载失败的处理,此处可以自定义各种操作(...)
141 |
142 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
143 | strongSelf.reloadButton = button;
144 | button.layer.cornerRadius = 2;
145 | button.clipsToBounds = YES;
146 | button.bounds = CGRectMake(0, 0, 200, 40);
147 | button.center = CGPointMake(kAPPWidth * 0.5, kAppHeight * 0.5);
148 | button.titleLabel.font = [UIFont systemFontOfSize:14];
149 | button.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.3f];
150 | [button setTitle:@"原图加载失败,点击重新加载" forState:UIControlStateNormal];
151 | [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
152 | [button addTarget:strongSelf action:@selector(reloadImage) forControlEvents:UIControlEventTouchUpInside];
153 |
154 | [self addSubview:button];
155 | return;
156 | }
157 | strongSelf.hasLoadedImage = YES;//图片加载成功
158 | }];
159 | }
160 |
161 | - (void)reloadImage
162 | {
163 | [self setImageWithURL:_imageUrl placeholderImage:_placeHolderImage];
164 | }
165 |
166 | - (void)layoutSubviews
167 | {
168 | [super layoutSubviews];
169 | _indicatorView.center = _scrollview.center;
170 | _scrollview.frame = self.bounds;
171 | _reloadButton.center = CGPointMake(kAPPWidth * 0.5, kAppHeight * 0.5);
172 | [self adjustFrames];
173 | }
174 |
175 | - (void)adjustFrames
176 | {
177 | CGRect frame = self.scrollview.frame;
178 | if (self.imageview.image) {
179 | CGSize imageSize = self.imageview.image.size;
180 | CGRect imageFrame = CGRectMake(0, 0, imageSize.width, imageSize.height);
181 | if (kIsFullWidthForLandScape) {
182 | CGFloat ratio = frame.size.width/imageFrame.size.width;
183 | imageFrame.size.height = imageFrame.size.height*ratio;
184 | imageFrame.size.width = frame.size.width;
185 | } else{
186 | if (frame.size.width<=frame.size.height) {
187 |
188 | CGFloat ratio = frame.size.width/imageFrame.size.width;
189 | imageFrame.size.height = imageFrame.size.height*ratio;
190 | imageFrame.size.width = frame.size.width;
191 | }else{
192 | CGFloat ratio = frame.size.height/imageFrame.size.height;
193 | imageFrame.size.width = imageFrame.size.width*ratio;
194 | imageFrame.size.height = frame.size.height;
195 | }
196 | }
197 |
198 | self.imageview.frame = imageFrame;
199 | self.scrollview.contentSize = self.imageview.frame.size;
200 | self.imageview.center = [self centerOfScrollViewContent:self.scrollview];
201 |
202 |
203 | CGFloat maxScale = frame.size.height/imageFrame.size.height;
204 | maxScale = frame.size.width/imageFrame.size.width>maxScale?frame.size.width/imageFrame.size.width:maxScale;
205 | maxScale = maxScale>kMaxZoomScale?maxScale:kMaxZoomScale;
206 |
207 | self.scrollview.minimumZoomScale = kMinZoomScale;
208 | self.scrollview.maximumZoomScale = maxScale;
209 | self.scrollview.zoomScale = 1.0f;
210 | }else{
211 | frame.origin = CGPointZero;
212 | self.imageview.frame = frame;
213 | self.scrollview.contentSize = self.imageview.frame.size;
214 | }
215 | self.scrollview.contentOffset = CGPointZero;
216 |
217 | }
218 |
219 | - (CGPoint)centerOfScrollViewContent:(UIScrollView *)scrollView
220 | {
221 | CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)?
222 | (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;
223 | CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?
224 | (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;
225 | CGPoint actualCenter = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
226 | scrollView.contentSize.height * 0.5 + offsetY);
227 | return actualCenter;
228 | }
229 |
230 | #pragma mark UIScrollViewDelegate
231 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
232 | {
233 | return self.imageview;
234 | }
235 |
236 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView
237 | {
238 | self.imageview.center = [self centerOfScrollViewContent:scrollView];
239 | }
240 | @end
241 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/SDImageCache.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import
10 | #import "SDWebImageCompat.h"
11 |
12 | typedef NS_ENUM(NSInteger, SDImageCacheType) {
13 | /**
14 | * The image wasn't available the SDWebImage caches, but was downloaded from the web.
15 | */
16 | SDImageCacheTypeNone,
17 | /**
18 | * The image was obtained from the disk cache.
19 | */
20 | SDImageCacheTypeDisk,
21 | /**
22 | * The image was obtained from the memory cache.
23 | */
24 | SDImageCacheTypeMemory
25 | };
26 |
27 | typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType cacheType);
28 |
29 | typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache);
30 |
31 | typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize);
32 |
33 | /**
34 | * SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed
35 | * asynchronous so it doesn’t add unnecessary latency to the UI.
36 | */
37 | @interface SDImageCache : NSObject
38 |
39 | /**
40 | * Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
41 | * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
42 | */
43 | @property (assign, nonatomic) BOOL shouldDecompressImages;
44 |
45 | /**
46 | * disable iCloud backup [defaults to YES]
47 | */
48 | @property (assign, nonatomic) BOOL shouldDisableiCloud;
49 |
50 | /**
51 | * use memory cache [defaults to YES]
52 | */
53 | @property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
54 |
55 | /**
56 | * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
57 | */
58 | @property (assign, nonatomic) NSUInteger maxMemoryCost;
59 |
60 | /**
61 | * The maximum number of objects the cache should hold.
62 | */
63 | @property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
64 |
65 | /**
66 | * The maximum length of time to keep an image in the cache, in seconds
67 | */
68 | @property (assign, nonatomic) NSInteger maxCacheAge;
69 |
70 | /**
71 | * The maximum size of the cache, in bytes.
72 | */
73 | @property (assign, nonatomic) NSUInteger maxCacheSize;
74 |
75 | /**
76 | * Returns global shared cache instance
77 | *
78 | * @return SDImageCache global instance
79 | */
80 | + (SDImageCache *)sharedImageCache;
81 |
82 | /**
83 | * Init a new cache store with a specific namespace
84 | *
85 | * @param ns The namespace to use for this cache store
86 | */
87 | - (id)initWithNamespace:(NSString *)ns;
88 |
89 | /**
90 | * Init a new cache store with a specific namespace and directory
91 | *
92 | * @param ns The namespace to use for this cache store
93 | * @param directory Directory to cache disk images in
94 | */
95 | - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory;
96 |
97 | -(NSString *)makeDiskCachePath:(NSString*)fullNamespace;
98 |
99 | /**
100 | * Add a read-only cache path to search for images pre-cached by SDImageCache
101 | * Useful if you want to bundle pre-loaded images with your app
102 | *
103 | * @param path The path to use for this read-only cache path
104 | */
105 | - (void)addReadOnlyCachePath:(NSString *)path;
106 |
107 | /**
108 | * Store an image into memory and disk cache at the given key.
109 | *
110 | * @param image The image to store
111 | * @param key The unique image cache key, usually it's image absolute URL
112 | */
113 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key;
114 |
115 | /**
116 | * Store an image into memory and optionally disk cache at the given key.
117 | *
118 | * @param image The image to store
119 | * @param key The unique image cache key, usually it's image absolute URL
120 | * @param toDisk Store the image to disk cache if YES
121 | */
122 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk;
123 |
124 | /**
125 | * Store an image into memory and optionally disk cache at the given key.
126 | *
127 | * @param image The image to store
128 | * @param recalculate BOOL indicates if imageData can be used or a new data should be constructed from the UIImage
129 | * @param imageData The image data as returned by the server, this representation will be used for disk storage
130 | * instead of converting the given image object into a storable/compressed image format in order
131 | * to save quality and CPU
132 | * @param key The unique image cache key, usually it's image absolute URL
133 | * @param toDisk Store the image to disk cache if YES
134 | */
135 | - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk;
136 |
137 | /**
138 | * Query the disk cache asynchronously.
139 | *
140 | * @param key The unique key used to store the wanted image
141 | */
142 | - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
143 |
144 | /**
145 | * Query the memory cache synchronously.
146 | *
147 | * @param key The unique key used to store the wanted image
148 | */
149 | - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key;
150 |
151 | /**
152 | * Query the disk cache synchronously after checking the memory cache.
153 | *
154 | * @param key The unique key used to store the wanted image
155 | */
156 | - (UIImage *)imageFromDiskCacheForKey:(NSString *)key;
157 |
158 | /**
159 | * Remove the image from memory and disk cache synchronously
160 | *
161 | * @param key The unique image cache key
162 | */
163 | - (void)removeImageForKey:(NSString *)key;
164 |
165 |
166 | /**
167 | * Remove the image from memory and disk cache asynchronously
168 | *
169 | * @param key The unique image cache key
170 | * @param completion An block that should be executed after the image has been removed (optional)
171 | */
172 | - (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion;
173 |
174 | /**
175 | * Remove the image from memory and optionally disk cache asynchronously
176 | *
177 | * @param key The unique image cache key
178 | * @param fromDisk Also remove cache entry from disk if YES
179 | */
180 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk;
181 |
182 | /**
183 | * Remove the image from memory and optionally disk cache asynchronously
184 | *
185 | * @param key The unique image cache key
186 | * @param fromDisk Also remove cache entry from disk if YES
187 | * @param completion An block that should be executed after the image has been removed (optional)
188 | */
189 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion;
190 |
191 | /**
192 | * Clear all memory cached images
193 | */
194 | - (void)clearMemory;
195 |
196 | /**
197 | * Clear all disk cached images. Non-blocking method - returns immediately.
198 | * @param completion An block that should be executed after cache expiration completes (optional)
199 | */
200 | - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion;
201 |
202 | /**
203 | * Clear all disk cached images
204 | * @see clearDiskOnCompletion:
205 | */
206 | - (void)clearDisk;
207 |
208 | /**
209 | * Remove all expired cached image from disk. Non-blocking method - returns immediately.
210 | * @param completionBlock An block that should be executed after cache expiration completes (optional)
211 | */
212 | - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock;
213 |
214 | /**
215 | * Remove all expired cached image from disk
216 | * @see cleanDiskWithCompletionBlock:
217 | */
218 | - (void)cleanDisk;
219 |
220 | /**
221 | * Get the size used by the disk cache
222 | */
223 | - (NSUInteger)getSize;
224 |
225 | /**
226 | * Get the number of images in the disk cache
227 | */
228 | - (NSUInteger)getDiskCount;
229 |
230 | /**
231 | * Asynchronously calculate the disk cache's size.
232 | */
233 | - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock;
234 |
235 | /**
236 | * Async check if image exists in disk cache already (does not load the image)
237 | *
238 | * @param key the key describing the url
239 | * @param completionBlock the block to be executed when the check is done.
240 | * @note the completion block will be always executed on the main queue
241 | */
242 | - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock;
243 |
244 | /**
245 | * Check if image exists in disk cache already (does not load the image)
246 | *
247 | * @param key the key describing the url
248 | *
249 | * @return YES if an image exists for the given key
250 | */
251 | - (BOOL)diskImageExistsWithKey:(NSString *)key;
252 |
253 | /**
254 | * Get the cache path for a certain key (needs the cache path root folder)
255 | *
256 | * @param key the key (can be obtained from url using cacheKeyForURL)
257 | * @param path the cach path root folder
258 | *
259 | * @return the cache path
260 | */
261 | - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path;
262 |
263 | /**
264 | * Get the default cache path for a certain key
265 | *
266 | * @param key the key (can be obtained from url using cacheKeyForURL)
267 | *
268 | * @return the default cache path
269 | */
270 | - (NSString *)defaultCachePathForKey:(NSString *)key;
271 |
272 | @end
273 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/UIScrollView+MJRefresh.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // UIScrollView+MJRefresh.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/4.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "UIScrollView+MJRefresh.h"
11 | #import "MJRefreshGifHeader.h"
12 | #import "MJRefreshLegendHeader.h"
13 | #import "MJRefreshGifFooter.h"
14 | #import "MJRefreshLegendFooter.h"
15 | #import
16 |
17 | @implementation UIScrollView (MJRefresh)
18 | #pragma mark - 下拉刷新
19 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey
20 | {
21 | MJRefreshLegendHeader *header = [self addLegendHeader];
22 | header.refreshingBlock = block;
23 | header.dateKey = dateKey;
24 | return header;
25 | }
26 |
27 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey
28 | {
29 | MJRefreshLegendHeader *header = [self addLegendHeader];
30 | header.refreshingTarget = target;
31 | header.refreshingAction = action;
32 | header.dateKey = dateKey;
33 | return header;
34 | }
35 |
36 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action
37 | {
38 | return [self addLegendHeaderWithRefreshingTarget:target refreshingAction:action dateKey:nil];
39 | }
40 |
41 | - (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block
42 | {
43 | return [self addLegendHeaderWithRefreshingBlock:block dateKey:nil];
44 | }
45 |
46 | - (MJRefreshLegendHeader *)addLegendHeader
47 | {
48 | MJRefreshLegendHeader *header = [[MJRefreshLegendHeader alloc] init];
49 | self.header = header;
50 |
51 | return header;
52 | }
53 |
54 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey
55 | {
56 | MJRefreshGifHeader *header = [self addGifHeader];
57 | header.refreshingBlock = block;
58 | header.dateKey = dateKey;
59 | return header;
60 | }
61 |
62 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey
63 | {
64 | MJRefreshGifHeader *header = [self addGifHeader];
65 | header.refreshingTarget = target;
66 | header.refreshingAction = action;
67 | header.dateKey = dateKey;
68 | return header;
69 | }
70 |
71 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block
72 | {
73 | return [self addGifHeaderWithRefreshingBlock:block dateKey:nil];
74 | }
75 |
76 | - (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action
77 | {
78 | return [self addGifHeaderWithRefreshingTarget:target refreshingAction:action dateKey:nil];
79 | }
80 |
81 | - (MJRefreshGifHeader *)addGifHeader
82 | {
83 | MJRefreshGifHeader *header = [[MJRefreshGifHeader alloc] init];
84 | self.header = header;
85 |
86 | return header;
87 | }
88 |
89 | - (void)removeHeader
90 | {
91 | self.header = nil;
92 | }
93 |
94 | #pragma mark - Property Methods
95 | #pragma mark gifHeader
96 | - (MJRefreshGifHeader *)gifHeader
97 | {
98 | if ([self.header isKindOfClass:[MJRefreshGifHeader class]]) {
99 | return (MJRefreshGifHeader *)self.header;
100 | }
101 |
102 | return nil;
103 | }
104 |
105 | #pragma mark legendHeader
106 | - (MJRefreshLegendHeader *)legendHeader
107 | {
108 | if ([self.header isKindOfClass:[MJRefreshLegendHeader class]]) {
109 | return (MJRefreshLegendHeader *)self.header;
110 | }
111 |
112 | return nil;
113 | }
114 |
115 | #pragma mark header
116 | static char MJRefreshHeaderKey;
117 | - (void)setHeader:(MJRefreshHeader *)header
118 | {
119 | if (header != self.header) {
120 | [self.header removeFromSuperview];
121 |
122 | [self willChangeValueForKey:@"header"];
123 | objc_setAssociatedObject(self, &MJRefreshHeaderKey,
124 | header,
125 | OBJC_ASSOCIATION_ASSIGN);
126 | [self didChangeValueForKey:@"header"];
127 |
128 | [self addSubview:header];
129 | }
130 | }
131 |
132 | - (MJRefreshHeader *)header
133 | {
134 | return objc_getAssociatedObject(self, &MJRefreshHeaderKey);
135 | }
136 |
137 | #pragma mark - 上拉刷新
138 | - (MJRefreshLegendFooter *)addLegendFooterWithRefreshingBlock:(void (^)())block
139 | {
140 | MJRefreshLegendFooter *footer = [self addLegendFooter];
141 | footer.refreshingBlock = block;
142 | return footer;
143 | }
144 |
145 | - (MJRefreshLegendFooter *)addLegendFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action
146 | {
147 | MJRefreshLegendFooter *footer = [self addLegendFooter];
148 | footer.refreshingTarget = target;
149 | footer.refreshingAction = action;
150 | return footer;
151 | }
152 |
153 | - (MJRefreshLegendFooter *)addLegendFooter
154 | {
155 | MJRefreshLegendFooter *footer = [[MJRefreshLegendFooter alloc] init];
156 | self.footer = footer;
157 |
158 | return footer;
159 | }
160 |
161 | - (MJRefreshGifFooter *)addGifFooterWithRefreshingBlock:(void (^)())block
162 | {
163 | MJRefreshGifFooter *footer = [self addGifFooter];
164 | footer.refreshingBlock = block;
165 | return footer;
166 | }
167 |
168 | - (MJRefreshGifFooter *)addGifFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action
169 | {
170 | MJRefreshGifFooter *footer = [self addGifFooter];
171 | footer.refreshingTarget = target;
172 | footer.refreshingAction = action;
173 | return footer;
174 | }
175 |
176 | - (MJRefreshGifFooter *)addGifFooter
177 | {
178 | MJRefreshGifFooter *footer = [[MJRefreshGifFooter alloc] init];
179 | self.footer = footer;
180 |
181 | return footer;
182 | }
183 |
184 | - (void)removeFooter
185 | {
186 | self.footer = nil;
187 | }
188 |
189 | static char MJRefreshFooterKey;
190 | - (void)setFooter:(MJRefreshFooter *)footer
191 | {
192 | if (footer != self.footer) {
193 | [self.footer removeFromSuperview];
194 |
195 | [self willChangeValueForKey:@"footer"];
196 | objc_setAssociatedObject(self, &MJRefreshFooterKey,
197 | footer,
198 | OBJC_ASSOCIATION_ASSIGN);
199 | [self didChangeValueForKey:@"footer"];
200 |
201 | [self addSubview:footer];
202 | }
203 | }
204 |
205 | - (MJRefreshGifFooter *)gifFooter
206 | {
207 | if ([self.footer isKindOfClass:[MJRefreshGifFooter class]]) {
208 | return (MJRefreshGifFooter *)self.footer;
209 | }
210 | return nil;
211 | }
212 |
213 | - (MJRefreshLegendFooter *)legendFooter
214 | {
215 | if ([self.footer isKindOfClass:[MJRefreshLegendFooter class]]) {
216 | return (MJRefreshLegendFooter *)self.footer;
217 | }
218 | return nil;
219 | }
220 |
221 |
222 | - (MJRefreshFooter *)footer
223 | {
224 | return objc_getAssociatedObject(self, &MJRefreshFooterKey);
225 | }
226 |
227 | #pragma mark - swizzle
228 | + (void)load
229 | {
230 | Method method1 = class_getInstanceMethod([self class], NSSelectorFromString(@"dealloc"));
231 | Method method2 = class_getInstanceMethod([self class], @selector(deallocSwizzle));
232 | method_exchangeImplementations(method1, method2);
233 | }
234 |
235 | - (void)deallocSwizzle
236 | {
237 | [self removeFooter];
238 | [self removeHeader];
239 |
240 | [self deallocSwizzle];
241 | }
242 |
243 | @end
244 |
245 |
246 | #pragma mark - 1.0.0版本以前的接口
247 | @implementation UIScrollView(MJRefreshDeprecated)
248 | #pragma mark - 下拉刷新
249 | /**
250 | * 添加一个下拉刷新头部控件
251 | *
252 | * @param callback 回调
253 | */
254 | - (void)addHeaderWithCallback:(void (^)())callback
255 | {
256 | [self addHeaderWithCallback:callback dateKey:nil];
257 | }
258 |
259 | /**
260 | * 添加一个下拉刷新头部控件
261 | *
262 | * @param callback 回调
263 | * @param dateKey 刷新时间保存的key值
264 | */
265 | - (void)addHeaderWithCallback:(void (^)())callback dateKey:(NSString*)dateKey
266 | {
267 | [self addLegendHeader];
268 | self.header.dateKey = dateKey;
269 | self.header.refreshingBlock = callback;
270 | }
271 |
272 | /**
273 | * 添加一个下拉刷新头部控件
274 | *
275 | * @param target 目标
276 | * @param action 回调方法
277 | */
278 | - (void)addHeaderWithTarget:(id)target action:(SEL)action
279 | {
280 | [self addHeaderWithTarget:target action:action dateKey:nil];
281 | }
282 |
283 | /**
284 | * 添加一个下拉刷新头部控件
285 | *
286 | * @param target 目标
287 | * @param action 回调方法
288 | * @param dateKey 刷新时间保存的key值
289 | */
290 | - (void)addHeaderWithTarget:(id)target action:(SEL)action dateKey:(NSString*)dateKey
291 | {
292 | [self addLegendHeader];
293 | self.header.dateKey = dateKey;
294 | [self.header setRefreshingTarget:target refreshingAction:action];
295 | }
296 |
297 | /**
298 | * 主动让下拉刷新头部控件进入刷新状态
299 | */
300 | - (void)headerBeginRefreshing
301 | {
302 | [self.header beginRefreshing];
303 | }
304 |
305 | /**
306 | * 让下拉刷新头部控件停止刷新状态
307 | */
308 | - (void)headerEndRefreshing
309 | {
310 | [self.header endRefreshing];
311 | }
312 |
313 | /**
314 | * 下拉刷新头部控件的可见性
315 | */
316 | - (void)setHeaderHidden:(BOOL)headerHidden
317 | {
318 | self.header.hidden = headerHidden;
319 | }
320 |
321 | - (BOOL)isHeaderHidden
322 | {
323 | return self.header.isHidden;
324 | }
325 |
326 | /**
327 | * 是否正在下拉刷新
328 | */
329 | - (BOOL)isHeaderRefreshing
330 | {
331 | return self.header.isRefreshing;
332 | }
333 |
334 | #pragma mark - 上拉刷新
335 | /**
336 | * 添加一个上拉刷新尾部控件
337 | *
338 | * @param callback 回调
339 | */
340 | - (void)addFooterWithCallback:(void (^)())callback
341 | {
342 | [self addLegendFooter];
343 | self.footer.refreshingBlock = callback;
344 | }
345 |
346 | /**
347 | * 添加一个上拉刷新尾部控件
348 | *
349 | * @param target 目标
350 | * @param action 回调方法
351 | */
352 | - (void)addFooterWithTarget:(id)target action:(SEL)action
353 | {
354 | [self addLegendFooter];
355 | [self.footer setRefreshingTarget:target refreshingAction:action];
356 | }
357 |
358 | /**
359 | * 主动让上拉刷新尾部控件进入刷新状态
360 | */
361 | - (void)footerBeginRefreshing
362 | {
363 | [self.footer beginRefreshing];
364 | }
365 |
366 | /**
367 | * 让上拉刷新尾部控件停止刷新状态
368 | */
369 | - (void)footerEndRefreshing
370 | {
371 | [self.footer endRefreshing];
372 | }
373 |
374 | /**
375 | * 上拉刷新头部控件的可见性
376 | */
377 | - (void)setFooterHidden:(BOOL)footerHidden
378 | {
379 | self.footer.hidden = footerHidden;
380 | }
381 |
382 | - (BOOL)isFooterHidden
383 | {
384 | return self.footer.isHidden;
385 | }
386 |
387 | /**
388 | * 是否正在上拉刷新
389 | */
390 | - (BOOL)isFooterRefreshing
391 | {
392 | return self.footer.isRefreshing;
393 | }
394 | @end
395 |
--------------------------------------------------------------------------------
/Demo2/SDWebImage/UIImageView+WebCache.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the SDWebImage package.
3 | * (c) Olivier Poitrey
4 | *
5 | * For the full copyright and license information, please view the LICENSE
6 | * file that was distributed with this source code.
7 | */
8 |
9 | #import "SDWebImageCompat.h"
10 | #import "SDWebImageManager.h"
11 |
12 | /**
13 | * Integrates SDWebImage async downloading and caching of remote images with UIImageView.
14 | *
15 | * Usage with a UITableViewCell sub-class:
16 | *
17 | * @code
18 |
19 | #import
20 |
21 | ...
22 |
23 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
24 | {
25 | static NSString *MyIdentifier = @"MyIdentifier";
26 |
27 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
28 |
29 | if (cell == nil) {
30 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier]
31 | autorelease];
32 | }
33 |
34 | // Here we use the provided sd_setImageWithURL: method to load the web image
35 | // Ensure you use a placeholder image otherwise cells will be initialized with no image
36 | [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://example.com/image.jpg"]
37 | placeholderImage:[UIImage imageNamed:@"placeholder"]];
38 |
39 | cell.textLabel.text = @"My Text";
40 | return cell;
41 | }
42 |
43 | * @endcode
44 | */
45 | @interface UIImageView (WebCache)
46 |
47 | /**
48 | * Get the current image URL.
49 | *
50 | * Note that because of the limitations of categories this property can get out of sync
51 | * if you use sd_setImage: directly.
52 | */
53 | - (NSURL *)sd_imageURL;
54 |
55 | /**
56 | * Set the imageView `image` with an `url`.
57 | *
58 | * The download is asynchronous and cached.
59 | *
60 | * @param url The url for the image.
61 | */
62 | - (void)sd_setImageWithURL:(NSURL *)url;
63 |
64 | /**
65 | * Set the imageView `image` with an `url` and a placeholder.
66 | *
67 | * The download is asynchronous and cached.
68 | *
69 | * @param url The url for the image.
70 | * @param placeholder The image to be set initially, until the image request finishes.
71 | * @see sd_setImageWithURL:placeholderImage:options:
72 | */
73 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
74 |
75 | /**
76 | * Set the imageView `image` with an `url`, placeholder and custom options.
77 | *
78 | * The download is asynchronous and cached.
79 | *
80 | * @param url The url for the image.
81 | * @param placeholder The image to be set initially, until the image request finishes.
82 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
83 | */
84 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
85 |
86 | /**
87 | * Set the imageView `image` with an `url`.
88 | *
89 | * The download is asynchronous and cached.
90 | *
91 | * @param url The url for the image.
92 | * @param completedBlock A block called when operation has been completed. This block has no return value
93 | * and takes the requested UIImage as first parameter. In case of error the image parameter
94 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
95 | * indicating if the image was retrived from the local cache or from the network.
96 | * The fourth parameter is the original image url.
97 | */
98 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
99 |
100 | /**
101 | * Set the imageView `image` with an `url`, placeholder.
102 | *
103 | * The download is asynchronous and cached.
104 | *
105 | * @param url The url for the image.
106 | * @param placeholder The image to be set initially, until the image request finishes.
107 | * @param completedBlock A block called when operation has been completed. This block has no return value
108 | * and takes the requested UIImage as first parameter. In case of error the image parameter
109 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
110 | * indicating if the image was retrived from the local cache or from the network.
111 | * The fourth parameter is the original image url.
112 | */
113 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
114 |
115 | /**
116 | * Set the imageView `image` with an `url`, placeholder and custom options.
117 | *
118 | * The download is asynchronous and cached.
119 | *
120 | * @param url The url for the image.
121 | * @param placeholder The image to be set initially, until the image request finishes.
122 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
123 | * @param completedBlock A block called when operation has been completed. This block has no return value
124 | * and takes the requested UIImage as first parameter. In case of error the image parameter
125 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
126 | * indicating if the image was retrived from the local cache or from the network.
127 | * The fourth parameter is the original image url.
128 | */
129 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
130 |
131 | /**
132 | * Set the imageView `image` with an `url`, placeholder and custom options.
133 | *
134 | * The download is asynchronous and cached.
135 | *
136 | * @param url The url for the image.
137 | * @param placeholder The image to be set initially, until the image request finishes.
138 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
139 | * @param progressBlock A block called while image is downloading
140 | * @param completedBlock A block called when operation has been completed. This block has no return value
141 | * and takes the requested UIImage as first parameter. In case of error the image parameter
142 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
143 | * indicating if the image was retrived from the local cache or from the network.
144 | * The fourth parameter is the original image url.
145 | */
146 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
147 |
148 | /**
149 | * Set the imageView `image` with an `url` and a optionaly placeholder image.
150 | *
151 | * The download is asynchronous and cached.
152 | *
153 | * @param url The url for the image.
154 | * @param placeholder The image to be set initially, until the image request finishes.
155 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
156 | * @param progressBlock A block called while image is downloading
157 | * @param completedBlock A block called when operation has been completed. This block has no return value
158 | * and takes the requested UIImage as first parameter. In case of error the image parameter
159 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
160 | * indicating if the image was retrived from the local cache or from the network.
161 | * The fourth parameter is the original image url.
162 | */
163 | - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
164 |
165 | /**
166 | * Download an array of images and starts them in an animation loop
167 | *
168 | * @param arrayOfURLs An array of NSURL
169 | */
170 | - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs;
171 |
172 | /**
173 | * Cancel the current download
174 | */
175 | - (void)sd_cancelCurrentImageLoad;
176 |
177 | - (void)sd_cancelCurrentAnimationImagesLoad;
178 |
179 | /**
180 | * Show activity UIActivityIndicatorView
181 | */
182 | - (void)setShowActivityIndicatorView:(BOOL)show;
183 |
184 | /**
185 | * set desired UIActivityIndicatorViewStyle
186 | *
187 | * @param style The style of the UIActivityIndicatorView
188 | */
189 | - (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
190 |
191 | @end
192 |
193 |
194 | @interface UIImageView (WebCacheDeprecated)
195 |
196 | - (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`");
197 |
198 | - (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`");
199 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`");
200 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options`");
201 |
202 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`");
203 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`");
204 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`");
205 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:progress:completed:`");
206 |
207 | - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs __deprecated_msg("Use `sd_setAnimationImagesWithURLs:`");
208 |
209 | - (void)cancelCurrentArrayLoad __deprecated_msg("Use `sd_cancelCurrentAnimationImagesLoad`");
210 |
211 | - (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`");
212 |
213 | @end
214 |
--------------------------------------------------------------------------------
/Demo2/MJRefresh/MJRefreshFooter.m:
--------------------------------------------------------------------------------
1 | // 代码地址: https://github.com/CoderMJLee/MJRefresh
2 | // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
3 | // MJRefreshFooter.m
4 | // MJRefreshExample
5 | //
6 | // Created by MJ Lee on 15/3/5.
7 | // Copyright (c) 2015年 itcast. All rights reserved.
8 | //
9 |
10 | #import "MJRefreshFooter.h"
11 | #import "MJRefreshConst.h"
12 | #import "UIScrollView+MJExtension.h"
13 | #import "MJRefreshHeader.h"
14 | #import "UIView+MJExtension.h"
15 | #import "UIScrollView+MJRefresh.h"
16 | #import
17 |
18 | @interface MJRefreshFooter()
19 | /** 显示状态文字的标签 */
20 | @property (weak, nonatomic) UILabel *stateLabel;
21 | /** 点击可以加载更多 */
22 | @property (weak, nonatomic) UIButton *loadMoreButton;
23 | /** 没有更多的数据 */
24 | @property (weak, nonatomic) UILabel *noMoreLabel;
25 | /** 即将要执行的代码 */
26 | @property (strong, nonatomic) NSMutableArray *willExecuteBlocks;
27 | @end
28 |
29 | @implementation MJRefreshFooter
30 | #pragma mark - 懒加载
31 | - (NSMutableArray *)willExecuteBlocks
32 | {
33 | if (!_willExecuteBlocks) {
34 | self.willExecuteBlocks = [NSMutableArray array];
35 | }
36 | return _willExecuteBlocks;
37 | }
38 |
39 | - (UIButton *)loadMoreButton
40 | {
41 | if (!_loadMoreButton) {
42 | UIButton *loadMoreButton = [[UIButton alloc] init];
43 | loadMoreButton.backgroundColor = [UIColor clearColor];
44 | [loadMoreButton addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
45 | [self addSubview:_loadMoreButton = loadMoreButton];
46 | }
47 | return _loadMoreButton;
48 | }
49 |
50 | - (UILabel *)noMoreLabel
51 | {
52 | if (!_noMoreLabel) {
53 | UILabel *noMoreLabel = [[UILabel alloc] init];
54 | noMoreLabel.backgroundColor = [UIColor clearColor];
55 | noMoreLabel.textAlignment = NSTextAlignmentCenter;
56 | [self addSubview:_noMoreLabel = noMoreLabel];
57 | }
58 | return _noMoreLabel;
59 | }
60 |
61 | - (UILabel *)stateLabel
62 | {
63 | if (!_stateLabel) {
64 | UILabel *stateLabel = [[UILabel alloc] init];
65 | stateLabel.backgroundColor = [UIColor clearColor];
66 | stateLabel.textAlignment = NSTextAlignmentCenter;
67 | [self addSubview:_stateLabel = stateLabel];
68 | }
69 | return _stateLabel;
70 | }
71 |
72 | #pragma mark - 初始化方法
73 | - (instancetype)initWithFrame:(CGRect)frame {
74 | if (self = [super initWithFrame:frame]) {
75 | // 默认底部控件100%出现时才会自动刷新
76 | self.appearencePercentTriggerAutoRefresh = 1.0;
77 |
78 | // 设置为默认状态
79 | self.automaticallyRefresh = YES;
80 | self.state = MJRefreshFooterStateIdle;
81 |
82 | // 初始化文字
83 | [self setTitle:MJRefreshFooterStateIdleText forState:MJRefreshFooterStateIdle];
84 | [self setTitle:MJRefreshFooterStateRefreshingText forState:MJRefreshFooterStateRefreshing];
85 | [self setTitle:MJRefreshFooterStateNoMoreDataText forState:MJRefreshFooterStateNoMoreData];
86 | }
87 | return self;
88 | }
89 |
90 | - (void)willMoveToSuperview:(UIView *)newSuperview
91 | {
92 | [super willMoveToSuperview:newSuperview];
93 |
94 | // 旧的父控件
95 | [self.superview removeObserver:self forKeyPath:MJRefreshContentSize context:nil];
96 | [self.superview removeObserver:self forKeyPath:MJRefreshPanState context:nil];
97 |
98 | if (newSuperview) { // 新的父控件
99 | // 监听
100 | [newSuperview addObserver:self forKeyPath:MJRefreshContentSize options:NSKeyValueObservingOptionNew context:nil];
101 | [newSuperview addObserver:self forKeyPath:MJRefreshPanState options:NSKeyValueObservingOptionNew context:nil];
102 |
103 | self.mj_h = MJRefreshFooterHeight;
104 | _scrollView.mj_insetB += self.mj_h;
105 |
106 | // 重新调整frame
107 | [self adjustFrameWithContentSize];
108 | } else { // 被移除了
109 | _scrollView.mj_insetB -= self.mj_h;
110 | }
111 | }
112 |
113 | - (void)layoutSubviews
114 | {
115 | [super layoutSubviews];
116 |
117 | self.loadMoreButton.frame = self.bounds;
118 | self.stateLabel.frame = self.bounds;
119 | self.noMoreLabel.frame = self.bounds;
120 | }
121 |
122 | #pragma mark - 私有方法
123 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
124 | {
125 | // 遇到这些情况就直接返回
126 | if (!self.userInteractionEnabled || self.alpha <= 0.01 || self.hidden) return;
127 |
128 | if (self.state == MJRefreshFooterStateIdle) {
129 | // 当是Idle状态时,才需要检测是否要进入刷新状态
130 | if ([keyPath isEqualToString:MJRefreshPanState]) {
131 | if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) {// 手松开
132 | if (_scrollView.mj_insetT + _scrollView.mj_contentSizeH <= _scrollView.mj_h) { // 不够一个屏幕
133 | if (_scrollView.mj_offsetY > - _scrollView.mj_insetT) { // 向上拽
134 | [self beginRefreshing];
135 | }
136 | } else { // 超出一个屏幕
137 | if (_scrollView.mj_offsetY > _scrollView.mj_contentSizeH + _scrollView.mj_insetB - _scrollView.mj_h) {
138 | [self beginRefreshing];
139 | }
140 | }
141 | }
142 | } else if ([keyPath isEqualToString:MJRefreshContentOffset]) {
143 | if (self.state != MJRefreshFooterStateRefreshing && self.automaticallyRefresh) {
144 | // 根据contentOffset调整state
145 | [self adjustStateWithContentOffset];
146 | }
147 | }
148 | }
149 |
150 | // 不管是什么状态,都要调整位置
151 | if ([keyPath isEqualToString:MJRefreshContentSize]) {
152 | [self adjustFrameWithContentSize];
153 | }
154 | }
155 |
156 | #pragma mark 根据contentOffset调整state
157 | - (void)adjustStateWithContentOffset
158 | {
159 | if (self.mj_y == 0) return;
160 |
161 | if (_scrollView.mj_insetT + _scrollView.mj_contentSizeH > _scrollView.mj_h) { // 内容超过一个屏幕
162 | // 这里的_scrollView.mj_contentSizeH替换掉self.mj_y更为合理
163 | if (_scrollView.mj_offsetY > _scrollView.mj_contentSizeH - _scrollView.mj_h + self.mj_h * self.appearencePercentTriggerAutoRefresh + _scrollView.mj_insetB - self.mj_h) {
164 | // 当底部刷新控件完全出现时,才刷新
165 | [self beginRefreshing];
166 | }
167 | }
168 | }
169 |
170 | - (void)adjustFrameWithContentSize
171 | {
172 | // 设置位置
173 | self.mj_y = _scrollView.mj_contentSizeH;
174 | }
175 |
176 | - (void)buttonClick
177 | {
178 | [self beginRefreshing];
179 | }
180 |
181 | #pragma mark - 公共方法
182 | - (void)setHidden:(BOOL)hidden
183 | {
184 | __weak __typeof(self) weakSelf = self;
185 | BOOL lastHidden = weakSelf.isHidden;
186 | CGFloat h = weakSelf.mj_h;
187 | [weakSelf.willExecuteBlocks addObject:^{
188 | if (!lastHidden && hidden) {
189 | weakSelf.state = MJRefreshFooterStateIdle;
190 | _scrollView.mj_insetB -= h;
191 | } else if (lastHidden && !hidden) {
192 | _scrollView.mj_insetB += h;
193 |
194 | [weakSelf adjustFrameWithContentSize];
195 | }
196 | }];
197 | [weakSelf setNeedsDisplay]; // 放到drawRect是为了延迟执行,防止因为修改了inset,导致循环调用数据源方法
198 |
199 | [super setHidden:hidden];
200 | }
201 |
202 | - (void)drawRect:(CGRect)rect
203 | {
204 | [super drawRect:rect];
205 |
206 | for (void (^block)() in self.willExecuteBlocks) {
207 | block();
208 | }
209 | [self.willExecuteBlocks removeAllObjects];
210 | }
211 |
212 | - (void)beginRefreshing
213 | {
214 | self.state = MJRefreshFooterStateRefreshing;
215 | }
216 |
217 | - (void)endRefreshing
218 | {
219 | self.state = MJRefreshFooterStateIdle;
220 | }
221 |
222 | - (BOOL)isRefreshing
223 | {
224 | return self.state == MJRefreshFooterStateRefreshing;
225 | }
226 |
227 | - (void)noticeNoMoreData
228 | {
229 | self.state = MJRefreshFooterStateNoMoreData;
230 | }
231 |
232 | - (void)resetNoMoreData
233 | {
234 | self.state = MJRefreshFooterStateIdle;
235 | }
236 |
237 | - (void)setTitle:(NSString *)title forState:(MJRefreshFooterState)state
238 | {
239 | if (title == nil) return;
240 |
241 | // 刷新当前状态的文字
242 | switch (state) {
243 | case MJRefreshFooterStateIdle:
244 | [self.loadMoreButton setTitle:title forState:UIControlStateNormal];
245 | break;
246 |
247 | case MJRefreshFooterStateRefreshing:
248 | self.stateLabel.text = title;
249 | break;
250 |
251 | case MJRefreshFooterStateNoMoreData:
252 | self.noMoreLabel.text = title;
253 | break;
254 |
255 | default:
256 | break;
257 | }
258 | }
259 |
260 | - (void)setState:(MJRefreshFooterState)state
261 | {
262 | if (_state == state) return;
263 |
264 | _state = state;
265 |
266 | switch (state) {
267 | case MJRefreshFooterStateIdle:{
268 | self.noMoreLabel.hidden = YES;
269 | self.stateLabel.hidden = YES;
270 | self.loadMoreButton.hidden = YES;
271 |
272 | //修复传统上拉加载更多在 UITableView 使用 '- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;'方法加载更多数据时露出按钮的的问题
273 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
274 | self.loadMoreButton.hidden = self.state != MJRefreshFooterStateIdle;
275 | });
276 | }
277 | break;
278 |
279 | case MJRefreshFooterStateRefreshing:
280 | {
281 | self.loadMoreButton.hidden = YES;
282 | self.noMoreLabel.hidden = YES;
283 | if (!self.stateHidden) self.stateLabel.hidden = NO;
284 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
285 | if (self.refreshingBlock) {
286 | self.refreshingBlock();
287 | }
288 | if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
289 | msgSend(msgTarget(self.refreshingTarget), self.refreshingAction, self);
290 | }
291 | });
292 | }
293 | break;
294 |
295 | case MJRefreshFooterStateNoMoreData:
296 | self.loadMoreButton.hidden = YES;
297 | self.noMoreLabel.hidden = NO;
298 | self.stateLabel.hidden = YES;
299 | break;
300 |
301 | default:
302 | break;
303 | }
304 | }
305 |
306 | - (void)setTextColor:(UIColor *)textColor
307 | {
308 | [super setTextColor:textColor];
309 |
310 | self.stateLabel.textColor = textColor;
311 | [self.loadMoreButton setTitleColor:textColor forState:UIControlStateNormal];
312 | self.noMoreLabel.textColor = textColor;
313 | }
314 |
315 | - (void)setFont:(UIFont *)font
316 | {
317 | [super setFont:font];
318 |
319 | self.loadMoreButton.titleLabel.font = font;
320 | self.noMoreLabel.font = font;
321 | self.stateLabel.font = font;
322 | }
323 |
324 | - (void)setStateHidden:(BOOL)stateHidden
325 | {
326 | _stateHidden = stateHidden;
327 |
328 | self.stateLabel.hidden = stateHidden;
329 | [self setNeedsLayout];
330 | }
331 | @end
332 |
--------------------------------------------------------------------------------