你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 理解 iOS 8 中的 Photo Editing Extension

理解 iOS 8 中的 Photo Editing Extension

編輯:IOS開發基礎

(原文:Understanding Photo Editing Extensions in iOS 8 作者:Joyce Echessa 譯者:X140Yu)
Photo Editing Extension 允許用戶在 Photos 應用裡使用第三方應用編輯照片或視頻。在此之前,用戶不得不先在相機應用裡拍攝照片,然後切換到照片編輯應用裡編輯,或者必須從相冊裡導入照片。現在,這步應用間的切換可以被省略了,用戶能不從照片應用切換出去就能編輯照片了。在 Photo Editing Extension 裡編輯完成並確認修改後,Photos 應用裡的圖片也會獲得同樣的調整。照片的初始版本也保存下來,這樣用戶可以隨時恢復在擴展應用裡做出的修改。

我們一起來看看怎樣制作一個 Photo Editing Extension。由於我們的關注點在創建應用程序擴展而不是寫一個完整的應用,我已經創建了一個你們可以下載並且一路跟著做的上手項目。

PhotoEditingExtension.jpg

這是一個識別圖片上的臉然後自動給臉部打上馬賽克的簡單應用。在沒有識別出臉的情況下,圖片是不會被更改的。這將會成為我們擴展應用的母應用。擴展應用必須是母應用的一部分,不可能只有一個單單的擴展應用。如果想更多地了解一下擴展應用是什麼原理,你可以浏覽我們之前寫的關於Today extension的一篇文章。

我把圖片處理的代碼放在了一個框架裡。這樣我就可以在擴展應用和母應用裡使用同一份代碼。當你創建了一個應用擴展,它必須是它自己的 target,所以如果你想在主程序和擴展程序裡重用這些代碼,你必須把公共的代碼嵌入進框架中去。在下載的程序中,我已經創建了框架。如果你想了解如何創建,閱讀一下上一段提到的文章。

right_hook.png

我們將創建一個對於其它應用也可以使用這種功能的擴展應用。

創建擴展應用

一開始,在項目導航中選擇 FaceBlur project,然後選擇 Editor > Add Target。選擇 iOS > Application Extension > Photo Editing Extension 然後點擊 Next。

extensions.png

把 Product Name 設置成 FaceBlur Filter,語言選擇 Swift,其它保持不變。

name_extension.png

當詢問你時候是否啟用新解決方案的時候,選擇 Activate。

activate_scheme.png

在項目導航器裡有一個標有 FaceBlur Filter 的新組。它包含三個文件 - PhotoEditingViewController.swift, MainInterface.storyboard 和 Info.plist。

在 MainInterface.storyboard 中,視圖構建器是我們在之前 iOS 版本中使用過的,它沒有自適應布局(adaptive layout)。View controller 是 iPhone 大小,並且在視圖構建器的底部沒有 Size Class 的控制區域。但是我們想創建一個可以適應各種不同尺寸屏幕的應用擴展程序。

在 Document Outline 中選擇 Photo Editing View Controller。在 File Inspector 中,把 Use Size Classes 打勾,並在彈出的窗口中選擇確認。

size_class.png

在 storyboard 中刪掉這個 View Controller,從 Object Library 裡拽一個新的 View Controller。正如你所見,它將是一個接近正方形的形狀而不是一個特定型號設備的形狀。

在 Identity inspector,把這個 View Controller 的類設置成 PhotoEditingViewController,並且在 Attributes Inspector 裡把 Is Initial View Controller 打勾。

在 Document Outline 裡,選中 View ,在 Attributes Inspector 裡把它的顏色設置成 Dark Gray Color。

向 View 的底部拽兩個按鈕。各放在左右。把它們的顏色設置成白色,並把左右按鈕的標題分別設置成 Cancel 和 Add Filter。現在你的 View 應該跟下圖的 View 差不多。

initial_view.png

選中 Cancel 按鈕,向它的左側和底部添加約束。

cancel_pins.png

選中 Add Filter 按鈕,向它的右側和底部添加約束。

add_filter_pins.png

