• 图片编辑扩展

注:此教程来源于http://www.raywenderlich.com的《iOS8 by Tutorials》


1.准备

与(二)类似的使用Imgur作为图片来源
 

2.正文

添加Photo Editing Extension
之后在新生成的文件夹下找到MainInterface.storyboard为PhotoEditingViewController加上Size Classes,在这里我删掉原来的vc,加入新的vc,并设置它为启动界面,具体设置见我提供的源码中的storyboard文件,这里只具体写写它的实现类PhotoEditingViewController的使用方法。
还要注意的一点是:由于在新工程中要使用RWTImageFilterService.h,所以要在下面添加它的实现.m文件,否则会报错!!!
下面是PhotoEditingViewController.m代码,附有我的一些注释说明
 
 //
// PhotoEditingViewController.m
// JMImgure Photo
//
// Created by JackMa on 15/12/3.
// Copyright © 2015年 JackMa. All rights reserved.
// #import "PhotoEditingViewController.h"
#import <Photos/Photos.h>
#import <PhotosUI/PhotosUI.h>
#import "RWTImageFilterService.h" @interface PhotoEditingViewController () <PHContentEditingController> @property (strong) PHContentEditingInput *input; @property (nonatomic, weak) IBOutlet UIImageView *imageView;
@property (nonatomic, weak) IBOutlet UIButton *undoButton;
@property (nonatomic, weak) IBOutlet UIButton *addButton; @property (strong, nonatomic) RWTImageFilterService *imageFilterService;
@property (strong, nonatomic) NSString *currentFilterName;
@property (strong, nonatomic) UIImage *filteredImage; @end @implementation PhotoEditingViewController //撤销的button
- (IBAction)undo:(id)sender {
self.imageView.image = self.input.displaySizeImage;
self.currentFilterName = nil;
self.filteredImage = nil;
} //添加过滤器
- (IBAction)addFilter:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"过滤器" message:@"请选择一种过滤器" preferredStyle:UIAlertControllerStyleActionSheet];
//遍历字典
[self.imageFilterService.availableFilters enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
UIAlertAction *action = [UIAlertAction actionWithTitle:key style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
//为图片添加过滤
self.filteredImage = [self.imageFilterService applyFilter:obj toImage:self.input.displaySizeImage];
self.imageView.image = self.filteredImage;
self.currentFilterName = obj;
}];
[alert addAction:action];
}];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
} - (void)viewDidLoad {
[super viewDidLoad]; self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageFilterService = [[RWTImageFilterService alloc] init];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} #pragma mark - PHContentEditingController //在原始编辑界面可以对图片进行调整,当你在这个App想获取的是最原始的图片,那么返回NO
//你想获取调整后的adjustmentData的话,那么返回YES
//只有图片经过调整才会调用此函数,否则默认NO
- (BOOL)canHandleAdjustmentData:(PHAdjustmentData *)adjustmentData {
return NO;
} //view Load后,view appear前调用,用来接受原始数据contentEditingInput
- (void)startContentEditingWithInput:(PHContentEditingInput *)contentEditingInput placeholderImage:(UIImage *)placeholderImage {
//canHandleAdjustmentData:返回YES的话,这里的contentEditingInput也会带上adjustmentData
//canHandleAdjustmentData:返回NO的话,这里只有原始图像displaySizeImage
self.input = contentEditingInput;
self.imageView.image = self.input.displaySizeImage;//将原始图片呈现出来
} //点击右上方完成button时调用
- (void)finishContentEditingWithCompletionHandler:(void (^)(PHContentEditingOutput *))completionHandler {
//异步处理图片
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
//创建output并设置
PHContentEditingOutput *output = [[PHContentEditingOutput alloc] initWithContentEditingInput:self.input];
NSData *archiveData = [NSKeyedArchiver archivedDataWithRootObject:self.currentFilterName];
#warning Please set your Photos Extension Name and Version here
PHAdjustmentData *adjustmentData = [[PHAdjustmentData alloc] initWithFormatIdentifier:@"qq100858433.JMImgure.JMImgure-Photo" formatVersion:@"1.0" data:archiveData];
output.adjustmentData = adjustmentData; UIImage *fullImage = [UIImage imageWithContentsOfFile:self.input.fullSizeImageURL.path];
fullImage = [self.imageFilterService applyFilter:self.currentFilterName toImage:fullImage]; //将转化后的图片存到renderedContentURL中
NSData *jpegData = UIImageJPEGRepresentation(fullImage, 1.0);
BOOL saved = [jpegData writeToURL:output.renderedContentURL options:NSDataWritingAtomic error:nil];
if (saved) {
//回调处理结果给Photos
//注:这里模拟机调试会出现无法显示修改后图片问题,真机调试没有问题
completionHandler(output);
} else {
NSLog(@"An error occurred during save");
completionHandler(nil);
}
// Clean up temporary files, etc.
});
} //点击左上方取消后调用
- (BOOL)shouldShowCancelConfirmation {
//返回YES,则会弹出AlertSheet让用户确认是否取消
//返回NO,则页面直接消失
return NO;
} //shouldShowCancelConfirmation或finishContentEditingWithCompletionHandler:
//之后调用,此函数在后台运行,负责清理临时文件
- (void)cancelContentEditing {
// Clean up temporary files, etc.
// May be called after finishContentEditingWithCompletionHandler: while you prepare output.
} @end

