2016-09-20 14:11:07 Zhi_Sheng 阅读数 1542
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    104 人正在学习 去看看 谷世杰

图片的本身就是各种图像数据的载体,包含着像素、色彩、灰度等各种数据信息,除此之外,还包含着曝光数据、日期、位置、版权等元数据(metadata)。
何为图片元数据

元数据包括许多重要的信息,常用的有Exif(可交换图像文件格式,Exchangeable image file format)、GPS(位置信息)和TIFF(Tagged Image File Format,标签图像文件格式)。

所谓元数据是指Data about Data,就是用来描述数据的数据。

以Exif为例,其中包含了大量信息:

Image Description 图像描述、来源. 指生成图像的工具
Artist 作者 有些相机可以输入使用者的名字
Make 生产者 指产品生产厂家
Model 型号 指设备型号
Orientation方向 有的相机支持,有的不支持
XResolution/YResolution X/Y方向分辨率 本栏目已有专门条目解释此问题。
ResolutionUnit分辨率单位 一般为PPI
Software软件 显示固件Firmware版本
DateTime日期和时间
YCbCrPositioning 色相定位
ExifOffsetExif信息位置,定义Exif在信息在文件中的写入,有些软件不显示。
ExposureTime 曝光时间 即快门速度
FNumber光圈系数
ExposureProgram曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter Priority(快门优先)、Aperture Priority(快门优先)等等。
ISO speed ratings感光度
ExifVersionExif版本
DateTimeOriginal创建时间
DateTimeDigitized数字化时间
ComponentsConfiguration图像构造(多指色彩组合方案)
CompressedBitsPerPixel(BPP)压缩时每像素色彩位 指压缩程度
ExposureBiasValue曝光补偿。
MaxApertureValue最大光圈
MeteringMode测光方式, 平均式测光、中央重点测光、点测光等。
Lightsource光源 指白平衡设置
Flash是否使用闪光灯。
FocalLength焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距 MakerNote(User Comment)作者标记、说明、记录
FlashPixVersionFlashPix版本 (个别机型支持)ColorSpace色域、色彩空间
ExifImageWidth(Pixel X Dimension)图像宽度 指横向像素数
ExifImageLength(Pixel Y Dimension)图像高度 指纵向像素数
Interoperability IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详
FileSource源文件 Compression压缩比。

这些数据就是构成一张图片的元素,也相当于一张图片的名片,包含着丰富的信息。

你可以在此了解更多关于Exif的具体研究。
在开发中使用

目前市场上的大部分智能手机拍摄的照片都支持写入元数据,因此我们可以利用图片的元数据来携带需要添加的数据。在处理图片时,我们往往需要对图片数据进行操作,除了操作其中的图像信息外,我们还可以对图片信息的元数据进行操作,包括存和取。这对于传递数据将是十分便利的,其中一方只需将数据写入图片,另一方通过读取图片的元数据就可获取所要传递的数据,而不需要传除图片之外的任何对象,在实际开发中应用场景很多。


    首先,我们需要借助与UIImagePickerControllerDelegate的代理方法,创建一个UIImagePickerController,在其代理方法- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info中就可获取info,从而获取image对象:

UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];

    为获取info的metadata,要使用ALAssetsLibrary的assetForURL: resultBlock:方法:

 //1. 首先得到Reference URL
    NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
    //2. 创建一个ALAssetsLibrary
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    //3. 使用回调方法,得到字典类型的metadata



 [library assetForURL:assetURL
             resultBlock:^(ALAsset *asset) {

                 NSDictionary *imageMetadata = [[NSMutableDictionary alloc] initWithDictionary:asset.defaultRepresentation.metadata];

                 NSLog(@"metadata:--%@",imageMetadata);

                 NSDictionary *gpsDic = [imageMetadata objectForKey:@"{GPS}"];
                 NSDictionary *exifDic = [imageMetadata objectForKey:@"{Exif}"];
                 NSDictionary *tiffDic = [imageMetadata objectForKey:@"{TIFF}"];

                 //可交换图像文件
                 NSLog(@"Exif info:--%@",exifDic);
                 //地理位置信息
                 NSLog(@"GPS info:--%@",gpsDic);
                 //图像文件格式
                 NSLog(@"tiff info:--%@",tiffDic);
             }

以向图片元数据中写入Exif的kCGImagePropertyExifDateTimeOriginal为例。

1.先按照特定的格式创建一个日期对象:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"YYYY:MM:dd hh:mm:ss"];
NSString *now = [formatter stringFromDate:[NSDate date]];