向主 View 中拽一個 Image View。調整它的大小,來讓它的頂部,左部和右部邊緣能夠緊貼 View 的邊緣。拖住它的底部一直向下拉,直到在靠近按鈕的時候出現了藍色的導航線再停下。保持 Image View 為選中狀態,選擇 Pin 菜單,把 Constrain to margins 取消。把頂部,左側和右側的約束設置成0,對於底部的約束,單擊底部約束下拉菜單,選擇 Bottom Layout Guide。添加這四個約束。

image_view_pins.png

按住 Control 鍵,同時從 Image View 到 PhotoEditingViewController 類拖動鼠標,為 Image View 添加一個 ouelet(使用 Assistant editor,把左右兩個文件分別調整為 storyboard 和 類文件)。把 outlet 命名為 imageView。為底部的兩個按鈕分別添加 outlet,命名為 cancelButton 和 addFilterButton。

按住 Control 鍵,同時從 Cancel 按鈕到 PhotoEditingViewController 類拖動鼠標,把 Connection 改為 Action。把 Type 設置成 UIButton,命名它為 cancel。對於 Add Filter 也一樣,把這個 Action 命名為 addFilter。你現在類應該擁有如下的 outlets 和 actions。

    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var cancelButton: UIButton!
    @IBOutlet weak var addFilterButton: UIButton!
   
    @IBAction func cancel(sender: UIButton) {
    }

    @IBAction func addFilter(sender: UIButton) {
    }

PhotoEditingViewController 類遵從了 PHContentEditingController 協議,在這個類裡會有幾個協議方法的實現。

  • startContentEditingWithInput(contentEditingInput:, placeholderImage:) - 這個方法在 View Controller 出現之前並且 asset 可以被編輯時被調用。它被傳入兩個對象 - 一個 PHContentEditingInput 實例(要被編輯的 asset)和一個 UIImage 實例(可能是原本的圖像或者根據下面提到的 canHandleAdjustmentData(adjustmentData:) 方法的返回值得到的被編輯過的圖像)。

  • finishContentEditingWithCompletionHandler(completionHandler:) - 這個方法在圖像被編輯以後被調用。一個存儲編輯和描述編輯調整的數據的 PHContentEditingOutput 實例會被創建。這個實例會被傳入 completionHandler。

  • cancelContentEditing – 這個方法在用戶取消編輯時被調用。你應當在這裡清理不需要的資源。

  • canHandleAdjustmentData(adjustmentData:) – 如果你的擴展應用能對之前的編輯生效,那這個方法返回 true。

我們將處理以上這幾個方法。

先導入 ImageProcessingKit 框架。在文件添加以下代碼。

import ImageProcessingKit

在類中添加以下兩個變量。

var processedImage: UIImage?
let processor = ImageProcessor()

按照以下形式修改 addFilter()。

@IBAction func addFilter(sender: UIButton) {
    if let input = input {
        processedImage = processor.processImage(input.displaySizeImage)
        imageView.image = processedImage
    }
}

這裡把顯示的照片改成了編輯後的照片而並沒有把改變應用於圖片。如果一個擴展應用真的提供了許多種濾鏡,那麼這裡可以讓用戶在選擇確定之前,來嘗試多種不同的濾鏡。

按照下面的形式修改 cancel(),當用戶點擊 Cancel 按鈕時,把 Image View 設置成原來的圖片。

@IBAction func cancel(sender: UIButton) {
    if let input = input {
        imageView.image = input.displaySizeImage
        processedImage = nil
    }
}

按照以下形式修改 startContentEditingWithInput()。

func startContentEditingWithInput(contentEditingInput: PHContentEditingInput?, placeholderImage: UIImage) {
    input = contentEditingInput
    if let input = contentEditingInput {
        imageView.image = input.displaySizeImage
    }
}

當編輯模式將要啟動時,這個方法能夠獲取輸入的圖片並把它顯示在 Image View 裡。

按照以下形式修改 finishContentEditingWithCompletionHandler() 。