最后的说明:

在新建Photo Extension Target时,系统默认是只为图片添加扩展效果,那么视频呢

你可以在PHSupportedMediaTypes中修改你想支持的媒体类型

 
源码点击 包括未添加扩展的original版本和修改后版本

iOS8中添加的extensions总结(三)——图片编辑扩展的更多相关文章

  1. iOS8中添加的extensions总结(一)——今日扩展

    通知栏中的今日扩展 分享扩展 Action扩展 图片编辑扩展 文件管理扩展 第三方键盘扩展 注:此教程来源于http://www.raywenderlich.com的<iOS8 by Tutor ...

  2. iOS8中添加的extensions总结(四)——Action扩展

    Action扩展 注:此教程来源于http://www.raywenderlich.com的<iOS8 by Tutorials> 1.准备 本次教程利用网站bitly.com进行 bit ...

  3. iOS8中添加的extensions总结(二)——分享扩展

    分享扩展 注:此教程来源于http://www.raywenderlich.com的<iOS8 by Tutorials> 1.准备 这次例子来源于国外的图片分享网站Imgur.com 首 ...

  4. cocos2d-x 中添加显示文字的三种方式 LabelTTF 、LabelBMFont 和 LabelAtlas

    在 cocos2d-x 中有三个类可以在层或精灵中添加文字: LabelTTF LabelBMFont LabelAtlas LabelTTF 直接支持使用 TTF 字库,可以支持全部的中文,但是效率 ...

  5. ZH奶酪:PHP中添加HTML代码的三种方法

    php中添加HTML代码,就是php类型的文件中添加html代码~ 第一种是在HTML中加PHP. 大段大段的html代码中,在各个需要执行php的地方<?php .... ?> 比如 l ...

  6. cocos中添加显示文字的三种方式(CCLabelTTF 、CCLabelBMFont 和CCLabelAtlas)

    CCLabelTTF CCLabelTTF 每次调用 setString (即改变文字)的时候,一个新的OPENGL 纹理将会被创建..这意味着setString 和创建一个新的标签一样慢. 这个类使 ...

  7. 在VS中添加lib库的三种方法

    注意: 1.每种方法也要复制相应的DLL文件到相应目录,或者设定DLL目录的位置,具体方法为:"Properties" -> "Configuration Prop ...

  8. C# 往Datatable中添加新行的步骤

    以一个实例说明 //录入年份绑定 public void YearList(FineUIPro.DropDownList ddlYear) { //年份从15年到当前年//起止年份 ; int yea ...

  9. Spring中添加新的配置表,并对新的配置表进行处理

    实习过程中boss交代的任务(以下出现的代码以及数据只给出小部分,提供一个思路) 目的:Spring中添加新的配置表,并对新的配置表进行处理:替换的新的配置表要友好,同时保证替换前后功能不能发生变化. ...

随机推荐

  1. django 内建标签和过滤器参考

    下面的标签和过滤器参考就是为那些没有 admin 站点的可用的人准备的.由于 Django 是高度可定制的,你的 admin 里的关于标签和过滤器的参考可以认为是最可信的. 内建标签参考 block ...

  2. Android 判断当前网络连接类型

    实际应用开发时,如果存在需要用户获取大量数据的情况,最好是先判断下网络类型,提示用户当前的网络类型,是否需要连接Wifi,etc.(手机流量太贵啦,当然土豪是无视这玩意的, (/ □ \)). 定义网 ...

  3. 简单的猜数字(JAVA版)

    按书上的样例来操作的. 不过,书上提到的BUG,我没有在看下一章时就解决了哈.. 从网上查找的删除数组元素的方法. 其实,将数据结构更改为ARRAYLIST,可能更简单.:) GameHelper.j ...

  4. KEIL C51的XBYTE关键字

    The XBYTE macro allows you to access individual bytes in the external data memory of the 8051. You m ...

  5. Windows平台下主要的内存管理途径

    new / delete   malloc / free    CoTaskMemAlloc / CoTaskMemFree    IMalloc::alloc / IMalloc/free    G ...

  6. SQLite for xamarin

    原文地址:http://www.codeproject.com/Articles/1097179/SQLite-with-Xamarin-Forms-Step-by-Step-guide SQLite ...

  7. redis 基本使用

    Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集(diff ...

  8. OpenWrt+nginx+php安装discuz

    下面这个图片是本次的硬件资源:一个无线路由器的开发板,一个8G的u盘,一条手机的数据线(可以作为串口和供电使用),一条网线,一个USB Hub. <ignore_js_op>        ...

  9. 下载doxygen

    官网首页:http://www.stack.nl/~dimitri/doxygen/index.html 下载页面:http://www.stack.nl/~dimitri/doxygen/downl ...

  10. 转自http://blog.sina.com.cn/daylive——C++ STL map

    Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作! 1.map最基本的构造函数: map<string ...