classproxy target class哪些类可以访问和更改变量的name的

发表了一篇文章
Features(特性)
First-level memory cache using NSCache.
Second-level LRU disk cache using the file system.
Zero-config UIImageView category to use the cache, optimized for UITableView and UICollectionViewcell reuse.
Asynchronous and synchronous image retrieval.
Background image resizing and file reading.
Image decompression.
Custom image transformations before and after resizing.
Thread-safe.
Automatic cache eviction on memory warnings or disk capacity reached.
Preloading images from the disk cache into memory on startup.
NSCache 第一级别的缓存
第二级别的文件系统缓存
0配置的 UIImageView 类目来使用缓存,对 UITableView 以及 UICollectionViewCell 重用进行优化
异步以及同步的图片恢复技术
在后台进行图片尺寸的设置以及文件读写
图片解压缩
在重新设置图片尺寸之间可以自定义图片的变换形式
自动清除内存警告或者磁盘容量溢出
在内存启用的时候就已经从磁盘上预加载了图片
Add Haneke to your project(添加到你的工程当中)
folder to your project.
将 Haneke 文件夹添加到你的工程当中。
尽情享用吧!
UIImageView category(UIImageView 类目)
Haneke provides convenience methods for UIImageView with optimizations for UITableView and UICollectionView cell reuse. Images will be resized appropriately and cached in a shared cache.
Haneke 给 UIImageView 提供了便利的方法,用来给 UITableView 以及 UICollectionVIew 进行重用。图片会被适当的重新设置尺寸并缓存到单例缓存当中。
// Setting a remote image
[imageView hnk_setImageFromURL:url];
// Setting a local image
[imageView hnk_setImageFromFile:path];
// Setting an image manually. Requires you to provide a key.
[imageView hnk_setImage:image withKey:key];
The above lines take care of:
上面的代码需要注意:
If cached, retrieving an appropriately sized image (based on the bounds and contentMode of the UIImageView) from the memory or disk cache. Disk access is performed in background.
If not cached, loading the original image from web/disk/memory and producing an appropriately sized image, both in background. Remote images will be retrieved from the shared NSURLCache if available.
Setting the image and animating the change if appropriate.
Or doing nothing if the UIImageView was reused during any of the above steps.
Caching the resulting image.
If needed, evicting the least recently used images in the cache.
如果已经缓存了,就会从内存或者磁盘缓存文件中恢复出设置过尺寸的图片(基于 bounds 以及 UIIamgeView 的 contentMode)。磁盘操作都在后台进行。
如果还没有进行缓存,从web/磁盘/内存中加载原始的图片并创建出便利的图片尺寸,都是在后台进行的。web上的图片将会被恢复加载,在这个当你NSURLCache中,如果存在的话。
如果便利则会设置图片以及动态改变。
如果重用了,上面的都不是执行。
缓存重用的图片。
如果有需求,移除掉缓存中使用最少的图片。
Cache formats(缓存格式)
The cache behavior can be customized by defining cache formats. Each image view has a default format and you can also define your own formats. A format is uniquely identified by its name.
你是可以定制缓存的行为的。每张图片View都有一个默认的格式,你也可以自定义你自己的格式,每种格式都有它自己的唯一标示的名字。
UIImageView format(UIImageView 的格式)
Each image view has a default format created on demand. The default format is configured as follows:
每个 iamgeView 有一个默认的格式,这个默认的格式是这么被配置的:
Size matches the bounds of the image view.
Images will be scaled based on the contentMode of the the image view.
Images can be upscaled if they're smaller than the image view.
High compression quality.
No preloading.
Up to 10MB of disk cache.
Modifying this default format is discouraged. Instead, you can set your own custom format like this:
不要修改默认的图片格式。相对的,你可以设置你自己的图片格式:
HNKCacheFormat *format = [[HNKCacheFormat alloc] initWithName:@"thumbnail"];
format.size = CGSizeMake(320, 240);
format.scaleMode = HNKScaleModeAspectFill;
format.compressionQuality = 0.5;
format.diskCapacity = 1 * 1024 * 1024; // 1MB
format.preloadPolicy = HNKPreloadPolicyLastSession;
imageView.hnk_cacheFormat = format;
The image view category will take care of registering the format in the shared cache.
iamge view 的类目会注册这个格式到 cache 的单例中。
Disk cache(磁盘缓存)
A format can have disk cache by setting the diskCapacity property with a value greater than 0. Haneke will take care of evicting the least recently used images of the format from the disk cache when the disk capacity is surpassed.
磁盘缓存 diskCapacity 是可以设置的。Haneke 会自动移除掉使用得最少的 image,当往这个已经满了的磁盘缓存中写入新的图片。
Preload policy(预加载策略)
When registering a format, Haneke will load none, some or all images cached on disk into the memory cache based on the preload policy of the format. The available preload policies are:
当注册了一种格式后,Haneke会将磁盘上缓存的图片加载到内存的缓存当中,基于这个预加载的策略。提供给你的预加载策略如下:
HNKPreloadPolicyNone: No images will be preloaded.
HNKPreloadPolicyLastSession: Only images from the last session will be preloaded.
HNKPreloadPolicyAll: All images will be preloaded.
If an image of the corresponding format is requested before preloading finishes, Haneke will cancel preloading to give priority to the request. To make the most of this feature it's recommended to register formats on startup.
如果此时有一张图片开始请求了,在预加载完成之前发生的,Haneke 会取消预加载而响应这个请求。为了最大限度的使用这个特性,建议你在程序开始运行的时候就开始注册。
Preloading only applies to formats that have disk cache.
预加载仅支持能够进行磁盘缓存的格式。
Pre and post resize blocks
Formats can have blocks that will be called before and after the original image is resized: preResizeBlock and postResizeBlock respectively. Both receive a key and the image up to the corresponding stage. For example:
format.postResizeBlock = ^UIImage* (NSString *key, UIImage *image) {
UIImage *roundedImage = [image imageByRoundingCorners];
return roundedImage;
These blocks will be called only if the requested image is not found in the cache. They will be executed in background when using the image view category or the asynchronous methods of the cache directly.
Logging(debug)
Haneke provides useful logging that is turned off by default. You can see it in action in the demo.
Haneke 提供好用的打印信息,默认是关闭了的。你可以在demo中看到效果。
To turn logging on you must set the preprocessor macro HANEKE_DEBUG to 1. The recommended way to do this is by adding HANEKE_DEBUG=1 to the Preprocessor Macros build setting. If you included Haneke directly, add it to your project target. If you are using CocoaPods, add it to the Pods-Haneke target of the Pods project.
你把预处理宏 HANEKE_DEBUG 设置成1就可以看到打印信息了。
Requirements(环境要求)
Haneke requires iOS 7.0 or above and ARC.
iOS 6 compatibility can be achieved with very few . You can use 's
that adds it by replacing NSURLSession with .
Haneke 需要 iOS 7.0 以及 ARC。
虽然兼容 iOS 6,但基本上没有啥效果,你可以使用
来替换 AFNetworking 中的 NSURLSession 。
Roadmap(任重而道远)
Haneke is in initial development and its public API should not be considered stable.
Haneke 是一个刚刚开始的项目,所以,它公开的 API 可能会经常变动。
/hpique/Haneke
A lightweight zero-config image cache for iOS.
轻量级0配置图片缓存…
发表了一篇文章
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.
两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区,使sv减1。而第二个进程将被阻止进入临界区,因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。
Node.js允许注册监听器来处理操作系统发送给一个进程的信号。可以被发送的node.js进程的事件有下面几个:
SIGUSR1 :启动调试器时发出。
SIGPIPE:进程试图写入在另一端没有进程连接的管道时发出
SIGHUP:Window上控制台关闭窗口时发出。在发出此事件约10秒会终止Node.js
SIGTERM:在发出一个终止进程的请求时发出.Windwo不支持。
SIGINT:当中断被发送到这个进程上,如Ctrl+C组合键被按下时发出
SIGBEAK:Windwo下Ctrl+Break组合键被按下时发出。
SIGWINCE:在控制台已经被调整大小时发出。Window下,只有当你写入控制台,移动光标或者在原始模式下使用可读的TTY时发出
SIGKILL:进程杀掉时发出
SIGSTOP:进程终止时发出。
监听的其实不止上面的信号在process的on定义中也能看出还有exit、uncaughtException等(可以转到定义)。
四、控制进程执行
abort():使当前的Node.js应用程序发出abort事件,退出,并产生一个内存核心转储文件
exit([code]):使当前Node.js应用退出,并返回指定的code
kill(pid,[signall]):操作系统会向指定的pid的进程发送一个kill信号,默认是SIGTERM
nexttick(callback):调度node.js程序的队列中的callback函数
五、从Process模块获取信息
var util = require('util');
//返回进程的当前工作目录
console.log('Current directory: ' + process.cwd());
//该进程的环境中指定的键/值对
console.log('Environment Settings: ' + JSON.stringify(process.env));
//用于启动Node.js应用程序的命令参数
console.log('Node Args: ' + process.argv);
//Node。js从中启动的绝对路径
console.log('Execution Path: ' + process.execPath);
//用于启动应用程序的特定节点的命令行选项
console.log('Execution Args: ' + JSON.stringify(process.execArgv));
//Node.js版本号
console.log('Node Version: ' + process.version);
//提供一个对象,包含Node.js应用程序所需的模块和版本
console.log('Module Versions: ' +
JSON.stringify(process.versions));
//用于编译当前节点可执行程序的配置选项
console.log('Node Config: ' +
JSON.stringify(process.config));
//当前进程ID
console.log('Process ID: ' + process.pid);
//当前进程标题
console.log('Process Title: ' + process.title);
//操作系统
console.log('Process Platform: ' + process.platform);
//进程正在运行的处理器体系结构
console.log('Process Architecture: ' + process.arch);
//Node.js进程的当前内存使用情况可使用util.inspect()读取
console.log('Memory Usage: ' + util.inspect(process.memoryUsage()));
//返回一个高精确的时间
var start = process.hrtime();
setTimeout(function() {
var delta = process.hrtime(start);
console.log('High-Res timer took %d seconds and %d nanoseconds',
delta[0], + delta[1]);
console.log('Node has been running %d seconds', process.uptime());
"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe process_info.js
Current directory: c:\Users\Administrator\Desktop\nodejs-mongodb-angularjs-web-development-master\ch09
Environment Settings: {"#envTSLOGTSLOG11328":"","ALLUSERSPROFILE":"C:\\ProgramData","APPDATA":"C:\\Users\\Administrator\\AppData\\Roaming","asl.log":"Destination=file","CommonProgramFiles":"C:\\Program Files\\Common Files","CommonProgramFiles(x86)":"C:\\Program Files (x86)\\Common Files","CommonProgramW6432":"C:\\Program Files\\Common Files","COMPUTERNAME":"LENOVO-PC","ComSpec":"C:\\WINDOWS\\system32\\cmd.exe","configsetroot":"C:\\WINDOWS\\ConfigSetRoot","FPS_BROWSER_APP_PROFILE_STRING":"Internet Explorer","FPS_BROWSER_USER_PROFILE_STRING":"Default","FP_NO_HOST_CHECK":"NO","HOMEDRIVE":"C:","HOMEPATH":"\\Users\\Administrator","LOCALAPPDATA":"C:\\Users\\Administrator\\AppData\\Local","LOGONSERVER":"\\\\MicrosoftAccount","NUMBER_OF_PROCESSORS":"4","OS":"Windows_NT","Path":"C:\\PROGRAM FILES (X86)\\INTEL\\ICLS CLIENT\\;C:\\PROGRAM FILES\\INTEL\\ICLS CLIENT\\;C:\\WINDOWS\\SYSTEM32;C:\\WINDOWS;C:\\WINDOWS\\SYSTEM32\\WBEM;C:\\WINDOWS\\SYSTEM32\\WINDOWSPOWERSHELL\\V1.0\\;C:\\PROGRAM FILES\\INTEL\\INTEL(R) MANAGEMENT ENGINE COMPONENTS\\DAL;C:\\PROGRAM FILES\\INTEL\\INTEL(R) MANAGEMENT ENGINE COMPONENTS\\IPT;C:\\PROGRAM FILES (X86)\\INTEL\\INTEL(R) MANAGEMENT ENGINE COMPONENTS\\DAL;C:\\PROGRAM FILES (X86)\\INTEL\\INTEL(R) MANAGEMENT ENGINE COMPONENTS\\IPT;C:\\PROGRAM FILES (X86)\\ATI TECHNOLOGIES\\ATI.ACE\\CORE-STATIC;;C:\\WINDOWS\\SYSTEM32;C:\\WINDOWS;C:\\WINDOWS\\SYSTEM32\\WBEM;C:\\WINDOWS\\SYSTEM32\\WINDOWSPOWERSHELL\\V1.0\\;C:\\PROGRAM FILES (X86)\\AMD\\ATI.ACE\\CORE-STATIC;C:\\Program Files\\Lenovo\\Bluetooth Software\\;C:\\Program Files\\Lenovo\\Bluetooth Software\\syswow64;F:\\nodejs\\;C:\\WINDOWS\\system32\\config\\systemprofile\\.dnx\\C:\\Program Files\\Microsoft DNX\\Dnvm\\;C:\\Program Files (x86)\\Lenovo\\Lenovo Home\\DCMainWin.C:\\Users\\Administrator\\AppData\\Roaming\\npm","PATHEXT":".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC","PROCESSOR_ARCHITECTURE":"AMD64","PROCESSOR_IDENTIFIER":"Intel64 Family 6 Model 60 Stepping 3, GenuineIntel","PROCESSOR_LEVEL":"6","PROCESSOR_REVISION":"3c03","ProgramData":"C:\\ProgramData","ProgramFiles":"C:\\Program Files","ProgramFiles(x86)":"C:\\Program Files (x86)","ProgramW6432":"C:\\Program Files","PSModulePath":"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules\\","PUBLIC":"C:\\Users\\Public","SESSIONNAME":"Console","SystemDrive":"C:","SystemRoot":"C:\\WINDOWS","TEMP":"C:\\Users\\ADMINI~1\\AppData\\Local\\Temp","TMP":"C:\\Users\\ADMINI~1\\AppData\\Local\\Temp","USERDOMAIN":"LENOVO-PC","USERDOMAIN_ROAMINGPROFILE":"LENOVO-PC","USERNAME":"Administrator","USERPROFILE":"C:\\Users\\Administrator","VS140COMNTOOLS":"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\","windir":"C:\\WINDOWS"}
Node Args: F:\nodejs\node.exe,c:\Users\Administrator\Desktop\nodejs-mongodb-angularjs-web-development-master\ch09\process_info.js
Execution Path: F:\nodejs\node.exe
Execution Args: []
Node Version: v4.3.2
Module Versions: {"http_parser":"2.5.2","node":"4.3.2","v8":"4.5.103.35","uv":"1.8.0","zlib":"1.2.8","ares":"1.10.1-DEV","icu":"56.1","modules":"46","openssl":"1.0.2g"}
Node Config: {"target_defaults":{"cflags":[],"default_configuration":"Release","defines":[],"include_dirs":[],"libraries":[]},"variables":{"asan":0,"host_arch":"x64","icu_data_file":"icudt56l.dat","icu_data_in":"../../deps/icu/source/data/in\\icudt56l.dat","icu_endianness":"l","icu_gyp_path":"tools/icu/icu-generic.gyp","icu_locales":"en,root","icu_path":"deps\\icu","icu_small":true,"icu_ver_major":"56","node_byteorder":"little","node_install_npm":true,"node_prefix":"/usr/local","node_release_urlbase":"","node_shared_http_parser":false,"node_shared_libuv":false,"node_shared_openssl":false,"node_shared_zlib":false,"node_tag":"","node_use_dtrace":false,"node_use_etw":true,"node_use_lttng":false,"node_use_openssl":true,"node_use_perfctr":true,"openssl_fips":"","openssl_no_asm":0,"python":"C:\\Python27\\python.exe","target_arch":"x64","v8_enable_gdbjit":0,"v8_enable_i18n_support":1,"v8_no_strict_aliasing":1,"v8_optimized_debug":0,"v8_random_seed":0,"v8_use_snapshot":true,"want_separate_host_toolset":0}}
Process ID: 8124
Process Title: C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe
Process Platform: win32
Process Architecture: x64
Memory Usage: { rss: , heapTotal: 7409232, heapUsed: 3756584 }
High-Res timer took 1 seconds and 107153 nanoseconds
Node has been running 1.128 seconds
Process finished with exit code 0
在前面Node.js事件运行机制也有提到,Node.js应用在单个线程运行,但是现在大部分服务器都是多处理器,为了方便使用多个进程,Node.js提供了3个模块。Process模块提供了访问正在运行…
发表了一篇文章
An image format's style effectively determines the bit depth of the images stored in an image table. The following styles are currently available:
不同的图片格式决定了存储进图片 table 的位深。下面的这些格式是被支持的:
32-bit color plus an alpha component (default)
32-bit color, no alpha component
16-bit color, no alpha component
8-bit grayscale, no alpha component
If the source images lack transparency (e.g., JPEG images), then better Core Animation performance can be achieved by using 32-bit color with no alpha component. If the source images have little color detail, or if the image format's image size is relatively small, it may be sufficient to use 16-bit color with little or no perceptible loss of quality. This results in smaller image table files stored on disk.
如果图片资源没有透明像素,Core Animation 使用 32-bit 颜色的无 alpha 通道的组件会表现出好的效果。如果这个图片只有很少的颜色细节,或者这种格式的图片的尺寸很小,使用 16-bit 颜色会表现不错。
Configuring the Image Cache(配置图片的缓存)
Once one or more image formats have been defined, they need to be assigned to the image cache. Aside from assigning the image cache's delegate, there is nothing further that can be configured on the image cache itself.
一旦一个或多种图片格式被定义了,此时就需要把它们赋给图片缓存了。除了设置一个代理,没有更多的东西可以设置了。
FICImageCache *sharedImageCache = [FICImageCache sharedImageCache];
sharedImageCache.delegate = self;
sharedImageCache.formats = imageFormats;
Creating Entities(创建实体对象)
Entities are objects that conform to the
protocol. Entities uniquely identify entries in an image table, and they are also responsible for drawing the images they wish to store in the image cache. Applications that already have model objects defined (perhaps managed by Core Data) are usually appropriate entity candidates.
实体对象需要符合 FICentity 协议。实体对象的唯一标示了一个图片table。它们也负责存储绘制过的图片到图片缓存中。
@interface XXUser : NSObject &FICEntity&
@property (nonatomic, assign, getter = isActive) BOOL active;
@property (nonatomic, copy) NSString *userID;
@property (nonatomic, copy) NSURL *userPhotoURL;
Here is an example implementation of the
- (NSString *)UUID {
CFUUIDBytes UUIDBytes = FICUUIDBytesFromMD5HashOfString(_userID);
NSString *UUID = FICStringWithUUIDBytes(UUIDBytes);
return UUID;
- (NSString *)sourceImageUUID {
CFUUIDBytes sourceImageUUIDBytes = FICUUIDBytesFromMD5HashOfString([_userPhotoURL absoluteString]);
NSString *sourceImageUUID = FICStringWithUUIDBytes(sourceImageUUIDBytes);
return sourceImageUUID;
- (NSURL *)sourceImageURLWithFormatName:(NSString *)formatName {
return _sourceImageURL;
- (FICEntityImageDrawingBlock)drawingBlockForImage:(UIImage *)image withFormatName:(NSString *)formatName {
FICEntityImageDrawingBlock drawingBlock = ^(CGContextRef context, CGSize contextSize) {
CGRect contextBounds = CGRectZero;
contextBounds.size = contextSize;
CGContextClearRect(context, contextBounds);
// Clip medium thumbnails so they have rounded corners
if ([formatName isEqualToString:XXImageFormatNameUserThumbnailMedium]) {
UIBezierPath clippingPath = [self _clippingPath];
[clippingPath addClip];
UIGraphicsPushContext(context);
[image drawInRect:contextBounds];
UIGraphicsPopContext();
return drawingBlock;
Ideally, an entity's
should never change. This is why it corresponds nicely with a model object's server-generated ID in the case where an application is working with resources retrieved from an API.
An entity's
can change. For example, if a user updates their profile photo, the URL to that photo should change as well. The
remains the same and identifies the same user, but the changed profile photo URL will indicate that there is a new source image.
When the image cache is asked to provide an image for a particular entity and format name, the entity is responsible for providing a URL. The URL need not even point to an actual resource—e.g., the URL might be constructed of a custom URL-scheme—, but it must be a valid URL.
The image cache uses these URLs merely to keep track of which image requests a multiple requests to the image cache for the same image are handled correctly without any wasted effort. The choice to use URLs as a basis for keying image cache requests actually complements many real-world application designs whereby URLs to image resources (rather than the images themselves) are included with server-provided model data.
Finally, once the source image is available, the entity is asked to provide a drawing block. The image table that will store the final image sets up a file-mapped bitmap context and invokes the entity's drawing block. This makes it convenient for each entity to decide how to process the source image for particular image formats.
Requesting Images from the Image Cache(从图片缓存中请求图片)
Fast Image Cache works under the on-demand, lazy-loading design pattern common to Cocoa.
Fast Image Cache 使用了懒加载设计模式:
XXUser *user = [self _currentUser];
NSString *formatName = XXImageFormatNameUserThumbnailSmall;
FICImageCacheCompletionBlock completionBlock = ^(id &FICEntity& entity, NSString *formatName, UIImage *image) {
_imageView.image = image;
[_imageView.layer addAnimation:[CATransition animation] forKey:kCATransition];
BOOL imageExists = [sharedImageCache retrieveImageForEntity:user withFormatName:formatName completionBlock:completionBlock];
if (imageExists == NO) {
_imageView.image = [self _userPlaceholderImage];
There are a few things to note here.
Note that it is an entity and an image format name that uniquely identifies the desired image in the image cache. As a format name uniquely identifies an image table, the entity alone uniquely identifies the desired image data in an image table.
The image cache never returns a
directly. The requested image is included in the completion block. The return value will indicate whether or not the image already exists in the image cache.
is a synchronous method. If the requested image already exists in the image cache, the completion block will be called immediately. There is an asynchronous counterpart to this method called .
If a requested image does not already exist in the image cache, then the image cache invokes the necessary actions to request the source image for its delegate. Afterwards, perhaps some time later, the completion block will be called.
Providing Source Images to the Image Cache(给图片缓存提供图片)
There are two ways to provide source images to the image cache.
On Demand: This is the preferred method. The image cache's delegate is responsible for supplying the image cache with source images.
- (void)imageCache:(FICImageCache *)imageCache wantsSourceImageForEntity:(id&FICEntity&)entity withFormatName:(NSString *)formatName completionBlock:(FICImageRequestCompletionBlock)completionBlock {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Fetch the desired source image by making a network request
NSURL *requestURL = [entity sourceImageURLWithFormatName:formatName];
UIImage *sourceImage = [self _sourceImageForURL:requestURL];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(sourceImage);
This is where the URL-based nature of how the image cache manages image requests is convenient. First, an image retrieval request to the image cache for an image that is already being handled by the image cache's delegate—e.g., waiting on a large image to be downloaded—is simply added to the first request's array of completion blocks. Second, if source images are downloaded from the Internet (as is often the case), the URL for such a network request is readily available.
Manually: It is possible to manually insert image data into the image cache.
// Just finished downloading new user photo
XXUser *user = [self _currentUser];
NSString *formatName = XXImageFormatNameUserThumbnailSmall;
FICImageCacheCompletionBlock completionBlock = ^(id &FICEntity& entity, NSString *formatName, UIImage *image) {
NSLog(@"Processed and stored image for entity: %@", entity);
[sharedImageCache setImage:newUserPhoto forEntity:user withFormatName:formatName completionBlock:completionBlock];
Canceling Source Image Requests(取消图片请求)
If an image request is already in progress, it can be cancelled:
// We scrolled up far enough that the image we requested
cancel the request
XXUser *user = [self _currentUser];
NSString *formatName = XXImageFormatNameUserThumbnailSmall;
[sharedImageCache cancelImageRetrievalForEntity:user withFormatName:formatName];
When this happens, Fast Image Cache cleans up its internal bookkeeping, and any completion blocks from the corresponding image request will do nothing at this point. However, the image cache's delegate is still responsible for ensuring that any outstanding source image requests (e.g., network requests) are cancelled:
- (void)imageCache:(FICImageCache *)imageCache cancelImageLoadingForEntity:(id &FICEntity&)entity withFormatName:(NSString *)formatName {
[self _cancelNetworkRequestForSourceImageForEntity:entity withFormatName:formatName];
Working with Image Format Families
The advantage of classifying image formats into families is that the image cache's delegate can tell the image cache to process entity source images for all image formats in a family when any image format in that family is processed.
- (BOOL)imageCache:(FICImageCache *)imageCache shouldProcessAllFormatsInFamily:(NSString *)formatFamily forEntity:(id&FICEntity&)entity {
BOOL shouldProcessAllFormats = NO;
if ([formatFamily isEqualToString:XXImageFormatFamilyUserThumbnails]) {
XXUser *user = (XXUser *)entity;
shouldProcessAllFormats = user.active;
return shouldProcessAllFormats;
The advantage of processing all image formats in a family at once is that the source image does not need to be repeatedly downloaded (or loaded into memory if cached on disk).
For example, if a user changes their profile photo, it probably makes sense to process the new source image for every variant at the same time that the first image format is processed. That is, if the image cache is processing a new user profile photo for the image format named XXImageFormatNameUserThumbnailSmall, then it makes sense to also process and store new image data for that same user for the image format named XXImageFormatNameUserThumbnailMedium.
Documentation
Fast Image Cache's header files are fully documented, and
can be used to generate documentation in various forms, including HTML and Xcode DocSet.
HTML documentation can be .
Demo Application
Included with this repository is a demo app Xcode project. It demonstrates the difference between the conventional approach for loading and displaying images and the Fast Image Cache approach. See the.
/path/FastImageCache
Fast Image Cache is an efficient, persistent, and—above a…
发表了一篇文章
to your Podfile. If you don't use Cocoapods you're welcome to use git submodules, or simply
and include it in your project manually.
Note that FlatUIKit requires the CoreText framework as well as iOS & 5.0. The flat stepper component requires iOS & 6.0.
你可以使用 Cocoapods 来安装。你也可以手动下载源码来添加到你的工程当中。
注意,FlatUIKit 需要 CoreText 框架,iOS & 5.0,这个扁平的 stepper 组件需要 iOS & 6.0。
The Components(组件)
Buttons(按钮)
FUIButton is a drop-in subclass of UIButton that exposes the additional properties buttonColor, shadowColor, cornerRadius, and shadowHeight. Note that if you set any of these, you have to set all of them.
FUIButton 继承自父类 UIButton,它添加了一些额外的属性 buttonColor, shadowColor, cornerRadius, 和 shadowHeight,注意,如果你设置了其中的一个,你就必须设置所有剩下的属性。
myButton.buttonColor = [UIColor turquoiseColor];
myButton.shadowColor = [UIColor greenSeaColor];
myButton.shadowHeight = 3.0f;
myButton.cornerRadius = 6.0f;
myButton.titleLabel.font = [UIFont boldFlatFontOfSize:16];
[myButton setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
SegmentedControls(段控制器)
FUISegmentedControl is a drop-in subclass of UISegmentedControl that exposes the additional properties selectedColor, deselectedColor, selectedFont, deselectedFont, selectedFontColor, deselectedFontColor, dividerColor and cornerRadius. Note that if you set any of these, it is recommended that you set all of them.
FUISegmentedControl 继承至父类 UISegmentedControl,它添加了一些额外的属性 selectedColor, deselectedColor, selectedFont, deselectedFont, selectedFontColor, deselectedFontColor, dividerColor 和 cornerRadius,注意,设置了其中一个,其他剩下的属性都需要设置。
mySegmentedControl.selectedFont = [UIFont boldFlatFontOfSize:16];
mySegmentedControl.selectedFontColor = [UIColor cloudsColor];
mySegmentedControl.deselectedFont = [UIFont flatFontOfSize:16];
mySegmentedControl.deselectedFontColor = [UIColor cloudsColor];
mySegmentedControl.selectedColor = [UIColor amethystColor];
mySegmentedControl.deselectedColor = [UIColor silverColor];
mySegmentedControl.dividerColor = [UIColor midnightBlueColor];
mySegmentedControl.cornerRadius = 5.0;
Switches(选择器)
FUISwitch is not a subclass of UISwitch (UISwitch is too inflexible to subclass), but rather a reimplementation that exposes all of the methods of UISwitch. In addition, it also provides access to its underlying on/off UILabels and other subviews.
FUISwitch 不是继承至 UISwitch(UISwitch 太恶心) ,只是重新实现了它,另外,它提供了开关的 UILabel 。
mySwitch.onColor = [UIColor turquoiseColor];
mySwitch.offColor = [UIColor cloudsColor];
mySwitch.onBackgroundColor = [UIColor midnightBlueColor];
mySwitch.offBackgroundColor = [UIColor silverColor];
mySwitch.offLabel.font = [UIFont boldFlatFontOfSize:14];
mySwitch.onLabel.font = [UIFont boldFlatFontOfSize:14];
Alert Views(警告View)
Similar to FUISwitch, FUIAlertView is a reimplemenation of UIAlertView that exposes all of UIAlertView's methods (and delegate methods, with the FUIAlertViewDelegate protocol), but with far greater flexibility in UI customization. All of its child UILabels, UIViews, and FUIButtons can be customized at will.
与 FUISwitch ,FUIAlertView 重新实现了 UIAlertView(以及提供代理方法),更具柔韧性。所有它的子 UILabel ,UIView 以及 FUIbutton 都可以定制。
FUIAlertView *alertView = [[FUIAlertView alloc] initWithTitle:@"Hello"
message:@"This is an alert view"
delegate:nil cancelButtonTitle:@"Dismiss"
otherButtonTitles:@"Do Something", nil];
alertView.titleLabel.textColor = [UIColor cloudsColor];
alertView.titleLabel.font = [UIFont boldFlatFontOfSize:16];
alertView.messageLabel.textColor = [UIColor cloudsColor];
alertView.messageLabel.font = [UIFont flatFontOfSize:14];
alertView.backgroundOverlay.backgroundColor = [[UIColor cloudsColor] colorWithAlphaComponent:0.8];
alertView.alertContainer.backgroundColor = [UIColor midnightBlueColor];
alertView.defaultButtonColor = [UIColor cloudsColor];
alertView.defaultButtonShadowColor = [UIColor asbestosColor];
alertView.defaultButtonFont = [UIFont boldFlatFontOfSize:16];
alertView.defaultButtonTitleColor = [UIColor asbestosColor];
[alertView show];
Sliders/Steppers/Progress Views
To provide flat UISliders, UIProgressViews and UISteppers, we simply provide categories on UISlider/ProgressView/UIStepper to automatically configure their appearance with appropriate colors/corner radii. This makes for zero-friction integration with your existing project:
为了提供扁平风格的 UISlider ,UIProgressView 以及 UIStepper。我仅仅提供了相关类目文件来自动的配置这些控件的样式,诸如颜色,圆角值等。把这些添加到你的项目中,零污染。
[mySlider configureFlatSliderWithTrackColor:[UIColor silverColor]
progressColor:[UIColor alizarinColor]
thumbColor:[UIColor pomegranateColor]];
[myProgressView configureFlatProgressViewWithTrackColor:[UIColor silverColor]
progressColor:[UIColor alizarinColor]];
[myStepper configureFlatStepperWithColor:[UIColor wisteriaColor]
highlightedColor:[UIColor wisteriaColor]
disabledColor:[UIColor amethystColor]
iconColor:[UIColor cloudsColor]];
Bar Button Items
To customize bar button items for your entire application (including back buttons), UIBarButtonItem+FlatUI provides a class method which leverages the UIBarButtonItem appearance proxy to do this in one step:
为了在你整个应用中全局定制 bar item,UIBarButtonItem+FlatUI 提供了一个类方法,用来促使 UIBarButtonItem 的样式改变,你只需要做一步设置即可。
[UIBarButtonItem configureFlatButtonsWithColor:[UIColor peterRiverColor]
highlightedColor:[UIColor belizeHoleColor]
cornerRadius:3];
However, this might cause rendering issues with controllers that are pushed from actionsheets, sharesheets or links in webviews. To prevent this behavior, scope the customized bar buttom items to your controllers:
然而,这回引起渲染问题,当你的控制器从 actionsheet ,sharesheet 否则 webview 中 push 出来的。为了防止这个,你可以进行如下的设置。
[UIBarButtonItem configureFlatButtonsWithColor:[UIColor peterRiverColor]
highlightedColor:[UIColor belizeHoleColor]
cornerRadius:3
whenContainedIn:[YourViewController class]];
Navigation Bars
As above, we provide a category on UINavigationBar to configure it flatly with a single color:
像上面那样,我提供了一个 UINavigationBar 类目文件来配置,仅仅是设置颜色。
[self.navigationController.navigationBar configureFlatNavigationBarWithColor:[UIColor midnightBlueColor]];
TableView Cells
You can modify the backgroundColor and selectedBackgroundColor of a UITableViewCell without losing the rounded corners. The cell will copy the UITableView's separator color. The separator height is exposed as separatorHeight and the radius as cornerRadius.
你可以修改 UITableViewCell 的背景颜色,以及选中时的背景颜色,当然,你也可以设置圆角。这个 cell 会复制 UITableView 的分割条颜色。分割条的高度被扩展了支持圆角以及内圆角。
cell = [UITableViewCell configureFlatCellWithColor:[UIColor greenSeaColor]
selectedColor:[UIColor cloudsColor]
style:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
cell.cornerRadius = 5.0f; // optional
cell.separatorHeight = 2.0f; // optional
Like some other flat components, we simply provide a category to automatically configure a popover appearance for iPad by only having to set a background color.
像其他的扁平组件一样,我提供了一个类目来自动配置一个 popover 的样式用于 iPad ,仅仅设置一下背景色即可。
popover = [[UIPopoverController alloc] initWithContentViewController:nc];
[popover configureFlatPopoverWithBackgroundColor: [UIColor midnightBlueColor] cornerRadius:3];
popover.delegate = self;
[popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny
For convenience, FlatUIKit includes the colors defined at . You can see examples of these colors in the code/components above. Using them is as simple as:
为了便利,FlatUIKit 包括了已经定义好的颜色。你可以看 demo ,用下面的方式来使用。
#import &FlatUIKit/UIColor+FlatUI.h&
UIColor *myColor = [UIColor turquoiseColor];
FlatUIKit comes bundled with Lato, a clean, beautiful open font. More info on Lato can be found . It is included in FlatUIK you can use it as follows:
FlatUIKit 使用了 Lato 字体,整洁而美观。你可以在这里看到更多的信息。FlatUIKit 自动包含了 FlatUIKit。你可以这么用:
#import "UIFont+FlatUI.h"
UIFont *myFont = [UIFont flatFontOfSize:16];
FlatUIKit is a collection of iOS components styled with the &Flat UI& aesthetic that we …
发表了一篇文章
/ccgus/fmdb
This is an Objective-C wrapper around SQLite: http://sqlite.or…
发表了一篇文章
MAObjCRuntime
源码地址:(引入头文件MARTNSObject.h即可,非arc环境下)
/s/1eQ6776U
https://githu…
发表了一篇文章
Dynamically Generated iOS Headers
/nst/iOS-Runtime-Headers
Here are iOS Object…
发表了一篇文章
Core Text Objective-C Wrapper
/akosma/CoreTextWrapper
Introduction(介绍)
One of th…
发表了一篇文章
One time setup (Explicit registration):(一次设定,明确的注册)
/* FONT COLLECTION FILE (TTC OR OTC) */
// Create an NSURL for your font file: 'Lao MN.ttc'
NSURL *laoFontURL = [[NSBundle mainBundle] URLForResource:@"Lao MN" withExtension:@"ttc"]];
// Do the registration.
NSArray *fontPostScriptNames = [UIFont registerFontFromURL:laoFontURL];
// If everything went ok, fontPostScriptNames will become @[@"LaoMN",@"LaoMN-Bold"]
// and collection will be registered.
// (Note: On iOS & 7.0 you will get an empty array)
// Then, anywhere in your code, you can do
UIFont *laoFont = [UIFont fontWithName:@"LaoMN" size:18.0f];
/* SINGLE FONT FILE (TTF OR OTF) */
// Create an NSURL for your font file: 'Lato-Hairline.ttf'
NSURL *latoHairlineFontURL = [[NSBundle mainBundle] URLForResource:@"Lato-Hairline" withExtension:@"ttf"]];
// Do the registration.
NSArray *fontPostScriptNames = [UIFont registerFontFromURL:latoHairlineFontURL];
// If everything went ok, fontPostScriptNames will become @[@"Lato-Hairline"]
// and collection will be registered.
// Then, anywhere in your code, you can do
UIFont *latoHairlineFont = [UIFont fontWithName:@"Lato-Hairline" size:18.0f];
UIFont *latoHairlineFont = [UIFont customFontWithURL:latoHairlineFontURL size:18.0f];
// or (*deprecated*)
UIFont *myCustomFont = [UIFont customFontOfSize:18.0f withName:@"Lato-Hairline" withExtension:@"ttf"];
No setup (Implicit registration)(不用设置,使用时注册)
/* SINGLE FONT (TTF OR OTF) */
// Create an NSURL for your font file: 'Lato-Hairline.ttf'
NSURL *latoHairlineFontURL = [[NSBundle mainBundle] URLForResource:@"Lato-Hairline" withExtension:@"ttf"]];
// Then, anywhere in your code, you can do
UIFont *latoHairlineFont = [UIFont customFontWithURL:latoHairlineFontURL size:18.0f];
// or (*deprecated*)
UIFont *myCustomFont = [UIFont customFontOfSize:18.0f withName:@"Lato-Hairline" withExtension:@"ttf"];
NOTE: Font registration will be made on first [ UIFont customFont… ] method call.
注意:你在注册字体前,需要先调用[UIFont customFont...]方法.
Prerequisites(前提条件)
UIFontWDCustomLoader requires:
Deployment target greater or equal to iOS 4.1
CoreText Framework
&= iOS 4.1
需要引入CoreText框架
This library has been tested with: iOS 5, 6 and 7
在 iOS 5,6,7 上都测试过了亲.
附带本人的测试结果^_^
*用的时候直接取
*仅注册一次,以后可以直接根据名字使用
上述两种方式都得出了一样的结果哦,亲.
再来一个组合显示:
结果,效果拔群!!
UIFontWDCustomLoader
/daktales/UIFontWDCustomLoader
You can use UIFontWDCustomLo…
发表了一篇文章
FrameAccessor
/AlexDenisov/FrameAccessor
Manual Install(手动安装)
All you need to …
发表了一篇文章
The Amazing Audio Engine
/TheAmazingAudioEngine/TheAmazingAudioEngine
The Amazin…
发表了一篇文章
// 直接从RGB取颜色(RGB 0xFF00FF)
#define UICOLOR_FROM_RGB(rgbValue) \
[UIColor colorWithRed:((float)((…
发表了一篇文章
- (void)setMainController:(MainViewController *)mainController{
_mainController = mainC
UIScreenEdgePanGestureRecognizer *panGesture = [[UIScreenEdgePanGestureRecognizer alloc]initWithTarget:self action:@selector(gestureHandler:)];
panGesture.edges = UIRectEdgeL
[[self.mainController.view window] addGestureRecognizer:panGesture];
While we set this property we attach a gesture recognizer for theUIScreenEdgePanGestureRecognizer to the window view and we set its side as left.
Note: we use the window view because that way the gesture is recognised in the entire application. How to set the recogniser obviously depends on your specific needs.
At this point, when user moves his finger from the left side of the screen to the right, the gesture handler is called.
我们设置这个属性,来绑定UIScreendgePanGestureRecognizer到window的view上,并设置边界为left。
注意:我们设置成window view是因为在那种情况下,这个手势是整个程序中都能识别的。如何设置这个手势取决于你自己的需求。
在这时,当用户在屏幕左端移动手指到屏幕右端,这个手势就触发了。
UIPERCENTDRIVENINTERACTIVETRANSITION(百分比驱动型动态交互动画)
Now that a part of the user interactions is tied to the transitionManager it’s time to grab this information and put it to good use.
我们已经把用户的交互绑定到了transitionManager中,是时候来抓取信息使用了。
I previously mentioned the UIViewControllerInteractiveTransitioning, but as you can see the TransitionManager is not implementing it. It is, in fact, subclassing theUIPercentDrivenInteractiveTransition.
我之前提过了方法UIViewControllerInteractiveTransitioning,但是,这个TransitionManager没有实现他。因为,事实上,他是继承至UIPercentDrivenInteractiveTransition的。
From the documentation:
这个是官方文档的描述:
`A percent-driven interactive transition object drives the custom animation between the disappearance of one view controller and the appearance of another. It relies on a transition animator delegate (a custom object that adopts the UIViewControllerAnimatorTransitioning protocol) to set up and perform the animations.`
这个百分比驱动的交互转场对象可以酷动自定义的动画,介于一个controller将要消失以及另外一个controller将要出现。他以来与一个转场动画器的代理,来设置以及执行这些动画。
This class has 3 important methods that work together with the gesture handler to drive the animation.
这个类有着3个方法,一起配合手势来驱动这个动画效果。
o updateInteractiveTransition: used to set the progress of the transition from 0.0 to 1.0.设置进程百分比(从0.0到1.0)
o cancelInteractiveTransition: in case we wanted to abort the transition (for example when the user aborts the gesture)放弃动画
o finishInteractiveTransition: to mark that the transition can be completed in cases when the user only partially completes the gesture (but we want to assume he intends to complete the transition).完成动画
So, having already created the animation (it is described in the animateTransition: method), we now build the gesture handler that, together with the UIPercentDrivenInteractiveTransition method, is going to make the interaction work.
所以,我们已经创建了这个动画(在这个方法animateTransition:中),现在,我们来建一个手势来控制它,一起配合UIPercentDrivenInteractiveTransition这个方法,来实现交互效果。
THE GESTURE RECOGNIZER HANDLER(手势识别以及控制)
Stay in the TransitionManager.m file and check the gestureHandler function.
进入TransitionManager.m文件中,查看下gestureHandler方法。
This is a standard gesture handler that, in this case, has to recognize pan gestures from the left side of the screen, nothing special.
这是一个标准的手势,在这个情形下,必须识别拖拽手势,从屏幕的左侧开始,没有什么特别的。
When the gesture state is UIGestureRecognizerStateChanged we instantiate the modalController using the same routine we adopt for the animated custom transition:
当这个动画的状态变为UIGestureRecognizerStateChanged,我们实例化这个modalController,使用同样的路径来改变这个动画:
self.modalController = [[ModalViewController alloc]init];
self.modalController.transitioningDelegate = self;
self.modalController.modalPresentationStyle = UIModalPresentationC
[self.mainController presentViewController:self.modalController animated:YES completion:nil];
1) set a transition delegate (in this case, the TransitionManager itself).设置一个transition协议
2) set the modal presentation style to UIMoldaPresentationCustom.设置这个modal的展示风格为UIMoldaRresentationCustom
Note: in the previous tutorial I set this property to the mainController. Mistake. Fixed.
3) present the modalController from the mainController从mainController来展示这个modalController
Whit the gesture state UIGestureRecognizerStateChanged we just convert the touch location into a value ranging from 0 to 1 as it was shown in the previous image. In this code we take as reference the whole screen. So the left side is 0 and the right side is 1.
通过这个手势的状态值,我们将手势的位移转换成一个从0到1的值,刚好覆盖了整个屏幕。所以左侧刚好是0而右侧刚好是1。
CGFloat animationRatio = location.x / CGRectGetWidth([self.mainController.view window].bounds);
[self updateInteractiveTransition:animationRatio];
With these 2 rows we are translating the finger position to the progress of the animation.
用这两行代码,我们将手指的位移转换成了animation的progress。
Last but not least, the state UIGestureRecognizerStateEnded. Within this state we check wether the user wants to cancel the transition or complete it. To check user intention we just take into account the gesture velocity – not to be confused with the speed, velocity can be intended as the direction -.
If the direction is right we complete the transition otherwise we cancel it.
最后但不是很重要的,就是这个状态UIGestureRecognizerStateEnded。通过这个状态,我们检查这个用户是否想取消这个动画或者是完成他。为了检查这个,我们只需要考虑手势的速率。不要与速度混淆了,速率可以被看做是方向。
如果这个方向是对的,我们完成这个动画,如果不是,就取消他。
else if (recognizer.state == UIGestureRecognizerStateEnded) {
if (self.transitionTo == MODAL) {
if (velocity.x & 0) {
[self finishInteractiveTransition];
[self cancelInteractiveTransition];
self.modalController = nil;
At this point we have implemented the interactivity with the transition and it works like a charm.
最后,我们实现了这个动态交互的转场动画,他运行得不错哦,亲。
FINAL NOTES(最后的说明)
You can see that the transition now works in two different ways.
如今这个转场动画有两种方式了。
The presentation uses the interactive transition, while the dismiss keeps the previous custom transition, but both use the same animation! This means that you can create a really complete user experience mixing together a full user interaction with some driven call to action (like a button to dismiss the current controller).
展示controller时使用了实时动态交互,同时,推出controller时能保持自定义的动画效果,这两个都用了同样的动画!这意味着,你可以创建一个完整的用户体验,混杂了一个完全的用户驱动动画或者普通动画形式。
Have fun with transitions and show me your results pinging me on Twitter!
如果你用到了这个,在Twitter上告知我吧。
INTERACTIVE TRANSITIONS 实时动态动画
翻译不到位处敬请谅解,感谢原作者分享精神
原文链接 http://www.thinkandbuild.it/interactive-t…
发表了一篇文章
animation.toValue = @1.0;
animation.removedOnCompletion = NO;
animation.duration = kD
[self.pathBuilderView.pathShapeView.shapeLayer addAnimation:animation forKey:NSStringFromSelector(@selector(strokeEnd))];
self.pathBuilderView.pathShapeView.shapeLayer.speed = 0;
self.pathBuilderView.pathShapeView.shapeLayer.timeOffset = 0.0;
[CATransaction flush];
self.pathBuilderView.pathShapeView.shapeLayer.timeOffset = kInitialTimeO
The end result of this approach is that the animation has a beginTime of 0 and the shape layer renders it at time kInitialTimeOffset.
结果呢,就是动画有一个 beginTime,从 0 开始,然后,shapelayer 就根据 kInitialTimeOffset 来渲染。
The [CATransaction flush] is required because it forces the system to give the animation added to the layer a beginTime. The animation's beginTime is calculated by adding its initial value (its value before being added to the layer) to the layer's current time. This is why the layer's timeOffset must be set to 0 rather thankInitialTimeOffset when the animation is added. Otherwise, the animation's beginTime will have already taken kInitialTimeOffset into account such that the animation is added to the time range(kInitialTimeOffset, kInitialTimeOffset + kDuration) instead of (0, kDuration).
这个方法 [CATransaction flush] 是必须的,因为,他能够强制的让系统给添加了动画的 layer 一个 beginTime 。这个动画的 beginTime
是添加了 layer 的起始值,这就是为什么 layer 的 timeOffset 必须设置成 0 ,而不是 kInitalTimeOffset。所以,这个动画的 beginTime 会考虑到 kInitialTimeOffset ,然后他的时间就被设置成了 (kIntialTimeOffset, kInitialTimeOffset + kDuration), 而不是 (0, kDuration)【能力有限,此段翻译不准,见谅】
This example was inspired by
is a helpful resource.
这个例子的灵感来自于
AnimatedPath动画路径
感谢原作者分享精神,有空补上使用教程
/twotoasters/AnimatedPath
AnimatedPath expl…
发表了一篇文章
POST URL-Form-Encoded Request(附带表单编码的POST请求)
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
[manager POST:@"/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
POST Multi-Part Request(复杂的POST请求)
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
[manager POST:@"/resources.json" parameters:parameters constructingBodyWithBlock:^(id&AFMultipartFormData& formData) {
[formData appendPartWithFileURL:filePath name:@"image" error:nil];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
AFURLSessionManager
AFURLSessionManager creates and manages an NSURLSession object based on a specified NSURLSessionConfiguration object, which conforms to &NSURLSessionTaskDelegate&, &NSURLSessionDataDelegate&, &NSURLSessionDownloadDelegate&, and &NSURLSessionDelegate&.
AFURLSessionManager 创建了一个管理一个NSURLSession的对象,基于一个指定的NSURLSessionConfiguration对象,它与以下的这些协议融合在一起(&NSURLSessionTaskDelegate&, &NSURLSessionDataDelegate&, &NSURLSessionDownloadDelegate&,&NSURLSessionDelegate&)。
Creating a Download Task(创建一个下载任务)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(@"File downloaded to: %@", filePath);
[downloadTask resume];
Creating an Upload Task(创建一个上传任务)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
NSLog(@"Success: %@ %@", response, responseObject);
[uploadTask resume];
Creating an Upload Task for a Multi-Part Request, with Progress(创建一个复杂的请求,并附带进度)
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"/upload" parameters:nil constructingBodyWithBlock:^(id&AFMultipartFormData& formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSProgress *progress = nil;
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
NSLog(@"%@ %@", response, responseObject);
[uploadTask resume];
Creating a Data Task(创建一个数据任务)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
NSLog(@"%@ %@", response, responseObject);
[dataTask resume];
Request Serialization(请求序列化)
Request serializers create requests from URL strings, encoding parameters as either a query string or HTTP body.
请求序列化器会从URL字符串创建请求,编码参数,查找字符串或者是HTTPbody部分。
NSString *URLString = @"";
NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]};
Query String Parameter Encoding(查询string的编码)
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters error:nil];
GET ?foo=bar&baz[]=1&baz[]=2&baz[]=3
URL Form Parameter Encoding(查询URL表单形式参数的编码)
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters];
Content-Type: application/x-www-form-urlencoded
foo=bar&baz[]=1&baz[]=2&baz[]=3
JSON Parameter Encoding(查询json参数的编码)
[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters];
Content-Type: application/json
{"foo": "bar", "baz": [1,2,3]}
Network Reachability Manager(监测网络管理器)
AFNetworkReachabilityManager monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces.
AFNetworkReachabilityManager 监测域名以及IP地址的畅通性,对于WWAN以及WiFi的网络接口都管用。
Shared Network Reachability(单例形式检测网络畅通性)
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
HTTP Manager with Base URL(用基本的URL管理HTTP)
When a baseURL is provided, network reachability is scoped to the host of that base URL.
如果提供了一个基本的URL地址,那个基本URL网址的畅通性就会被仔细的监测着。
NSURL *baseURL = [NSURL URLWithString:@"/"];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
NSOperationQueue *operationQueue = manager.operationQueue;
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
[operationQueue setSuspended:NO];
case AFNetworkReachabilityStatusNotReachable:
[operationQueue setSuspended:YES];
Security Policy
AFSecurityPolicy evaluates server trust against pinned X.509 certificates and public keys over secure connections.
Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled.
Allowing Invalid SSL Certificates(允许不合法的SSL证书)
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES; // not recommended for production
AFHTTPRequestOperation
AFHTTPRequestOperation is a subclass of AFURLConnectionOperation for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request.
Although AFHTTPRequestOperationManager is usually the best way to go about making requests, AFHTTPRequestOperation can be used by itself.
AFHTTPRequestOperation继承自AFURLConnectionOperation,使用HTTP以及HTTPS协议来处理网络请求。它封装成了一个可以令人接受的代码形式。当然AFHTTPRequestOperationManager 目前是最好的用来处理网络请求的方式,但AFHTTPRequestOperation 也有它自己的用武之地。
GET with AFHTTPRequestOperation(使用AFHTTPRequestOperation)
NSURL *URL = [NSURL URLWithString:@"/resources/123.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
[[NSOperationQueue mainQueue] addOperation:op];
Batch of Operations(许多操作一起进行)
NSMutableArray *mutableOperations = [NSMutableArray array];
for (NSURL *fileURL in filesToUpload) {
NSURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"/upload" parameters:nil constructingBodyWithBlock:^(id&AFMultipartFormData& formData) {
[formData appendPartWithFileURL:fileURL name:@"images[]" error:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[mutableOperations addObject:operation];
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
NSLog(@"All operations in batch complete");
[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
大名鼎鼎的开源网络库AFNetworking 2.0,目前只是翻译了Github上的链接文章,使用教程请点击
/YouXianMing/p/365146…
发表了一篇文章
/mjmsmith/gcdobjc
GCDObjC is an Objective-C wrapper for the most commonl…
发表了一篇文章
and you are ready to go!
If you'd like to run the bundled test app, make sure to install its dependencies by running
pod install
after cloning the repo.
我建议你使用CocoaPods安装吧。
RBBCustomAnimation(自定义动画)
Use RBBCustomAnimation to create arbitrary animations by passing in an RBBAnimationBlock:
使用RBBCustomAnimation来创建直观的自定义动画,在RBBAnimationBlock中设置即可。
RBBCustomAnimation *rainbow = [RBBCustomAnimation animationWithKeyPath:@"backgroundColor"];
rainbow.animationBlock = ^(CGFloat elapsed, CGFloat duration) {
UIColor *color = [UIColor colorWithHue:elapsed / duration
saturation:1
brightness:1
return (id)color.CGColor;
The arguments of the block are the current position of the animation as well as its total duration.
Most of the time, you will probably want to use the higher-level RBBTweenAnimation.
block中的参数就是你要设置动画的参数,以及需要你配置一个动画持续的时间。
大部分时间,你需要使用更高级别上的RBBTweenAnimation。
RBBSpringAnimation(精灵动画)
RBBSpringAnimation is a handy replacement for the private . Specify your spring's mass, damping, stiffness as well as its initial velocity and watch it go:
RBBSpringAnimation是用来替换这个私有方法CASpringAnimation。指定你精灵对象的质量,阻尼,生硬程度以及他的速率,参考如下:
RBBSpringAnimation *spring = [RBBSpringAnimation animationWithKeyPath:@"position.y"];
spring.fromValue = @(-100.0f);
spring.toValue = @(100.0f);
spring.velocity = 0;
spring.mass = 1;
spring.damping = 10;
spring.stiffness = 100;
spring.additive = YES;
spring.duration = [spring durationForEpsilon:0.01];
RBBTweenAnimation(两点之间的动画)
RBBTweenAnimation allows you to animate from one value to another, similar to CABasicAnimation but with a greater flexibility in how the values should be interpolated.
It supports the same cubic Bezier interpolation that you get from CAMediaTimingFunction using the RBBCubicBezier helper function:
RBBTweenAnimation允许你从一个值动态变化到另外一个值,就像CABasicAnimation一样,但是呢,对于如何设置参数更加便利。
它同样支持你篡改立方体贝塞尔曲线,你可以从CAMediaTimingFunction中使用RBBCubicBezier来获取一些帮助信息:
RBBTweenAnimation *easeInOutBack = [RBBTweenAnimation animationWithKeyPath:@"position.y"];
easeInOutBack.fromValue = @(-100.0f);
easeInOutBack.toValue = @(100.0f);
easeInOutBack.easing = RBBCubicBezier(0.68, -0.55, 0.265, 1.55);
easeInOutBack.additive = YES;
easeInOutBack.duration = 0.6;
However, RBBTweenAnimation also supports more complex easing functions such as RBBEasingFunctionEaseOutBounce:
当然,RBBTweenAnimation支持更复杂的easing方法,例如RBBEasingFunctionEaseOutBounce:
RBBTweenAnimation *bounce = [RBBTweenAnimation animationWithKeyPath:@"position.y"];
bounce.fromValue = @(-100);
bounce.toValue = @(100);
bounce.easing = RBBEasingFunctionEaseOutBounce;
bounce.additive = YES;
bounce.duration = 0.8;
You can also specify your own easing functions, from scratch:
你也可以使用你自己定制的easiing函数:
RBBTweenAnimation *sinus = [RBBTweenAnimation animationWithKeyPath:@"position.y"];
sinus.fromValue = @(0);
sinus.toValue = @(100);
sinus.easing = ^CGFloat (CGFloat fraction) {
return sin((fraction) * 2 * M_PI);
sinus.additive = YES;
sinus.duration = 2;
RBBAnimation
RBBAnimation is a subclass of CAKeyframeAnimation that allows you to declare your ani…
发表了一篇文章
1.用Photoshop制作出字母以及背景
要点:阴影部分靠渐变工具中的透明渐变产生,这个最终会产生边缘渐变消失的效果(如动画中边缘逐渐消失),很重要,如下图示
2.将文件分层导入到 After Effects 中
3.新建六个固态层,并用钢笔工具在线条上描绘
4.对每个固态层使用 3D Stroke 特效,辉光特效(看起来更柔和),以及参数的配置,并根据时间打上关键帧
要点:3D Stroke 的关键配置如下所示
5.整理下图层关系后之后将渲染成JPG图片序列
6.渲染完成后,将文件导入到GIF Movie Gear,通过简单的操作就能够导出动态gif文件了
本人从事iOS开发工作,但对特效制作很感兴趣,现提供一份教程,制作本人logo的教程。
上图是用 Photoshop 与 After Effects 与 GIF Movie Gear 合力制作的动…
发表了一篇文章
本人视频教程系列
导入AFNetworking 2.0 文件夹,引入头文件AFNetworking.h
---------------
*使用NSURLSessionDownloadTask来…
发表了一篇文章
UITableView分页上拉加载简单,ARC环境,源码如下,以作备份:
原理是,点击最后一个cell,触发一个事件来处理数据,然后reloadData
RootViewController.m +…
312914人浏览
220915人浏览
178126人浏览
124093人浏览
99063人浏览
手机扫描访问社区}

我要回帖

更多关于 e.target 获取class 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信