2.将之前的exifDic中的对应字段值设为当前日期对象now:

[exifDic setValue:now forKey:(NSString*)kCGImagePropertyExifDateTimeOriginal];
[imageMetadata setValue:exifDic forKey:@"{Exif}"];

3.利用ALAssetsLibrary的writeImageToSavedPhotosAlbum: metadata: completionBlock方法写入并保存:

[library writeImageToSavedPhotosAlbum:[image CGImage] metadata:imageMetadata completionBlock:^(NSURL *assetURL, NSError *error) {
                     if (error == nil)
                         NSLog(@"metadata write success!");
                     else
                         NSLog(@"write error:%@",error.userInfo);
                 }];

这样,图片的创建时间就被写入并保存了,如果是对相册中已经存在的图片进行此写入操作,则其将被更改创建时间而另存。

如果你想写入中文或者自定义数据,可以考虑将数据写入到kCGImagePropertyExifUserComment中。

UserComment标签说明
标签号:0x9286;格式:undefined;描述:存储用户的注释,这个标签允许使用两字节的德字符或者 unicode,前8 个字节描述的是字符集,'JIS' 是日文 (著名的有 Kanji)。
'0x41,0x53,0x43,0x49,0x49,0x00,0x00,0x00':ASCII
'0x4a,0x49,0x53,0x00,0x00,0x00,0x00,0x00':JIS
'0x55,0x4e,0x49,0x43,0x4f,0x44,0x45,0x00':Unicode
'0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00':Undefined

UserComment写入的代码实现

NSString *userComment = @"你好,this is a test text for writing data in UserComment";
                 [exifDic setValue:userComment forKey:(NSString*)kCGImagePropertyExifUserComment];
                 [imageMetadata setValue:exifDic forKey:@"{Exif}"];
2016-06-29 16:47:08 wjchao1990 阅读数 370
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    104 人正在学习 去看看 谷世杰

iOS 开发 一些关于图片的处理

1、对图片进行滤镜处理。滤镜名称,iOS上有90多种滤镜,可以通过查看官方文档,来查看相应效果需要的参数数据。
网址:
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/#//apple_ref/doc/filter/ci/CIGaussianBlur

/**
 *  对图片进行滤镜处理
 *
 *  @param image 目标图片
 *  @param name  滤镜名称
 *
 *  @return 完成图片
 */
+ (UIImage *)filerWithOriginalImage:(UIImage *)image fileterName:(NSString *)name{
    CIContext * context = [CIContext contextWithOptions:nil];
    CIImage * inputImage = [[CIImage alloc] initWithImage:image];
    CIFilter * filter = [CIFilter filterWithName:name];
    [filter setValue:inputImage forKey:kCIInputEVKey];
    CIImage * result = [filter valueForKey:kCIOutputImageKey];
    CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]];
    UIImage * resultImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    return resultImage;
}

2、调整图片饱和度、亮度、对比度
其中,饱和度,1是标准饱和度;
亮度,0是标准亮度,范围-1 ~ 1;
对比度,1是标准对比度,1+倍数增加, 0 ~ 1 弱对比度

/**
 *  调整图片饱和度、亮度、对比度
 *
 *  @param image      目标图片
 *  @param saturation 饱和度
 *  @param brightness 亮度:-1.0 ~ 1.0
 *  @param contrast   对比度
 *
 *  @return 完成图片
 */
+ (UIImage *)colorControlsWithOriginalImage:(UIImage *)image saturation:(CGFloat)saturation brightness:(CGFloat)brightness contrast:(CGFloat)contrast{
    CIContext * context = [CIContext contextWithOptions:nil];
    CIImage * inputImage = [[CIImage alloc] initWithImage:image];
    CIFilter * filter = [CIFilter filterWithName:@"CIColorControls"];
    [filter setValue:inputImage forKey:kCIInputImageKey];

    [filter setValue:@(saturation) forKey:@"inputSaturation"];
    [filter setValue:@(brightness) forKey:@"inputBrightness"];
    [filter setValue:@(contrast) forKey:@"inputContrast"];

    CIImage * result = [filter valueForKey:kCIOutputImageKey];
    CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]];
    UIImage * resultImage = [UIImage imageWithCGImage:cgImage];;
    CGImageRelease(cgImage);
    return resultImage;
}

3、创建一张实时模糊效果 View (毛玻璃效果)
/**
* 创建一张实时模糊效果 View (毛玻璃效果)
*
* @param frame frame
*
* @return effectView
*/
+ (UIVisualEffectView *)effectViewWithFrame:(CGRect)frame{
UIBlurEffect * effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView * effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
effectView.frame = frame;
return effectView;
}

4、截取一张 view 生成图片

/**
 *  截取一张 view 生成图片
 *
 *  @param view 目标View
 *
 *  @return 生成的图片
 */
+ (UIImage *)shotWithView:(UIView *)view{
    UIGraphicsBeginImageContext(view.bounds.size);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

5、截取view中某个区域生成一张图片(先截取View)

/**
 *  截取view中某个区域生成一张图片(先截取View)
 *
 *  @param view  目标View
 *  @param scope 目标大小
 *
 *  @return 生成的图片
 */
+ (UIImage *)shotWithView:(UIView *)view scope:(CGRect)scope{
    CGImageRef imageRef = CGImageCreateWithImageInRect([self shotWithView:view].CGImage, scope);
    UIGraphicsBeginImageContext(scope.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect rect = CGRectMake(0, 0, scope.size.width, scope.size.height);
    CGContextTranslateCTM(context, 0, rect.size.height);//  下移
    CGContextScaleCTM(context, 1.0f, -1.0f);
    CGContextDrawImage(context, rect, imageRef);
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGContextRelease(context);
    return image;
}

6、压缩图片到指定尺寸大小

/**
 *  压缩图片到指定尺寸大小
 *
 *  @param image 原始图片
 *  @param size  目标大小
 *
 *  @return 生成图片
 */
+ (UIImage *)compressOriginalImage:(UIImage *)image toSize:(CGSize)size{
    UIImage * resultImage = image;
    UIGraphicsBeginImageContext(size);
    [resultImage drawInRect:CGRectMake(00, 0, size.width, size.height)];
    UIGraphicsEndImageContext();
    return image;
}

7、压缩图片到指定文件大小

/**
 *  压缩图片到指定文件大小
 *
 *  @param image 目标图片
 *  @param size  目标大小(最大值)
 *
 *  @return 返回的图片文件
 */
+ (NSData *)compressOriginalImage:(UIImage *)image toMaxDataSizeKBytes:(CGFloat)size{
    NSData * data = UIImageJPEGRepresentation(image, 1.0);
    CGFloat dataKBytes = data.length/1000.0;
    CGFloat maxQuality = 0.9f;
    CGFloat lastData = dataKBytes;
    while (dataKBytes > size && maxQuality > 0.01f) {
        maxQuality = maxQuality - 0.01f;
        data = UIImageJPEGRepresentation(image, maxQuality);
        dataKBytes = data.length / 1000.0;
        if (lastData == dataKBytes) {
            break;
        }else{
            lastData = dataKBytes;
        }
    }
    return data;
}

github 地址:https://github.com/wangjianchao1990/image

2015-10-12 20:20:02 u010576399 阅读数 352
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    104 人正在学习 去看看 谷世杰

今天想来聊聊iOS的数据持久化。因为今天在家辅导表弟,玩iPad的时候,发现XX应用没有对首页做缓存,正好家里网断了(初三小表弟,你懂得),手机共享伤不起。

回归正题,我建议凡是数据比较多的应用,你都要考虑做下缓存,我看今日头条就不错,在网好的时候,它除了新闻的图片不提前缓存,所有首页文字信息都提前缓存下来了,看的很舒服。
iOS数据持久化,无非几种。

分开讲吧,这篇讲,归档吧。(Archiver持久化)

我推荐一个关于Archive的博文,很详细,这里就不多做说明了。点击打开链接

基本的数据类型如NSString、NSDictionary、NSArray、NSData、NSNumber等可以用属性列表的方法持久化到.plist 文件中,但如果是一些自定义的类的话,属性列表的方法就不管用了。archiver 方法可以做到。

这里强调下,NSKeyedArchive 并不是所有对象都可以通过它来归档的,我们想要归档的话,就必须要遵守NSCoding协议

遵守协议是第一步,之后在遵守协议,希望归档的对象实现两个协议方法,就可以实现数据归档了。

一、 encodeWithCoder:(NSCoder *)encoder  代理方法

-(void)encodeWithCoder:(NSCoder *)encoder{  

[super encodeWithCoder:encoder];//不要忘了这个  首先要调用父类的方法,NSObject除外,NSObject 没有实现此方法。

[encoder encodeInt:self.age forKey:@"age"]; 

[encoder encodeObject:self.name forKey:@"name"];  

[encoder encodeFloat:self.height forKey:@"height"];  


二、initWithCoder:(NSCoder *)decoder  代理方法

-(id)initWithCoder:(NSCoder *)decoder{   

self = [super initWithCoder:decoder];//不要忘了这个  

self.age = [decoder decodeIntForKey:@"age"];

self.name = [decoder decodeObjectForKey:@"name"];   

self.height = [decoder decodeFloatForKey:@"height"];

 return self;  

}


之后的操作就是在归档的地方归档在想解档的地方解档

    //创建  
    -(void)createPerson{  
          
        person *p = [[[person alloc] init] autorelease];  
        p.age = 20;  
        p.name = @"Rio";  
        p.height =1.75f;  
          
        //获得Document的路径  
        NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
        NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];//拓展名可以自己随便取  
          
        [NSKeyedArchiver archiveRootObject:p toFile:path];  
          
    }  
      
    //读取  
    -(void)readPerson{  
        NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
        NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];  
        person *person1 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];  
        NSLog(@"%@",person1);  
    }  

之后,我之前做一款应用时,就用到过这方面来处理缓存

把原理和源码也放在这里了,

原理就是归档,通过请求数据的URL来命名归档的文件名,加上MD5加密一下,基本保证了文件名不重复,

MD5 加密如下,我的处理是给NSString加上了一个类别。


//
//  ScienceCacheManager.m
//  每日新鲜事
//
//  Created by JackYang on 15/9/1.
//  Copyright (c) 2015年 JackYang. All rights reserved.
//

#import "NSString+Hashing.h"
#import <CommonCrypto/CommonDigest.h>

@implementation NSString (NSString_Hashing)

- (NSString *)MD5Hash
{
    const char *cStr = [self UTF8String];
    unsigned char result[16];
    CC_MD5(cStr, strlen(cStr), result);
    return [NSString stringWithFormat:
            @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]];
}

@end



剩下的代码就比较通用了。

我都放在这里了。


//
//  LimitCachManager.h
//  每日新鲜事
//
//  Created by JackYang on 15/9/16.
//  Copyright (c) 2015年 JackYang. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface LimitCachManager : NSObject

//保存url 对应的数据
+ (void)saveData:(id)object atUrl:(NSString*)url;

//读取url对应的数据
+ (id)readDataAtUrl:(NSString*)ulr;

//判断缓存数据是否有效
+ (BOOL)isCacheDataInvalid:(NSString*)url;

//计算缓存的大小
+ (NSInteger)cacheSize;

//清除缓存
+ (void)clearDisk;


@end

主要实现

#import "LimitCachManager.h"
#import "NSString+Hashing.h"

@implementation LimitCachManager