func finishContentEditingWithCompletionHandler(completionHandler: ((PHContentEditingOutput!) -> Void)!) {
       
    if input == nil {
        self.cancelContentEditing()
        return
    }
       
    dispatch_async(dispatch_get_global_queue(CLong(DISPATCH_QUEUE_PRIORITY_DEFAULT), 0)) {
        let contentEditingOutput = PHContentEditingOutput(contentEditingInput: self.input)
           
        let archiveData = NSKeyedArchiver.archivedDataWithRootObject("Face Blur")
        let identifier = "com.appcoda.FaceBlur.FaceBlur-filter"
        let adjustmentData = PHAdjustmentData(formatIdentifier: identifier, formatVersion: "1.0", data: archiveData)
        contentEditingOutput.adjustmentData = adjustmentData
           
        if let path = self.input!.fullSizeImageURL.path {
            var image = UIImage(contentsOfFile: path)!
            image = self.processor.processImage(image)
               
            let jpegData = UIImageJPEGRepresentation(image, 1.0)
            var error: NSError?
               
            let saveSucceeded = jpegData.writeToURL(contentEditingOutput.renderedContentURL, options: .DataWritingAtomic, error: &error)
            if saveSucceeded {
                completionHandler(contentEditingOutput)
            } else {
                println("Save error")
                completionHandler(nil)
            }
        } else {
            println("Load error")
            completionHandler(nil)
        }
    }
}

首先,我們檢查一下是否有圖片被選中,如果沒有,什麼都不做,直接 return。如果有,我們啟動一個異步 block 來做修改的工作。

接著,通過傳進來的對象創建了一個 PHContentEditingOutput 實例。我們又創建了一個 PHAdjustmentData 實例。隨著修改的進行,調整的數據也會被一路保存下來。PHAdjustmentData 對象提供了一個你可以用來重構編輯的“菜譜”,如果你的擴展應用提供了多種不同的濾鏡,這個對象能把應用濾鏡的順序給保存下來,所以它們可以隨時恢復到之 前某一個已編輯圖片的狀態。這個數據需要一個獨一無二的標識和一個版本號碼。對於標識,我們把域名標識倒過來來表示,為了保證它的獨一無二性。版本號碼可 以幫助你擴展應用後面的版本不把你先前版本不同的給歸檔。

然後,我們把需要修改的整張圖片從磁盤中載入並應用濾鏡。然後,把這個數據轉換成 JPEG 格式,重新寫入磁盤。如果成功了,completion handler 會被調用,並且被傳入修改後的對象。

為了運行此擴展,先要檢察解決方案是不是被設置成 FaceBlur Filter。運行工程,會彈出一個窗口讓你選擇通過哪個應用來運行。我們選擇 Photos。

run_extension.png

Photos 應用會啟動。選擇一張圖片並進入編輯模式。在底部的右下角,會有一個內含三個點的圓形圖標。

show_extensions.png

單擊它來激活第三方編輯圖片的應用程序擴展。

available_extensions.png

選擇 FaceBlur 然後點擊 Add Filter。如果檢測出了臉,這張圖片會被處理並且被編輯。你可以選擇取消修改或者選擇確認來保存這些修改。

360桌面截圖20150121143104.jpg360桌面截圖20150121143125.jpg

在選擇確定以後,會返回 Photos 應用,這裡將顯示編輯過後的圖像。

360桌面截圖20150121143329.jpg

你也可以在照片的編輯模式下按 Revert 來取消之前用濾鏡做的修改。

revert.png

總結

我們已經了解了如何創建一個簡單的照片編輯應用擴展了。你也可以把它變得更復雜:創建一個可以處理先前編輯的應用擴展。我希望這篇博文能在你處理你自己的應用擴展時,給你一個良好的參照。如果你想得到關於應用擴展的更多信息,一定要看看 App Extension Programming Guide。

為了讓你有個參考,你可以下載整個 Xcode 項目。

注意:當然運行這個應用擴展時,你可能會注意到一些錯誤還有 CoreMedia 的許可信息。這些在 Xcode 6 的 GM 版本發布後開始出現,所以在以後的版本可能不會出現,或者在 iOS 8 將來的版本會被修復。但是現在來看,除了這些問題,整個應用擴展運行良好。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved