In the iOS 7 and Mac OS 10.9 SDKs, Apple introduced new base64 methods on NSData that make it unnecessary to use a 3rd party base 64 decoding library. What's more, they exposed access to private base64 methods that are retrospectively available back as far as IOS 4 and Mac OS 6.
Although use of this library is no longer required, you may still find it useful, as it abstracts the complexity of supporting the deprecated Base64 methods for older OS versions, and also provides some additional utility functions, such as arbitrary wrap widths and NSString encoding.
Purpose
--------------
Base64 is a set of categories that provide methods to encode and decode data as a base-64-encoded string.
Supported OS & SDK Versions
-----------------------------
* Supported build target - iOS 7.0 / Mac OS 10.9 (Xcode 5.0, Apple LLVM compiler 5.0)
* Earliest supported deployment target - iOS 5.0 / Mac OS 10.7
* Earliest compatible deployment target - iOS 4.3 / Mac OS 10.6
NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this iOS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly.
ARC Compatibility
------------------
As of version 1.1, Base64 requires ARC. If you wish to use Base64 in a non-ARC project, just add the -fobjc-arc compiler flag to the Base64.m file. To do this, go to the Build Phases tab in your target settings, open the Compile Sources group, double-click Base64.m in the list and type -fobjc-arc into the popover.
If you wish to convert your whole project to ARC, comment out the #error line in Base64.m, then run the Edit > Refactor > Convert to Objective-C ARC... tool in Xcode and make sure all files that you wish to use ARC for (including Base64.m) are checked.
Thread Safety
--------------
All the Base64 methods should be safe to call from multiple threads concurrently.
Installation
--------------
To use the Base64 category in an app, just drag the category files (demo files and assets are not needed) into your project and import the header file into any class where you wish to make use of the Base64 functionality.
Takes a base-64-encoded string and returns an autoreleased NSData object containing the decoded data. Any non-base-64 characters in the string are ignored, so it is safe to pass a string containing line breaks or other delimiters.
Encodes the data as a base-64-encoded string and returns it. The wrapWidth argument allows you to specify the number of characters at which the output should wrap onto a new line. The value of wrapWidth must be a multiple of four. Values that are not a multiple of four will be truncated to the nearest multiple. A value of zero indicates that the data should not wrap.
- (NSString *)base64EncodedString;
Encodes the data as a base-64-encoded string without any wrapping (line breaks).
NSString Extensions
----------------------
Base64 extends NSString with the following methods:
Takes a base-64-encoded string and returns an autoreleased NSString object containing the decoded data, interpreted using UTF8 encoding. The vast majority of use cases for Base64 encoding use Ascii or UTF8 strings, so this should be sufficient for most purposes. If you do need to decode string data in an encoding other than UTF8, convert your string to an NSData object first and then use the NSData dataWithBase64EncodedString: method instead.
Converts the string data to UTF8 data and then encodes the data as a base-64-encoded string and returns it. The wrapWidth argument allows you to specify the number of characters at which the output should wrap onto a new line. The value of wrapWidth must be a multiple of four. Values that are not a multiple of four will be truncated to the nearest multiple. A value of zero indicates that the data should not wrap.
- (NSString *)base64EncodedString;
Encodes the string as UTF8 data and then encodes that as a base-64-encoded string without any wrapping (line breaks).
- (NSString *)base64DecodedString;
Treats the string as a base-64-encoded string and returns an autoreleased NSString object containing the decoded data, interpreted using UTF8 encoding. Any non-base-64 characters in the string are ignored, so it is safe to use a string containing line breaks or other delimiters.
- (NSData *)base64DecodedData;
Treats the string as base-64-encoded data and returns an autoreleased NSData object containing the decoded data. Any non-base-64 characters in the string are ignored, so it is safe to use a string containing line breaks or other delimiters.
NSAssert(commonSuperview,@"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy.");
**Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're using Swift in your project, we recommend using [SnapKit](https://github.com/SnapKit/SnapKit) as it provides better type safety with a simpler API.**
Masonry is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonry has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable.
Masonry supports iOS and Mac OS X.
For examples take a look at the **Masonry iOS Examples** project in the Masonry workspace. You will need to run `pod install` after downloading.
## What's wrong with NSLayoutConstraints?
Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive.
Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side
Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views.
Another option is to use Visual Format Language (VFL), which is a bit less long winded.
However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as `NSLayoutConstraint constraintsWithVisualFormat:` returns an array.
## Prepare to meet your Maker!
Heres the same constraints created using MASConstraintMaker
By default, macros which support [autoboxing](https://en.wikipedia.org/wiki/Autoboxing#Autoboxing) are prefixed with `mas_`. Unprefixed versions are available by defining `MAS_SHORTHAND_GLOBALS` before importing Masonry.
#### 4. NSArray
An array of a mixture of any of the previous types
You can chain view attributes for increased readability:
```obj-c
// All edges but the top should equal those of the superview
make.left.right.and.bottom.equalTo(superview);
make.top.equalTo(otherView);
```
## Hold on for dear life
Sometimes you need modify existing constraints in order to animate or remove/replace constraints.
In Masonry there are a few different approaches to updating constraints.
#### 1. References
You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property.
You could also reference multiple constraints by storing them away in an array.
Alternatively if you are only updating the constant value of the constraint you can use the convience method `mas_updateConstraints` instead of `mas_makeConstraints`
```obj-c
// this is Apple's recommended place for adding/updating constraints
// this method can get called multiple times in response to setNeedsUpdateConstraints
// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints
//according to apple super should be called at end of method
[super updateConstraints];
}
```
### 3. mas_remakeConstraints
`mas_updateConstraints` is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where `mas_remakeConstraints` comes in.
`mas_remakeConstraints` is similar to `mas_updateConstraints`, but instead of updating constant values, it will remove all of its constraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove.
SDWebImage does very aggressive caching by default. It ignores all kind of caching control header returned by the HTTP server and cache the returned images with no time restriction. It implies your images URLs are static URLs pointing to images that never change. If the pointed image happen to change, some parts of the URL should change accordingly.
If you don't control the image server you're using, you may not be able to change the URL when its content is updated. This is the case for Facebook avatar URLs for instance. In such case, you may use the `SDWebImageRefreshCached` flag. This will slightly degrade the performance but will respect the HTTP caching control headers:
See this category: https://github.com/JJSaccolo/UIActivityIndicator-for-SDWebImage
Installation
------------
There are three ways to use SDWebImage in your project:
- using CocoaPods
- copying all the files into your project
- importing the project as a static library
### Installation with CocoaPods
[CocoaPods](http://cocoapods.org/) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the [Get Started](http://cocoapods.org/#get_started) section for more details.
#### Podfile
```
platform :ios, '6.1'
pod 'SDWebImage', '~>3.7'
```
If you are using Swift, be sure to add `use_frameworks!` and set your target to iOS 8+:
```
platform :ios, '8.0'
use_frameworks!
```
#### Subspecs
There are 3 subspecs available now: `Core`, `MapKit` and `WebP` (this means you can install only some of the SDWebImage modules. By default, you get just `Core`, so if you need `WebP`, you need to specify it).
Podfile example:
```
pod 'SDWebImage/WebP'
```
### Installation with Carthage (iOS 8+)
[Carthage](https://github.com/Carthage/Carthage) is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and is less invasive than CocoaPods.
To install with carthage, follow the instruction on [Carthage](https://github.com/Carthage/Carthage)
#### Cartfile
```
github "rs/SDWebImage"
```
#### Usage
Swift
If you installed using CocoaPods:
```
import SDWebImage
```
If you installed manually:
```
import WebImage
```
Objective-C
```
@import WebImage;
```
### Installation by cloning the repository
In order to gain access to all the files from the repository, you should clone it.
Alternatively, if this causes compilation problems with frameworks that extend optional libraries, such as Parse, RestKit or opencv2, instead of the -ObjC flag use:
// The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data.
if(url==nil){
if(completedBlock!=nil){
completedBlock(nil,nil,nil,NO);
}
return;
}
dispatch_barrier_sync(self.barrierQueue,^{
BOOLfirst=NO;
if(!self.URLCallbacks[url]){
self.URLCallbacks[url]=[NSMutableArraynew];
first=YES;
}
// Handle single download of simultaneous download request for the same URL
* Initializes a `SDWebImageDownloaderOperation` object
*
* @see SDWebImageDownloaderOperation
*
* @param request the URL request
* @param options downloader options
* @param progressBlock the block executed when a new chunk of data arrives.
* @note the progress block is executed on a background queue
* @param completedBlock the block executed when the download is done.
* @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
* @param cancelBlock the block executed if the download (operation) is cancelled
self.completedBlock(nil,nil,[NSErrorerrorWithDomain:NSURLErrorDomaincode:0userInfo:@{NSLocalizedDescriptionKey:@"Connection can't be initialized"}],YES);
completionBlock(nil,nil,[NSErrorerrorWithDomain:SDWebImageErrorDomaincode:0userInfo:@{NSLocalizedDescriptionKey:@"Downloaded image has 0 pixels"}],YES);
}
else{
completionBlock(image,self.imageData,nil,YES);
}
}else{
completionBlock(nil,nil,[NSErrorerrorWithDomain:SDWebImageErrorDomaincode:0userInfo:@{NSLocalizedDescriptionKey:@"Image data is nil"}],YES);
typedefvoid(^SDWebImageCompletedBlock)(UIImage*image,NSError*error,SDImageCacheTypecacheType)__deprecated_msg("Block type deprecated. Use `SDWebImageCompletionBlock`");
typedefvoid(^SDWebImageCompletedWithFinishedBlock)(UIImage*image,NSError*error,SDImageCacheTypecacheType,BOOLfinished)__deprecated_msg("Block type deprecated. Use `SDWebImageCompletionWithFinishedBlock`");
@interfaceSDWebImageManager(Deprecated)
/**
* Downloads the image at the given URL if not present in cache or return the cached version otherwise.
*
* @deprecated This method has been deprecated. Use `downloadImageWithURL:options:progress:completed:`
completed:(SDWebImageCompletedWithFinishedBlock)completedBlock__deprecated_msg("Method deprecated. Use `downloadImageWithURL:options:progress:completed:`");
// if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data
-(void)setImageWithURL:(NSURL*)urlforState:(UIControlState)state__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:`");
-(void)setImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholder__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:`");
-(void)setImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)options__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:options:`");
-(void)setImageWithURL:(NSURL*)urlforState:(UIControlState)statecompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:completed:`");
-(void)setImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholdercompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:completed:`");
-(void)setImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)optionscompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:options:completed:`");
-(void)setBackgroundImageWithURL:(NSURL*)urlforState:(UIControlState)state__deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:`");
-(void)setBackgroundImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholder__deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:`");
-(void)setBackgroundImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)options__deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:options:`");
-(void)setBackgroundImageWithURL:(NSURL*)urlforState:(UIControlState)statecompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:completed:`");
-(void)setBackgroundImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholdercompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:completed:`");
-(void)setBackgroundImageWithURL:(NSURL*)urlforState:(UIControlState)stateplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)optionscompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:options:completed:`");
-(void)setHighlightedImageWithURL:(NSURL*)url__deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:`");
-(void)setHighlightedImageWithURL:(NSURL*)urloptions:(SDWebImageOptions)options__deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:`");
-(void)setHighlightedImageWithURL:(NSURL*)urlcompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:completed:`");
-(void)setHighlightedImageWithURL:(NSURL*)urloptions:(SDWebImageOptions)optionscompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:completed:`");
-(void)setHighlightedImageWithURL:(NSURL*)urloptions:(SDWebImageOptions)optionsprogress:(SDWebImageDownloaderProgressBlock)progressBlockcompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:progress:completed:`");
-(void)setImageWithURL:(NSURL*)url__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`");
-(void)setImageWithURL:(NSURL*)urlplaceholderImage:(UIImage*)placeholder__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`");
-(void)setImageWithURL:(NSURL*)urlplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)options__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options`");
-(void)setImageWithURL:(NSURL*)urlcompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`");
-(void)setImageWithURL:(NSURL*)urlplaceholderImage:(UIImage*)placeholdercompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`");
-(void)setImageWithURL:(NSURL*)urlplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)optionscompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`");
-(void)setImageWithURL:(NSURL*)urlplaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)optionsprogress:(SDWebImageDownloaderProgressBlock)progressBlockcompleted:(SDWebImageCompletedBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:progress:completed:`");
-(void)sd_setImageWithPreviousCachedImageWithURL:(NSURL*)urlandPlaceholderImage:(UIImage*)placeholderoptions:(SDWebImageOptions)optionsprogress:(SDWebImageDownloaderProgressBlock)progressBlockcompleted:(SDWebImageCompletionBlock)completedBlock__deprecated_msg("Method deprecated. Use `sd_setImageWithPreviousCachedImageWithURL:placeholderImage:options:progress:completed:`");