//得到本地缓存的目录
+ (NSString*)cacheDirectory
{
    //得到沙盒目录下的cache文件夹
    NSString *cachDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    cachDir = [cachDir stringByAppendingPathComponent:@"LimitCache"];
    //创建LimitCache文件夹,目的是把所有的缓存数据放到该文件夹下面
    //attribute:nil只文件夹跟父文件夹一样的读写属性
    NSError *error;
    BOOL bret = [[NSFileManager defaultManager] createDirectoryAtPath:cachDir withIntermediateDirectories:YES attributes:nil error:&error];
    if (!bret) {
        NSLog(@"%@",error);
        return nil;
    }

    return cachDir;
}


+ (NSString*)cacheFileFullPath:(NSString*)url
{
    //得到保存的文件的全路径,使用url的MD5加密得到的字符串作为文件名
    //这样url和文件名就对应起来了
    //[url MD5Hash] 是把url进行MD5加密得到的字符串
    //MD5 加密算法是不可逆的
    NSString *fileName = [url MD5Hash];
    NSString *cacheDir = [self cacheDirectory];
    return [cacheDir stringByAppendingPathComponent:fileName];
}

//保存url 对应的数据
//输入的数据,要么是字典,要么数组
+ (void)saveData:(id)object atUrl:(NSString*)url{
    //首先得到保存的文件路径
    NSString *fileFullPath = [self cacheFileFullPath:url];

    //写入数据,使用NSKeyedArchiver进行数据转换
    NSData *data = [NSKeyedArchiver  archivedDataWithRootObject:object];
    [data writeToFile:fileFullPath atomically:YES];
}

//读取url对应的数据
+ (id)readDataAtUrl:(NSString*)url
{
    NSString *fileFullPath = [self cacheFileFullPath:url];
    NSData *data = [NSData dataWithContentsOfFile:fileFullPath];
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

//判断缓存数据是否有效
+ (BOOL)isCacheDataInvalid:(NSString*)url
{
    //isDirectory 的参数是返回给我们是否是一个目录
    NSString *fileFullPath = [self cacheFileFullPath:url];
    BOOL isFileExist = [[NSFileManager defaultManager] fileExistsAtPath:fileFullPath isDirectory:nil];
    //获取文件的属性
    NSDictionary *attributeDic = [[NSFileManager defaultManager] attributesOfItemAtPath:fileFullPath error:nil];
    NSDate *lastModify = attributeDic.fileModificationDate;
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:lastModify];
    BOOL isExpire = (timeInterval > 60*60);
    if (isFileExist && !isExpire) {
        return YES;
    }
    return NO;
}



//计算缓存的大小,遍历缓存目录,把文件内容大小累加
+ (NSInteger)cacheSize
{
    NSInteger totalSize = 0;
    NSString *cacheDir = [self cacheDirectory];
    //得到目录的枚举器,使用它来枚举目录下的所有文件
    NSDirectoryEnumerator *enmuerator = [[NSFileManager defaultManager]enumeratorAtPath:cacheDir];
    for (NSString *fileName in enmuerator) {
        NSString *fileFullPath = [cacheDir stringByAppendingPathComponent:fileName];
        NSDictionary *attributeDic = [[NSFileManager defaultManager] attributesOfItemAtPath:fileFullPath error:nil];
        totalSize += attributeDic.fileSize;
    }
    return totalSize;
}

//清除缓存
+ (void)clearDisk
{
    NSString *cacheDir = [self cacheDirectory];
    [[NSFileManager defaultManager] removeItemAtPath:cacheDir error:nil];
}
@end


当使用是就调用,传入url 存储,读取时先判断文件存在不存在,不存在,就获取,存在就读取本地数据。

然后在清除缓存时,将此缓存一并清除。

2016-09-07 17:24:50 lvchao1122 阅读数 690
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    104 人正在学习 去看看 谷世杰

图片流的第一个字节来辨别

其实就是取出图片数据的第一个字节, 就可以判断出图片的真实类型那该怎么做呢如下:

