├── .gitignore ├── LICENSE ├── README.md ├── XLRemoteImageView.podspec ├── XLRemoteImageView ├── Podfile ├── Podfile.lock ├── XLRemoteImageView.xcodeproj │ └── project.pbxproj ├── XLRemoteImageView.xcworkspace │ └── contents.xcworkspacedata ├── XLRemoteImageView │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── xl_appicon_120.png │ │ │ ├── xl_appicon_58.png │ │ │ └── xl_appicon_80.png │ │ └── LaunchImage.launchimage │ │ │ ├── Contents.json │ │ │ └── xl_splash@2x.png │ ├── ViewController.h │ ├── ViewController.m │ ├── XL │ │ ├── UIImageView+XLNetworking.h │ │ ├── UIImageView+XLNetworking.m │ │ ├── UIImageView+XLProgressIndicator.h │ │ ├── UIImageView+XLProgressIndicator.m │ │ ├── XLCircleProgressIndicator.h │ │ └── XLCircleProgressIndicator.m │ ├── XLRemoteImageView-Info.plist │ ├── XLRemoteImageView-Prefix.pch │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainStoryboard.storyboard │ └── main.m └── XLRemoteImageViewTests │ ├── XLRemoteImageViewTests-Info.plist │ ├── XLRemoteImageViewTests.h │ ├── XLRemoteImageViewTests.m │ └── en.lproj │ └── InfoPlist.strings └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 xmartlabs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | XLRemoteImageView 2 | ================= 3 | 4 | By [XMARTLABS](http://xmartlabs.com). 5 | 6 | Purpose 7 | -------------- 8 | 9 | UIImageView categories that show a progress indicator while the image is being downloaded. It uses the same NSCache and NSOperation objects used in UIImageView+AFNetworking category. It looks like Instagram loading indicator. 10 | 11 | Installation 12 | -------- 13 | 14 | The easiest way to integrate XLRemoteImageView in your projects is via [CocoaPods](http://cocoapods.org). 15 | 16 | 1. Add the following line in the project's Podfile file: `pod 'XLRemoteImageView', '~> 2.0'` 17 | 18 | 2. Run the command `pod install` from the Podfile folder directory. 19 | 20 | You can also install XLRemoteImageView manually. We don't recommend this approach. 21 | The source files you will need are in XLRemoteImageView/XLRemoteImageView/XL folder. 22 | 23 | 24 | Example 25 | -------- 26 | 27 | Take a look at `ViewController.m` in the example project for details on how to use this component. In short, though: 28 | 29 | 30 | ```objc 31 | // show a circle progress indicator 32 | [self.imageView setImageWithProgressIndicatorAndURL:[NSURL URLWithString:url]]; 33 | ``` 34 | 35 | UIImageView+XLProgressIndicator.h adds other helper methods: 36 | 37 | ```objc 38 | // same behaviour as previous method showing a placeholder image while the download is in progress. 39 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 40 | placeholderImage:(UIImage *)placeholderImage 41 | ``` 42 | 43 | and 44 | 45 | ```objc 46 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 47 | placeholderImage:(UIImage *)placeholderImage 48 | imageDidAppearBlock:(void (^)(UIImageView *))imageDidAppearBlock 49 | ``` 50 | 51 | The above methods use UIImageView+XLNetworking category, that let you know the image download progress. 52 | 53 | ```objc 54 | - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 55 | placeholderImage:(UIImage *)placeholderImage 56 | success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success 57 | failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure 58 | downloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadProgressBlock; 59 | ``` 60 | 61 | 62 | ![Screenshot](https://raw.github.com/xmartlabs/XLRemoteImageView/master/screenshot.png) 63 | 64 | 65 | Appearance customization 66 | -------- 67 | 68 | ```objc 69 | 70 | // progress color, yellow color in the example image. 71 | [[XLCircleProgressIndicator appearance] setStrokeProgressColor:[UIColor colorWithHex:COLOR_PROGRESSBAR_PROGRESS]]; 72 | 73 | // remaining color, gray color in the example image 74 | [[XLCircleProgressIndicator appearance] setStrokeRemainingColor:[UIColor colorWithHex:COLOR_PROGRESSBAR_BACKGROUND]]; 75 | 76 | //In order to set up the circle stroke's width you can choose between these 2 ways. 77 | [[XLCircleProgressIndicator appearance] setStrokeWidth:3.0f]; 78 | 79 | //or 80 | 81 | //the width of the circle stroke gets calculated based on the UIImageView size, 82 | //[[XLCircleProgressIndicator appearance] setStrokeWidthRatio:0.15f]; 83 | 84 | ``` 85 | 86 | 87 | XLRemoteImageView files 88 | -------- 89 | 90 | 1. `UIImageView+XLNetworking.h`. UIImageView category that allow us to know the download progress of an image using NSCache and NSOperation used by AFNetworking. 91 | 2. `UIImageView+XLProgressIndicator.h`. UIImageView category that allow us to show an circle progress view indicator on a UIImageView while its UIImage is being downloaded. 92 | 3. `XLCircleProgressIndicator.h`. UIView that shows a circle progress view. This source code is based on: https://github.com/swissmanu/MACircleProgressIndicator. 93 | 94 | License 95 | -------- 96 | XLRemoteImageView is distributed under MIT license, please feel free to use it and contribute. 97 | 98 | Requirements 99 | ----------------------------- 100 | 101 | * ARC 102 | * iOS 7.0 and above 103 | 104 | Release Notes 105 | -------------- 106 | 107 | Version 2.0.0 (cocoaPod) 108 | 109 | * Supports AFNetworking ~> 2.0. 110 | * Bug fixes. 111 | * Tested on iOS 7 & 7.1. 112 | 113 | Version 1.0.0 (cocoaPod) 114 | 115 | * Initial release. 116 | * Tested on ios 5 & 6. 117 | * AFNetworking ~> 1.3 support. 118 | 119 | Author 120 | ----------------- 121 | 122 | [Martin Barreto](https://www.github.com/mtnBarreto "Martin Barreto Github") ([@mtnBarreto](http://twitter.com/mtnBarreto "@mtnBarreto")) 123 | 124 | Contact 125 | -------- 126 | 127 | Any suggestion or question? Please create a Github issue or reach us out. 128 | 129 | [xmartlabs.com](http://xmartlabs.com) ([@xmartlabs](http://twitter.com/xmartlabs "@xmartlabs")) 130 | -------------------------------------------------------------------------------- /XLRemoteImageView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'XLRemoteImageView' 3 | s.version = '2.0.0' 4 | s.license = 'MIT' 5 | s.summary = 'UIImageView categories that show a progress indicator while the image is being downloaded.' 6 | s.description = <<-DESC 7 | It uses the same NSCache and NSOperation objects used in UIImageView+AFNetworking category. 8 | It looks like Instagram loading indicator. 9 | DESC 10 | s.homepage = 'https://github.com/xmartlabs/XLRemoteImageView' 11 | s.authors = { 'Martin Barreto' => 'martin@xmartlabs.com' } 12 | s.source = { :git => 'https://github.com/xmartlabs/XLRemoteImageView.git', :tag => 'v2.0.0' } 13 | s.source_files = 'XLRemoteImageView/XLRemoteImageView/XL/*.{h,m}' 14 | s.requires_arc = true 15 | s.dependency 'AFNetworking', '~> 2.0' 16 | s.ios.deployment_target = '7.0' 17 | s.ios.frameworks = 'UIKit', 'Foundation' 18 | end 19 | -------------------------------------------------------------------------------- /XLRemoteImageView/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, 7.0 2 | 3 | pod 'AFNetworking', '~> 2.0' 4 | -------------------------------------------------------------------------------- /XLRemoteImageView/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (2.3.1): 3 | - AFNetworking/NSURLConnection (= 2.3.1) 4 | - AFNetworking/NSURLSession (= 2.3.1) 5 | - AFNetworking/Reachability (= 2.3.1) 6 | - AFNetworking/Security (= 2.3.1) 7 | - AFNetworking/Serialization (= 2.3.1) 8 | - AFNetworking/UIKit (= 2.3.1) 9 | - AFNetworking/NSURLConnection (2.3.1): 10 | - AFNetworking/Reachability 11 | - AFNetworking/Security 12 | - AFNetworking/Serialization 13 | - AFNetworking/NSURLSession (2.3.1): 14 | - AFNetworking/Reachability 15 | - AFNetworking/Security 16 | - AFNetworking/Serialization 17 | - AFNetworking/Reachability (2.3.1) 18 | - AFNetworking/Security (2.3.1) 19 | - AFNetworking/Serialization (2.3.1) 20 | - AFNetworking/UIKit (2.3.1): 21 | - AFNetworking/NSURLConnection 22 | - AFNetworking/NSURLSession 23 | 24 | DEPENDENCIES: 25 | - AFNetworking (~> 2.0) 26 | 27 | SPEC CHECKSUMS: 28 | AFNetworking: 05b9f6e3aa5ac45bc383b4bb108ef338080a26c7 29 | 30 | COCOAPODS: 0.36.4 31 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 285DEF9319883A2A00109FF5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 285DEF9219883A2A00109FF5 /* Images.xcassets */; }; 11 | 28C7028F17D4E4B500C8507E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28C7028E17D4E4B500C8507E /* UIKit.framework */; }; 12 | 28C7029117D4E4B500C8507E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28C7029017D4E4B500C8507E /* Foundation.framework */; }; 13 | 28C7029917D4E4B500C8507E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 28C7029717D4E4B500C8507E /* InfoPlist.strings */; }; 14 | 28C7029B17D4E4B500C8507E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C7029A17D4E4B500C8507E /* main.m */; }; 15 | 28C7029F17D4E4B500C8507E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C7029E17D4E4B500C8507E /* AppDelegate.m */; }; 16 | 28C702A817D4E4B500C8507E /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 28C702A617D4E4B500C8507E /* MainStoryboard.storyboard */; }; 17 | 28C702AB17D4E4B500C8507E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C702AA17D4E4B500C8507E /* ViewController.m */; }; 18 | 28C702B417D4E4B500C8507E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28C7028E17D4E4B500C8507E /* UIKit.framework */; }; 19 | 28C702B517D4E4B500C8507E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28C7029017D4E4B500C8507E /* Foundation.framework */; }; 20 | 28C702BD17D4E4B500C8507E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 28C702BB17D4E4B500C8507E /* InfoPlist.strings */; }; 21 | 28C702C017D4E4B500C8507E /* XLRemoteImageViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C702BF17D4E4B500C8507E /* XLRemoteImageViewTests.m */; }; 22 | 28C702CE17D5330D00C8507E /* XLCircleProgressIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C702CB17D5330D00C8507E /* XLCircleProgressIndicator.m */; }; 23 | 28C702D817D6465A00C8507E /* UIImageView+XLNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C702D717D6465A00C8507E /* UIImageView+XLNetworking.m */; }; 24 | 28C702DB17D7728100C8507E /* UIImageView+XLProgressIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C702DA17D7728000C8507E /* UIImageView+XLProgressIndicator.m */; }; 25 | F867C11010694CB4B3D451A6 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A21E9A23DFAC48938AB408DD /* libPods.a */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | 28C702B617D4E4B500C8507E /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 28C7028317D4E4B500C8507E /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 28C7028A17D4E4B500C8507E; 34 | remoteInfo = XLRemoteImageView; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 285DEF9219883A2A00109FF5 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 40 | 28C7028B17D4E4B500C8507E /* XLRemoteImageView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XLRemoteImageView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 28C7028E17D4E4B500C8507E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 42 | 28C7029017D4E4B500C8507E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 43 | 28C7029617D4E4B500C8507E /* XLRemoteImageView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "XLRemoteImageView-Info.plist"; sourceTree = ""; }; 44 | 28C7029817D4E4B500C8507E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 45 | 28C7029A17D4E4B500C8507E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | 28C7029C17D4E4B500C8507E /* XLRemoteImageView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XLRemoteImageView-Prefix.pch"; sourceTree = ""; }; 47 | 28C7029D17D4E4B500C8507E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | 28C7029E17D4E4B500C8507E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | 28C702A717D4E4B500C8507E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; }; 50 | 28C702A917D4E4B500C8507E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 51 | 28C702AA17D4E4B500C8507E /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 52 | 28C702B117D4E4B500C8507E /* XLRemoteImageViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XLRemoteImageViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 28C702BA17D4E4B500C8507E /* XLRemoteImageViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "XLRemoteImageViewTests-Info.plist"; sourceTree = ""; }; 54 | 28C702BC17D4E4B500C8507E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 55 | 28C702BE17D4E4B500C8507E /* XLRemoteImageViewTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XLRemoteImageViewTests.h; sourceTree = ""; }; 56 | 28C702BF17D4E4B500C8507E /* XLRemoteImageViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XLRemoteImageViewTests.m; sourceTree = ""; }; 57 | 28C702CA17D5330D00C8507E /* XLCircleProgressIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLCircleProgressIndicator.h; path = XL/XLCircleProgressIndicator.h; sourceTree = ""; }; 58 | 28C702CB17D5330D00C8507E /* XLCircleProgressIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLCircleProgressIndicator.m; path = XL/XLCircleProgressIndicator.m; sourceTree = ""; }; 59 | 28C702D617D6465A00C8507E /* UIImageView+XLNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImageView+XLNetworking.h"; path = "XL/UIImageView+XLNetworking.h"; sourceTree = ""; }; 60 | 28C702D717D6465A00C8507E /* UIImageView+XLNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+XLNetworking.m"; path = "XL/UIImageView+XLNetworking.m"; sourceTree = ""; }; 61 | 28C702D917D7728000C8507E /* UIImageView+XLProgressIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImageView+XLProgressIndicator.h"; path = "XL/UIImageView+XLProgressIndicator.h"; sourceTree = ""; }; 62 | 28C702DA17D7728000C8507E /* UIImageView+XLProgressIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+XLProgressIndicator.m"; path = "XL/UIImageView+XLProgressIndicator.m"; sourceTree = ""; }; 63 | 6C98144AE67C5125D689423F /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 64 | A21E9A23DFAC48938AB408DD /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | C862175F70C1789B1B896E54 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 66 | /* End PBXFileReference section */ 67 | 68 | /* Begin PBXFrameworksBuildPhase section */ 69 | 28C7028817D4E4B500C8507E /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | 28C7028F17D4E4B500C8507E /* UIKit.framework in Frameworks */, 74 | 28C7029117D4E4B500C8507E /* Foundation.framework in Frameworks */, 75 | F867C11010694CB4B3D451A6 /* libPods.a in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | 28C702AD17D4E4B500C8507E /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | 28C702B417D4E4B500C8507E /* UIKit.framework in Frameworks */, 84 | 28C702B517D4E4B500C8507E /* Foundation.framework in Frameworks */, 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | 28C7028217D4E4B500C8507E = { 92 | isa = PBXGroup; 93 | children = ( 94 | 28C7029417D4E4B500C8507E /* XLRemoteImageView */, 95 | 28C702B817D4E4B500C8507E /* XLRemoteImageViewTests */, 96 | 28C7028D17D4E4B500C8507E /* Frameworks */, 97 | 28C7028C17D4E4B500C8507E /* Products */, 98 | 2A7B9F36448D57055689D4D0 /* Pods */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 28C7028C17D4E4B500C8507E /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 28C7028B17D4E4B500C8507E /* XLRemoteImageView.app */, 106 | 28C702B117D4E4B500C8507E /* XLRemoteImageViewTests.xctest */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | 28C7028D17D4E4B500C8507E /* Frameworks */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 28C7028E17D4E4B500C8507E /* UIKit.framework */, 115 | 28C7029017D4E4B500C8507E /* Foundation.framework */, 116 | A21E9A23DFAC48938AB408DD /* libPods.a */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | 28C7029417D4E4B500C8507E /* XLRemoteImageView */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 28C702C917D5308C00C8507E /* XL */, 125 | 28C7029D17D4E4B500C8507E /* AppDelegate.h */, 126 | 28C7029E17D4E4B500C8507E /* AppDelegate.m */, 127 | 28C702A617D4E4B500C8507E /* MainStoryboard.storyboard */, 128 | 28C702A917D4E4B500C8507E /* ViewController.h */, 129 | 28C702AA17D4E4B500C8507E /* ViewController.m */, 130 | 285DEF9219883A2A00109FF5 /* Images.xcassets */, 131 | 28C7029517D4E4B500C8507E /* Supporting Files */, 132 | ); 133 | path = XLRemoteImageView; 134 | sourceTree = ""; 135 | }; 136 | 28C7029517D4E4B500C8507E /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 28C7029617D4E4B500C8507E /* XLRemoteImageView-Info.plist */, 140 | 28C7029717D4E4B500C8507E /* InfoPlist.strings */, 141 | 28C7029A17D4E4B500C8507E /* main.m */, 142 | 28C7029C17D4E4B500C8507E /* XLRemoteImageView-Prefix.pch */, 143 | ); 144 | name = "Supporting Files"; 145 | sourceTree = ""; 146 | }; 147 | 28C702B817D4E4B500C8507E /* XLRemoteImageViewTests */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 28C702BE17D4E4B500C8507E /* XLRemoteImageViewTests.h */, 151 | 28C702BF17D4E4B500C8507E /* XLRemoteImageViewTests.m */, 152 | 28C702B917D4E4B500C8507E /* Supporting Files */, 153 | ); 154 | path = XLRemoteImageViewTests; 155 | sourceTree = ""; 156 | }; 157 | 28C702B917D4E4B500C8507E /* Supporting Files */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 28C702BA17D4E4B500C8507E /* XLRemoteImageViewTests-Info.plist */, 161 | 28C702BB17D4E4B500C8507E /* InfoPlist.strings */, 162 | ); 163 | name = "Supporting Files"; 164 | sourceTree = ""; 165 | }; 166 | 28C702C917D5308C00C8507E /* XL */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 28C702CA17D5330D00C8507E /* XLCircleProgressIndicator.h */, 170 | 28C702CB17D5330D00C8507E /* XLCircleProgressIndicator.m */, 171 | 28C702D617D6465A00C8507E /* UIImageView+XLNetworking.h */, 172 | 28C702D717D6465A00C8507E /* UIImageView+XLNetworking.m */, 173 | 28C702D917D7728000C8507E /* UIImageView+XLProgressIndicator.h */, 174 | 28C702DA17D7728000C8507E /* UIImageView+XLProgressIndicator.m */, 175 | ); 176 | name = XL; 177 | sourceTree = ""; 178 | }; 179 | 2A7B9F36448D57055689D4D0 /* Pods */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 6C98144AE67C5125D689423F /* Pods.debug.xcconfig */, 183 | C862175F70C1789B1B896E54 /* Pods.release.xcconfig */, 184 | ); 185 | name = Pods; 186 | sourceTree = ""; 187 | }; 188 | /* End PBXGroup section */ 189 | 190 | /* Begin PBXNativeTarget section */ 191 | 28C7028A17D4E4B500C8507E /* XLRemoteImageView */ = { 192 | isa = PBXNativeTarget; 193 | buildConfigurationList = 28C702C317D4E4B500C8507E /* Build configuration list for PBXNativeTarget "XLRemoteImageView" */; 194 | buildPhases = ( 195 | 6644797C8E04464C80EF8DB9 /* Check Pods Manifest.lock */, 196 | 28C7028717D4E4B500C8507E /* Sources */, 197 | 28C7028817D4E4B500C8507E /* Frameworks */, 198 | 28C7028917D4E4B500C8507E /* Resources */, 199 | 0235C08F38DE4BB99CB6A272 /* Copy Pods Resources */, 200 | ); 201 | buildRules = ( 202 | ); 203 | dependencies = ( 204 | ); 205 | name = XLRemoteImageView; 206 | productName = XLRemoteImageView; 207 | productReference = 28C7028B17D4E4B500C8507E /* XLRemoteImageView.app */; 208 | productType = "com.apple.product-type.application"; 209 | }; 210 | 28C702B017D4E4B500C8507E /* XLRemoteImageViewTests */ = { 211 | isa = PBXNativeTarget; 212 | buildConfigurationList = 28C702C617D4E4B500C8507E /* Build configuration list for PBXNativeTarget "XLRemoteImageViewTests" */; 213 | buildPhases = ( 214 | 28C702AC17D4E4B500C8507E /* Sources */, 215 | 28C702AD17D4E4B500C8507E /* Frameworks */, 216 | 28C702AE17D4E4B500C8507E /* Resources */, 217 | 28C702AF17D4E4B500C8507E /* ShellScript */, 218 | ); 219 | buildRules = ( 220 | ); 221 | dependencies = ( 222 | 28C702B717D4E4B500C8507E /* PBXTargetDependency */, 223 | ); 224 | name = XLRemoteImageViewTests; 225 | productName = XLRemoteImageViewTests; 226 | productReference = 28C702B117D4E4B500C8507E /* XLRemoteImageViewTests.xctest */; 227 | productType = "com.apple.product-type.bundle.unit-test"; 228 | }; 229 | /* End PBXNativeTarget section */ 230 | 231 | /* Begin PBXProject section */ 232 | 28C7028317D4E4B500C8507E /* Project object */ = { 233 | isa = PBXProject; 234 | attributes = { 235 | LastTestingUpgradeCheck = 0510; 236 | LastUpgradeCheck = 0460; 237 | ORGANIZATIONNAME = Xmartlabs; 238 | }; 239 | buildConfigurationList = 28C7028617D4E4B500C8507E /* Build configuration list for PBXProject "XLRemoteImageView" */; 240 | compatibilityVersion = "Xcode 3.2"; 241 | developmentRegion = English; 242 | hasScannedForEncodings = 0; 243 | knownRegions = ( 244 | en, 245 | ); 246 | mainGroup = 28C7028217D4E4B500C8507E; 247 | productRefGroup = 28C7028C17D4E4B500C8507E /* Products */; 248 | projectDirPath = ""; 249 | projectRoot = ""; 250 | targets = ( 251 | 28C7028A17D4E4B500C8507E /* XLRemoteImageView */, 252 | 28C702B017D4E4B500C8507E /* XLRemoteImageViewTests */, 253 | ); 254 | }; 255 | /* End PBXProject section */ 256 | 257 | /* Begin PBXResourcesBuildPhase section */ 258 | 28C7028917D4E4B500C8507E /* Resources */ = { 259 | isa = PBXResourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 28C7029917D4E4B500C8507E /* InfoPlist.strings in Resources */, 263 | 285DEF9319883A2A00109FF5 /* Images.xcassets in Resources */, 264 | 28C702A817D4E4B500C8507E /* MainStoryboard.storyboard in Resources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | 28C702AE17D4E4B500C8507E /* Resources */ = { 269 | isa = PBXResourcesBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | 28C702BD17D4E4B500C8507E /* InfoPlist.strings in Resources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | /* End PBXResourcesBuildPhase section */ 277 | 278 | /* Begin PBXShellScriptBuildPhase section */ 279 | 0235C08F38DE4BB99CB6A272 /* Copy Pods Resources */ = { 280 | isa = PBXShellScriptBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | ); 284 | inputPaths = ( 285 | ); 286 | name = "Copy Pods Resources"; 287 | outputPaths = ( 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | shellPath = /bin/sh; 291 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 292 | showEnvVarsInLog = 0; 293 | }; 294 | 28C702AF17D4E4B500C8507E /* ShellScript */ = { 295 | isa = PBXShellScriptBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | ); 299 | inputPaths = ( 300 | ); 301 | outputPaths = ( 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | shellPath = /bin/sh; 305 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 306 | }; 307 | 6644797C8E04464C80EF8DB9 /* Check Pods Manifest.lock */ = { 308 | isa = PBXShellScriptBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | ); 312 | inputPaths = ( 313 | ); 314 | name = "Check Pods Manifest.lock"; 315 | outputPaths = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | shellPath = /bin/sh; 319 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 320 | showEnvVarsInLog = 0; 321 | }; 322 | /* End PBXShellScriptBuildPhase section */ 323 | 324 | /* Begin PBXSourcesBuildPhase section */ 325 | 28C7028717D4E4B500C8507E /* Sources */ = { 326 | isa = PBXSourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | 28C7029B17D4E4B500C8507E /* main.m in Sources */, 330 | 28C7029F17D4E4B500C8507E /* AppDelegate.m in Sources */, 331 | 28C702AB17D4E4B500C8507E /* ViewController.m in Sources */, 332 | 28C702CE17D5330D00C8507E /* XLCircleProgressIndicator.m in Sources */, 333 | 28C702D817D6465A00C8507E /* UIImageView+XLNetworking.m in Sources */, 334 | 28C702DB17D7728100C8507E /* UIImageView+XLProgressIndicator.m in Sources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | 28C702AC17D4E4B500C8507E /* Sources */ = { 339 | isa = PBXSourcesBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | 28C702C017D4E4B500C8507E /* XLRemoteImageViewTests.m in Sources */, 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | }; 346 | /* End PBXSourcesBuildPhase section */ 347 | 348 | /* Begin PBXTargetDependency section */ 349 | 28C702B717D4E4B500C8507E /* PBXTargetDependency */ = { 350 | isa = PBXTargetDependency; 351 | target = 28C7028A17D4E4B500C8507E /* XLRemoteImageView */; 352 | targetProxy = 28C702B617D4E4B500C8507E /* PBXContainerItemProxy */; 353 | }; 354 | /* End PBXTargetDependency section */ 355 | 356 | /* Begin PBXVariantGroup section */ 357 | 28C7029717D4E4B500C8507E /* InfoPlist.strings */ = { 358 | isa = PBXVariantGroup; 359 | children = ( 360 | 28C7029817D4E4B500C8507E /* en */, 361 | ); 362 | name = InfoPlist.strings; 363 | sourceTree = ""; 364 | }; 365 | 28C702A617D4E4B500C8507E /* MainStoryboard.storyboard */ = { 366 | isa = PBXVariantGroup; 367 | children = ( 368 | 28C702A717D4E4B500C8507E /* en */, 369 | ); 370 | name = MainStoryboard.storyboard; 371 | sourceTree = ""; 372 | }; 373 | 28C702BB17D4E4B500C8507E /* InfoPlist.strings */ = { 374 | isa = PBXVariantGroup; 375 | children = ( 376 | 28C702BC17D4E4B500C8507E /* en */, 377 | ); 378 | name = InfoPlist.strings; 379 | sourceTree = ""; 380 | }; 381 | /* End PBXVariantGroup section */ 382 | 383 | /* Begin XCBuildConfiguration section */ 384 | 28C702C117D4E4B500C8507E /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | ALWAYS_SEARCH_USER_PATHS = NO; 388 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 389 | CLANG_CXX_LIBRARY = "libc++"; 390 | CLANG_ENABLE_OBJC_ARC = YES; 391 | CLANG_WARN_CONSTANT_CONVERSION = YES; 392 | CLANG_WARN_EMPTY_BODY = YES; 393 | CLANG_WARN_ENUM_CONVERSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 396 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 397 | COPY_PHASE_STRIP = NO; 398 | GCC_C_LANGUAGE_STANDARD = gnu99; 399 | GCC_DYNAMIC_NO_PIC = NO; 400 | GCC_OPTIMIZATION_LEVEL = 0; 401 | GCC_PREPROCESSOR_DEFINITIONS = ( 402 | "DEBUG=1", 403 | "$(inherited)", 404 | ); 405 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 406 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 407 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 408 | GCC_WARN_UNUSED_VARIABLE = YES; 409 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 410 | ONLY_ACTIVE_ARCH = YES; 411 | SDKROOT = iphoneos; 412 | }; 413 | name = Debug; 414 | }; 415 | 28C702C217D4E4B500C8507E /* Release */ = { 416 | isa = XCBuildConfiguration; 417 | buildSettings = { 418 | ALWAYS_SEARCH_USER_PATHS = NO; 419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 420 | CLANG_CXX_LIBRARY = "libc++"; 421 | CLANG_ENABLE_OBJC_ARC = YES; 422 | CLANG_WARN_CONSTANT_CONVERSION = YES; 423 | CLANG_WARN_EMPTY_BODY = YES; 424 | CLANG_WARN_ENUM_CONVERSION = YES; 425 | CLANG_WARN_INT_CONVERSION = YES; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 428 | COPY_PHASE_STRIP = YES; 429 | GCC_C_LANGUAGE_STANDARD = gnu99; 430 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 431 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 432 | GCC_WARN_UNUSED_VARIABLE = YES; 433 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 434 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 435 | SDKROOT = iphoneos; 436 | VALIDATE_PRODUCT = YES; 437 | }; 438 | name = Release; 439 | }; 440 | 28C702C417D4E4B500C8507E /* Debug */ = { 441 | isa = XCBuildConfiguration; 442 | baseConfigurationReference = 6C98144AE67C5125D689423F /* Pods.debug.xcconfig */; 443 | buildSettings = { 444 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 445 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 446 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 447 | GCC_PREFIX_HEADER = "XLRemoteImageView/XLRemoteImageView-Prefix.pch"; 448 | INFOPLIST_FILE = "XLRemoteImageView/XLRemoteImageView-Info.plist"; 449 | PRODUCT_NAME = "$(TARGET_NAME)"; 450 | WRAPPER_EXTENSION = app; 451 | }; 452 | name = Debug; 453 | }; 454 | 28C702C517D4E4B500C8507E /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | baseConfigurationReference = C862175F70C1789B1B896E54 /* Pods.release.xcconfig */; 457 | buildSettings = { 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 460 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 461 | GCC_PREFIX_HEADER = "XLRemoteImageView/XLRemoteImageView-Prefix.pch"; 462 | INFOPLIST_FILE = "XLRemoteImageView/XLRemoteImageView-Info.plist"; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | WRAPPER_EXTENSION = app; 465 | }; 466 | name = Release; 467 | }; 468 | 28C702C717D4E4B500C8507E /* Debug */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/XLRemoteImageView.app/XLRemoteImageView"; 472 | FRAMEWORK_SEARCH_PATHS = ( 473 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 474 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 475 | "$(inherited)", 476 | ); 477 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 478 | GCC_PREFIX_HEADER = "XLRemoteImageView/XLRemoteImageView-Prefix.pch"; 479 | INFOPLIST_FILE = "XLRemoteImageViewTests/XLRemoteImageViewTests-Info.plist"; 480 | PRODUCT_NAME = "$(TARGET_NAME)"; 481 | TEST_HOST = "$(BUNDLE_LOADER)"; 482 | }; 483 | name = Debug; 484 | }; 485 | 28C702C817D4E4B500C8507E /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/XLRemoteImageView.app/XLRemoteImageView"; 489 | FRAMEWORK_SEARCH_PATHS = ( 490 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 491 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 492 | "$(inherited)", 493 | ); 494 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 495 | GCC_PREFIX_HEADER = "XLRemoteImageView/XLRemoteImageView-Prefix.pch"; 496 | INFOPLIST_FILE = "XLRemoteImageViewTests/XLRemoteImageViewTests-Info.plist"; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | TEST_HOST = "$(BUNDLE_LOADER)"; 499 | }; 500 | name = Release; 501 | }; 502 | /* End XCBuildConfiguration section */ 503 | 504 | /* Begin XCConfigurationList section */ 505 | 28C7028617D4E4B500C8507E /* Build configuration list for PBXProject "XLRemoteImageView" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 28C702C117D4E4B500C8507E /* Debug */, 509 | 28C702C217D4E4B500C8507E /* Release */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | defaultConfigurationName = Release; 513 | }; 514 | 28C702C317D4E4B500C8507E /* Build configuration list for PBXNativeTarget "XLRemoteImageView" */ = { 515 | isa = XCConfigurationList; 516 | buildConfigurations = ( 517 | 28C702C417D4E4B500C8507E /* Debug */, 518 | 28C702C517D4E4B500C8507E /* Release */, 519 | ); 520 | defaultConfigurationIsVisible = 0; 521 | defaultConfigurationName = Release; 522 | }; 523 | 28C702C617D4E4B500C8507E /* Build configuration list for PBXNativeTarget "XLRemoteImageViewTests" */ = { 524 | isa = XCConfigurationList; 525 | buildConfigurations = ( 526 | 28C702C717D4E4B500C8507E /* Debug */, 527 | 28C702C817D4E4B500C8507E /* Release */, 528 | ); 529 | defaultConfigurationIsVisible = 0; 530 | defaultConfigurationName = Release; 531 | }; 532 | /* End XCConfigurationList section */ 533 | }; 534 | rootObject = 28C7028317D4E4B500C8507E /* Project object */; 535 | } 536 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // 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. 22 | // 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. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // 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. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 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 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "xl_appicon_58.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "40x40", 11 | "idiom" : "iphone", 12 | "filename" : "xl_appicon_80.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "60x60", 17 | "idiom" : "iphone", 18 | "filename" : "xl_appicon_120.png", 19 | "scale" : "2x" 20 | } 21 | ], 22 | "info" : { 23 | "version" : 1, 24 | "author" : "xcode" 25 | } 26 | } -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/xl_appicon_120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/XLRemoteImageView/db0a3e749f614342d2cbff2717c8fee0017c2e0b/XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/xl_appicon_120.png -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/xl_appicon_58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/XLRemoteImageView/db0a3e749f614342d2cbff2717c8fee0017c2e0b/XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/xl_appicon_58.png -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/xl_appicon_80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/XLRemoteImageView/db0a3e749f614342d2cbff2717c8fee0017c2e0b/XLRemoteImageView/XLRemoteImageView/Images.xcassets/AppIcon.appiconset/xl_appicon_80.png -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "extent" : "full-screen", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "filename" : "xl_splash@2x.png", 15 | "minimum-system-version" : "7.0", 16 | "orientation" : "portrait", 17 | "scale" : "2x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/Images.xcassets/LaunchImage.launchimage/xl_splash@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/XLRemoteImageView/db0a3e749f614342d2cbff2717c8fee0017c2e0b/XLRemoteImageView/XLRemoteImageView/Images.xcassets/LaunchImage.launchimage/xl_splash@2x.png -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIImageView+XLNetworking.h" 11 | #import "UIImageView+XLProgressIndicator.h" 12 | 13 | #import 14 | 15 | @interface ViewController () 16 | 17 | @property (nonatomic) UIImageView *imageView; 18 | @property int countRefresh; 19 | 20 | 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | @synthesize imageView = _imageView; 26 | @synthesize countRefresh = _countRefresh; 27 | 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | // Do any additional setup after loading the view, typically from a nib. 33 | 34 | } 35 | 36 | -(void)viewWillAppear:(BOOL)animated 37 | { 38 | [super viewWillAppear:animated]; 39 | [self.view setBackgroundColor: [UIColor whiteColor]]; 40 | [self.view addSubview:self.imageView]; 41 | [self refreshImage:nil]; 42 | } 43 | 44 | - (void)didReceiveMemoryWarning 45 | { 46 | [super didReceiveMemoryWarning]; 47 | // Dispose of any resources that can be recreated. 48 | } 49 | 50 | 51 | #pragma mark - properties 52 | 53 | -(UIImageView *)imageView{ 54 | if (_imageView) return _imageView; 55 | _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height, self.view.bounds.size.width, 320)]; 56 | [_imageView setBackgroundColor:[UIColor colorWithRed:0.84 green:0.85 blue:0.86 alpha:0.9f]]; 57 | _imageView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 58 | _imageView.contentMode = UIViewContentModeScaleAspectFit; 59 | _imageView.clipsToBounds = YES; 60 | return _imageView; 61 | } 62 | 63 | 64 | #pragma mark - example 65 | 66 | - (IBAction)refreshImage:(UIBarButtonItem *)sender { 67 | // use another url to prevent cache usage 68 | NSString * url = [NSString stringWithFormat:@"https://raw.githubusercontent.com/xmartlabs/XLRemoteImageView/master/screenshot.png?countRefresh=%i", self.countRefresh]; 69 | self.countRefresh += 1; 70 | 71 | [self.imageView setImageWithProgressIndicatorAndURL:[NSURL URLWithString:url]]; 72 | } 73 | 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XL/UIImageView+XLNetworking.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+XLNetworking.h 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/3/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XLCircleProgressIndicator.h" 11 | 12 | 13 | @interface UIImageView (XLNetworking) 14 | 15 | /** 16 | Creates and enqueues an image request operation, which asynchronously downloads the image with the specified URL request object. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 17 | 18 | If a success block is specified, it is the responsibility of the block to set the image of the image view before returning. If no success block is specified, the default behavior of setting the image with `self.image = image` is executed. 19 | 20 | @param urlRequest The URL request used for the image request. 21 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 22 | @param success A block to be executed when the image request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `image/png`). This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the request and response parameters will be `nil`. 23 | @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. 24 | @param downloadProgressBlock A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. 25 | */ 26 | - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 27 | placeholderImage:(UIImage *)placeholderImage 28 | success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success 29 | failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure 30 | downloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadProgressBlock; 31 | 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XL/UIImageView+XLNetworking.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+XLNetworking.m 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/3/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+XLNetworking.h" 10 | #import 11 | #import 12 | #import "XLCircleProgressIndicator.h" 13 | #import 14 | 15 | 16 | @interface AFImageCache : NSCache 17 | - (UIImage *)cachedImageForRequest:(NSURLRequest *)request; 18 | - (void)cacheImage:(UIImage *)image 19 | forRequest:(NSURLRequest *)request; 20 | @end 21 | 22 | @interface UIImageView (_XLNetworking) 23 | 24 | @property (readwrite, nonatomic, strong, setter = af_setImageRequestOperation:) AFHTTPRequestOperation *af_imageRequestOperation; 25 | 26 | @end 27 | 28 | @implementation UIImageView (_XLNetworking) 29 | 30 | @dynamic af_imageRequestOperation; 31 | 32 | @end 33 | 34 | 35 | 36 | @implementation UIImageView (XLNetworking) 37 | 38 | 39 | 40 | - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 41 | placeholderImage:(UIImage *)placeholderImage 42 | success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success 43 | failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure 44 | downloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadProgressBlock 45 | 46 | { 47 | [self cancelImageRequestOperation]; 48 | 49 | // get AFNetworking UIImageView cache 50 | AFImageCache * cache = (AFImageCache *)((id (*)(id, SEL))objc_msgSend)([self class], @selector(sharedImageCache)); 51 | // try to get the image from cache 52 | UIImage * cachedImage = [cache cachedImageForRequest:urlRequest]; 53 | if (cachedImage) { 54 | if (success) { 55 | success(nil, nil, cachedImage); 56 | } else { 57 | self.image = cachedImage; 58 | } 59 | 60 | self.af_imageRequestOperation = nil; 61 | } else { 62 | if (placeholderImage) { 63 | self.image = placeholderImage; 64 | } 65 | 66 | __weak __typeof(self) weakSelf = self; 67 | self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; 68 | self.af_imageRequestOperation.responseSerializer = self.imageResponseSerializer; 69 | [self.af_imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 70 | __strong __typeof(weakSelf) strongSelf = weakSelf; 71 | if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) { 72 | if (success) { 73 | success(urlRequest, operation.response, responseObject); 74 | } else if (responseObject) { 75 | strongSelf.image = responseObject; 76 | } 77 | 78 | if (operation == strongSelf.af_imageRequestOperation){ 79 | strongSelf.af_imageRequestOperation = nil; 80 | } 81 | } 82 | // cache the image recently fetched. 83 | [cache cacheImage:responseObject forRequest:urlRequest]; 84 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 85 | __strong __typeof(weakSelf)strongSelf = weakSelf; 86 | if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) { 87 | if (failure) { 88 | failure(urlRequest, operation.response, error); 89 | } 90 | 91 | if (operation == strongSelf.af_imageRequestOperation){ 92 | strongSelf.af_imageRequestOperation = nil; 93 | } 94 | } 95 | }]; 96 | 97 | if (downloadProgressBlock){ 98 | [self.af_imageRequestOperation setDownloadProgressBlock:downloadProgressBlock]; 99 | } 100 | // get the NSoperationQueue associated With UIImageView class 101 | #pragma clang diagnostic push 102 | #pragma clang diagnostic ignored "-Wundeclared-selector" 103 | NSOperationQueue * operationQueue = (NSOperationQueue *)((id (*)(id, SEL))objc_msgSend)([self class], @selector(af_sharedImageRequestOperationQueue)); 104 | #pragma clang diagnostic pop 105 | [operationQueue addOperation:self.af_imageRequestOperation]; 106 | } 107 | } 108 | 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XL/UIImageView+XLProgressIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+XLProgressIndicator.h 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/4/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XLCircleProgressIndicator.h" 11 | 12 | @interface UIImageView (XLProgressIndicator) 13 | 14 | @property (nonatomic, readonly) XLCircleProgressIndicator * progressIndicatorView; 15 | 16 | /** 17 | Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL, and sets it the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. A progress indicator will appear if the image has to be fetched from a server. 18 | 19 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 20 | 21 | @param url The URL used for the image request. 22 | */ 23 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url; 24 | 25 | /** 26 | Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL, and sets it the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. A progress indicator will appear if the image has to be fetched from a server. 27 | 28 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 29 | 30 | @param url The URL used for the image request. 31 | @param indicatorCenter The center point of indicator view. 32 | */ 33 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url indicatorCenter:(CGPoint)indicatorCenter; 34 | 35 | /** 36 | Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. A progress indicator will appear if the image has to be fetched from a server. 37 | 38 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 39 | 40 | @param url The URL used for the image request. 41 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 42 | */ 43 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 44 | placeholderImage:(UIImage *)placeholderImage; 45 | 46 | /** 47 | Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. A progress indicator will appear if the image has to be fetched from a server. 48 | 49 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 50 | 51 | @param url The URL used for the image request. 52 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 53 | @param imageDidAppearBlock A block to be executed when the image download finishes successfully, This block has no return value and takes one arguments: the UIImageView loaded. For example, you can use this parameter for show a play button after the download finishes. 54 | */ 55 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 56 | placeholderImage:(UIImage *)placeholderImage 57 | imageDidAppearBlock:(void(^)(UIImageView * imageView))imageDidAppearBlock; 58 | 59 | /** 60 | Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. A progress indicator will appear if the image has to be fetched from a server. 61 | 62 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 63 | 64 | @param url The URL used for the image request. 65 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 66 | @param imageDidAppearBlock A block to be executed when the image download finishes successfully, This block has no return value and takes one arguments: the UIImageView loaded. For example, you can use this parameter for show a play button after the download finishes. 67 | @param indicatorCenter The center point of indicator view. 68 | */ 69 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 70 | placeholderImage:(UIImage *)placeholderImage 71 | imageDidAppearBlock:(void (^)(UIImageView *))imageDidAppearBlock 72 | progressIndicatorCenterPoint:(CGPoint)indicatorCenter; 73 | 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XL/UIImageView+XLProgressIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+XLProgressIndicator.m 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/4/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+XLProgressIndicator.h" 10 | #import "UIImageView+XLNetworking.h" 11 | #import "XLCircleProgressIndicator.h" 12 | #import 13 | 14 | static char kXLImageProgressIndicatorKey; 15 | 16 | @interface UIImageView (_XLProgressIndicator) 17 | 18 | @property (readwrite, nonatomic, strong, setter = xl_setProgressIndicatorView:) XLCircleProgressIndicator *xl_progressIndicatorView; 19 | 20 | @end 21 | 22 | @implementation UIImageView (_XLProgressIndicator) 23 | 24 | @dynamic xl_progressIndicatorView; 25 | 26 | @end 27 | 28 | @implementation UIImageView (XLProgressIndicator) 29 | 30 | -(XLCircleProgressIndicator *)progressIndicatorView 31 | { 32 | return [self xl_progressIndicatorView]; 33 | } 34 | 35 | 36 | -(void)xl_setProgressIndicatorView:(XLCircleProgressIndicator *)xl_progressIndicatorView 37 | { 38 | objc_setAssociatedObject(self, &kXLImageProgressIndicatorKey, xl_progressIndicatorView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 39 | } 40 | 41 | -(XLCircleProgressIndicator *)xl_progressIndicatorView 42 | { 43 | XLCircleProgressIndicator * progressIndicator = (XLCircleProgressIndicator *)objc_getAssociatedObject(self, &kXLImageProgressIndicatorKey); 44 | if (progressIndicator) return progressIndicator; 45 | progressIndicator = [[XLCircleProgressIndicator alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))]; 46 | progressIndicator.center = CGPointMake(CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2); 47 | progressIndicator.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin; 48 | [self xl_setProgressIndicatorView:progressIndicator]; 49 | return progressIndicator; 50 | } 51 | 52 | 53 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 54 | { 55 | [self setImageWithProgressIndicatorAndURL:url placeholderImage:nil]; 56 | } 57 | 58 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url indicatorCenter:(CGPoint)indicatorCenter 59 | { 60 | [self setImageWithProgressIndicatorAndURL:url placeholderImage:Nil imageDidAppearBlock:nil progressIndicatorCenterPoint:indicatorCenter]; 61 | } 62 | 63 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 64 | placeholderImage:(UIImage *)placeholderImage 65 | { 66 | [self setImageWithProgressIndicatorAndURL:url placeholderImage:placeholderImage imageDidAppearBlock:nil progressIndicatorCenterPoint:self.center]; 67 | } 68 | 69 | - (void)setImageWithProgressIndicatorAndURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage 70 | imageDidAppearBlock:(void (^)(UIImageView *))imageDidAppearBlock 71 | { 72 | [self setImageWithProgressIndicatorAndURL:url 73 | placeholderImage:placeholderImage 74 | imageDidAppearBlock:imageDidAppearBlock 75 | progressIndicatorCenterPoint:CGPointMake(CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2)]; 76 | } 77 | 78 | -(void)setImageWithProgressIndicatorAndURL:(NSURL *)url 79 | placeholderImage:(UIImage *)placeholderImage 80 | imageDidAppearBlock:(void (^)(UIImageView *))imageDidAppearBlock 81 | progressIndicatorCenterPoint:(CGPoint)indicatorCenter 82 | { 83 | [self setImage:nil]; 84 | [self.xl_progressIndicatorView setProgressValue:0.0f]; 85 | if (![self.xl_progressIndicatorView superview]){ 86 | [self addSubview:self.xl_progressIndicatorView]; 87 | } 88 | //self.xl_progressIndicatorView.center = indicatorCenter; 89 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 90 | [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; 91 | __typeof__(self) __weak weakSelf = self; 92 | [self setImageWithURLRequest:request 93 | placeholderImage:placeholderImage 94 | success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 95 | [weakSelf.xl_progressIndicatorView removeFromSuperview]; 96 | weakSelf.image = image; 97 | if (imageDidAppearBlock){ 98 | imageDidAppearBlock(weakSelf); 99 | } 100 | } 101 | failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { 102 | [weakSelf.xl_progressIndicatorView setProgressValue:0.0f]; 103 | } 104 | downloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { 105 | float newValue = ((float)totalBytesRead / totalBytesExpectedToRead); 106 | [weakSelf.xl_progressIndicatorView setProgressValue:newValue]; 107 | }]; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XL/XLCircleProgressIndicator.h: -------------------------------------------------------------------------------- 1 | /** 2 | / Source based on https://github.com/swissmanu/MACircleProgressIndicator 3 | */ 4 | 5 | 6 | #import 7 | 8 | @interface XLCircleProgressIndicator : UIView 9 | 10 | /** 11 | Progress value. Pass a float number between 0.0 and 1.0 to update the progress indicator 12 | */ 13 | @property (nonatomic) float progressValue; 14 | 15 | /** 16 | The color used to show the progress. 17 | */ 18 | @property (nonatomic) UIColor * strokeProgressColor UI_APPEARANCE_SELECTOR; 19 | 20 | /** 21 | The color used to show the remaining porcentage to complete the load. 22 | */ 23 | @property (nonatomic) UIColor * strokeRemainingColor UI_APPEARANCE_SELECTOR; 24 | 25 | /** 26 | If you set this property the stroke width is calculated using the actual size of the progress indicator view instead of strokeWidth property. 27 | */ 28 | @property (nonatomic) CGFloat strokeWidthRatio UI_APPEARANCE_SELECTOR; 29 | 30 | /** 31 | Configure the stroke widht of the progress indicator circle explicitly. When configured, strokeWidthRatio is ignored. 32 | */ 33 | @property (nonatomic) CGFloat strokeWidth UI_APPEARANCE_SELECTOR; 34 | 35 | /** 36 | Configure size of CircleProgressIndicator by default 100 */ 37 | 38 | @property (nonatomic) CGFloat minimumSize UI_APPEARANCE_SELECTOR; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XL/XLCircleProgressIndicator.m: -------------------------------------------------------------------------------- 1 | /** 2 | / Source based on https://github.com/swissmanu/MACircleProgressIndicator 3 | */ 4 | 5 | #import "XLCircleProgressIndicator.h" 6 | 7 | #define kXLCircleProgressIndicatorDefaultStrokeProgressColor [UIColor redColor] 8 | #define kXLCircleProgressIndicatorDefaultStrokeRemainingColor [[UIColor redColor] colorWithAlphaComponent:0.1f] 9 | #define kXLCircleProgressIndicatorDefaultStrokeWidthRatio 0.1 10 | #define kXLCircleProgressIndicatorDefaultSize 80.f 11 | #define kXLCircleProgressIndicatorDefaultStrokeWidth -1.0 12 | 13 | @interface XLCircleProgressIndicator () 14 | @end 15 | 16 | @implementation XLCircleProgressIndicator 17 | 18 | @synthesize strokeWidth = _strokeWidth; 19 | @synthesize strokeProgressColor = _strokeProgressColor; 20 | @synthesize strokeRemainingColor = _strokeRemainingColor; 21 | @synthesize strokeWidthRatio = _strokeWidthRatio; 22 | @synthesize progressValue = _progressValue; 23 | @synthesize minimumSize = _minimumSize; 24 | 25 | 26 | -(id)initWithFrame:(CGRect)frame { 27 | self = [super initWithFrame:frame]; 28 | if (self) { 29 | [self setDefaultValues]; 30 | } 31 | return self; 32 | } 33 | 34 | -(void)setDefaultValues { 35 | self.backgroundColor = [UIColor clearColor]; 36 | _strokeProgressColor = kXLCircleProgressIndicatorDefaultStrokeProgressColor; 37 | _strokeRemainingColor = kXLCircleProgressIndicatorDefaultStrokeRemainingColor; 38 | _strokeWidthRatio = kXLCircleProgressIndicatorDefaultStrokeWidthRatio; 39 | _minimumSize = kXLCircleProgressIndicatorDefaultSize; 40 | _strokeWidth = kXLCircleProgressIndicatorDefaultStrokeWidth; 41 | } 42 | 43 | 44 | #pragma mark - Properties 45 | 46 | -(void)setProgressValue:(float)progressValue { 47 | if (progressValue < 0.0) progressValue = 0.0; 48 | if (progressValue > 1.0) progressValue = 1.0; 49 | _progressValue = progressValue; 50 | [self setNeedsDisplay]; 51 | } 52 | 53 | -(void)setStrokeWidth:(CGFloat)strokeWidth { 54 | _strokeWidthRatio = -1.0; 55 | _strokeWidth = strokeWidth; 56 | [self setNeedsDisplay]; 57 | } 58 | 59 | -(void)setStrokeWidthRatio:(CGFloat)strokeWidthRatio { 60 | _strokeWidth = -1.0; 61 | _strokeWidthRatio = strokeWidthRatio; 62 | [self setNeedsDisplay]; 63 | } 64 | 65 | -(void)setStrokeProgressColor:(UIColor *)strokeProgressColor{ 66 | _strokeProgressColor = strokeProgressColor; 67 | [self setNeedsDisplay]; 68 | } 69 | 70 | -(void)setStrokeRemainingColor:(UIColor *)strokeRemainingColor{ 71 | _strokeRemainingColor = strokeRemainingColor; 72 | [self setNeedsDisplay]; 73 | } 74 | 75 | - (void)setMinimumSize:(CGFloat)minimumSize 76 | { 77 | _minimumSize = minimumSize; 78 | [self setNeedsDisplay]; 79 | } 80 | 81 | #pragma mark - draw progress indicator view 82 | 83 | -(void)drawRect:(CGRect)rect { 84 | CGContextRef context = UIGraphicsGetCurrentContext(); 85 | CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); 86 | float minSize = MIN(self.minimumSize, CGRectGetHeight(self.bounds)); 87 | float lineWidth = _strokeWidth; 88 | if (lineWidth == -1.0) lineWidth = minSize * _strokeWidthRatio; 89 | float radius = (minSize - lineWidth) / 2.0; 90 | CGContextSaveGState(context); 91 | CGContextTranslateCTM(context, center.x, center.y); 92 | CGContextRotateCTM(context, -M_PI * 0.5); 93 | CGContextSetLineWidth(context, lineWidth); 94 | CGContextSetLineCap(context, kCGLineCapRound); 95 | CGContextBeginPath(context); 96 | CGContextAddArc(context, 0, 0, radius, 0, 2 * M_PI, 0); 97 | CGContextSetStrokeColorWithColor(context, _strokeRemainingColor.CGColor); 98 | CGContextStrokePath(context); 99 | CGContextBeginPath(context); 100 | CGContextAddArc(context, 0, 0, radius, 0, M_PI * (_progressValue * 2), 0); 101 | CGContextSetStrokeColorWithColor(context, _strokeProgressColor .CGColor); 102 | CGContextStrokePath(context); 103 | CGContextRestoreGState(context); 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XLRemoteImageView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundleIcons~ipad 14 | 15 | CFBundleIdentifier 16 | Xmartlabs.${PRODUCT_NAME:rfc1034identifier} 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 2.0 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 2.0 29 | LSRequiresIPhoneOS 30 | 31 | UIMainStoryboardFile 32 | MainStoryboard 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/XLRemoteImageView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'XLRemoteImageView' target in the 'XLRemoteImageView' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/en.lproj/MainStoryboard.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 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // XLRemoteImageView 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageViewTests/XLRemoteImageViewTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | Xmartlabs.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageViewTests/XLRemoteImageViewTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // XLRemoteImageViewTests.h 3 | // XLRemoteImageViewTests 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLRemoteImageViewTests : XCTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageViewTests/XLRemoteImageViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // XLRemoteImageViewTests.m 3 | // XLRemoteImageViewTests 4 | // 5 | // Created by Martin Barreto on 9/2/13. 6 | // Copyright (c) 2013 Xmartlabs. All rights reserved. 7 | // 8 | 9 | #import "XLRemoteImageViewTests.h" 10 | 11 | @implementation XLRemoteImageViewTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | XCTFail(@"Unit tests are not implemented yet in XLRemoteImageViewTests"); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /XLRemoteImageView/XLRemoteImageViewTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xmartlabs/XLRemoteImageView/db0a3e749f614342d2cbff2717c8fee0017c2e0b/screenshot.png --------------------------------------------------------------------------------