//通过图片Data数据第一个字节 来获取图片扩展名
- (NSString *)contentTypeForImageData:(NSData *)data {
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        case 0xFF:
            return @"jpeg";
        case 0x89:
            return @"png";     
        case 0x47:
            return @"gif";        
        case 0x49:   
        case 0x4D:
            return @"tiff";        
        case 0x52:  
            if ([data length] < 12) {
                return nil;
            }
            NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
            if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                return @"webp";
            }
            return nil;
    }
    return nil;
}

其实图片数据的第一个字节是固定的,一种类型的图片第一个字节就是它的标识, 我们来调用一下这个方法:

 //假设这是一个网络获取的URL
    NSString *path = @"http://pic.rpgsky.net/images/2016/07/26/3508cde5f0d29243c7d2ecbd6b9a30f1.png";
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:path]];
    //调用获取图片扩展名
    NSString *string = [self contentTypeForImageData:data];
    //输出结果为 png
    NSLog(@"%@",string);
2015-09-12 15:42:45 qq_18425273 阅读数 227
  • Unity仿微信开发

    使用Unity仿微信开发IM即时通讯软件,探索IM开发技术、数据库设计、通用网络模块、音视频通讯等。 功能介绍: 1.支持Unity编辑器、PC、Mac、Android、IOS、UWP平台 2.实现文字、表情、图片、视频、语音、文件发送 3.实现好友、群组功能 4.本地消息存储、离线消息处理 5.实现好友、群组音视频通话

    104 人正在学习 去看看 谷世杰

异步加载图片的原理就是 当网络请求下来的数据中有图片的数据,就把图片的数据提出来 让它自己去通过ImageDownload下载 等下载好了,在把图片传给View去显示。
话不多说 上代码

第一步 :在定义的Model类中 重新声明一个属性 用来显示图片的,在这之前 一定要引入ImageDownload的头文件哦!!!

@property (nonatomic, retain) UIImage *pictureimage;// 用来显示图片的属性

第二步:因为是在MRC下 所以要重写dealloc方法 别忘了!!!

- (void)dealloc
{
    [_movieId release];
    [_movieName release];
    [_pic_url release];
    // 下面是需要release的方法 
    [_pictureimage release];

    [super dealloc];
}

第三步 当外界执行相应的KVC方法(setValuesForKeysWithDictionary)的时候 内部会执行下面的方法 所以我们要重写这个方法 来进行图片异步加载

- (void)setValue:(id)value forKey:(NSString *)key
{
    [super setValue:value forKey:key];

    if ([key isEqualToString:@"pic_url"]) {
    // 使用ImageDownload里面的初始化方法
        ImageDownload *imagedownload = [ImageDownload imageDownloadWithURLStr:value];

        // 这里面的Block方法是要等图片加载完成后执行ImageDownload里面的方法后 才会执行
        __block MovieData *text = self;// 双下划线定义self 是为了防止循环引用

        imagedownload.successBlock = ^(ImageDownload *imageDownload, UIImage *image){
            // 将下载好的图片 赋值给创建的属性
            text.pictureimage = image;
        };

        imagedownload.errorBlock = ^(ImageDownload *imageDownload,NSError *error){
            NSLog(@"error = %@",[error localizedDescription]);
        };
    }
}

第四步 回到ImageDownload.m文件中 图片数据下载完成后 会执行下面的方法

// 将接收到的数据进行拼接
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 拼接数据
    [self.receiveData appendData:data];
}


// 数据下载成功后 调用外界成功的Block方法
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    UIImage *image = [UIImage imageWithData:self.receiveData];
    self.successBlock(self,image);
}
// 下载失败后,同样调用外界失败的Block方法
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    self.errorBlock(self,error);
}

第五步:在View中展示下载好的图片

- (void)configuerDataWithActivity:(MovieData *)movieDate
{
    self.namelabel.text = movieDate.movieName;

    // 异步加载的方式加载图片
    // 将下载好的图片给View中的Label显示出来
    self.imagelabel.image = movieDate.pictureimage;
}

这样 就可以实现异步图片的加载了 但是还有一个问题 就是实际情况中 如果网速比较慢的话 下载好的图片不能显示出来 所以在还不是最完美的版本 ,需要引入KVO观察者
敬请期待。。。

没有更多推荐了,返回首页