

カメラロールから選んだ画像をimageViewに描写している状態で、ボタンをタップするとセピア色や白黒にフィルターをかける機能を実装しています。  
さらに、ユーザがUISliderを左右にドラッグしてセピア色や白黒の濃淡具合を選択できるような機能を実装したいと思い  
独学でコーディングしたのですが、ここから先がわかりません。  
追記：前回回答頂いたコードを元に、今回コーディングさせて頂きました。  
カメラロールで画像を選び、フィルター用のボタンをタップした後、  
UISliderを左右にドラッグするとエラーとなります。  
エラー内容は、下記の通りです。

[code]

    import UIKit
    class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        @IBOutlet var mainImageView: UIImageView!
        @IBAction func pickImageFromLibrary() {
            if UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary) {
                let controller = UIImagePickerController()
                controller.delegate = self
                controller.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
                self.presentViewController(controller, animated: true, completion: nil)
            }
        }
        override func viewDidLoad() {
            super.viewDidLoad()
            let slider = UISlider()
            slider.frame = CGRect(x: 80, y: 380, width: 200, height: 40)
            slider.minimumValue = 0.0
            slider.maximumValue = 1.0
            slider.addTarget(self, action: #selector(ViewController.sepiaFilter(_:slider:)), forControlEvents: UIControlEvents.ValueChanged)
            slider.addTarget(self, action: #selector(ViewController.monoFilter(_:slider:)), forControlEvents: UIControlEvents.ValueChanged)
            self.view.addSubview(slider)
        }
        func imagePickerController(picker: UIImagePickerController,
        didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
            self.mainImageView.image = image
            (self.view.viewWithTag(1) as! UIButton).setImage(image, forState: .Normal)
            (self.view.viewWithTag(2) as! UIButton).setImage(sepiaFilter(image, slider: UISlider()), forState: .Normal)
            (self.view.viewWithTag(3) as! UIButton).setImage(monoFilter(image, slider: UISlider()), forState: .Normal)
            picker.dismissViewControllerAnimated(true, completion: nil)
        }
        @IBAction func sepiaFilter(sender: UISlider) {
            guard let image = self.mainImageView.image else {
                fatalError("something is wrong with mainImageView...")
            }
            self.mainImageView.image = sepiaFilter(image, slider: sender)
        }
        func sepiaFilter(image: UIImage, slider: UISlider) -> UIImage {
            guard let sepiaFilter = CIFilter(name: "CISepiaTone") else {
                fatalError("something is wrong with CIFilter...")
            }
            sepiaFilter.setDefaults()
            guard let ciImage: CIImage = CIImage(image: image) else {
            print("cannot create CIImage...")
            return image
            }
            posterFilter.setValue(ciImage, forKey: kCIInputImageKey)
            posterFilter.setValue(slider.value, forKey: "inputLevels")
            if let outputImage = posterFilter.valueForKey("outputImage") as? CIImage {
                let manipulatedImage = UIImage(CIImage: outputImage)
                return manipulatedImage
            }
            return image
        }
        @IBAction func monoFilter(sender: UISlider) {
            guard let image = self.mainImageView.image else {
                fatalError("something is wrong with mainImageView...")
            }
            self.mainImageView.image = monoFilter(image, slider: sender)
        }
        func monoFilter(image: UIImage, slider: UISlider) -> UIImage {
            guard let monoFilter = CIFilter(name: "CIColorControls") else {
                fatalError("something is wrong with CIFilter...")
            }
            monoFilter.setDefaults()
            guard let ciImage: CIImage = CIImage(image: image) else {
                print("cannot create CIImage...")
                return image
            }
            monoFilter.setValue(ciImage, forKey: kCIInputImageKey)
            monoFilter.setValue(slider.value, forKey: "inputSaturation")
            if let outputImage = monoFilter.valueForKey("outputImage") as? CIImage {
                let manipulatedImage = UIImage(CIImage: outputImage)
                return manipulatedImage
            }
            return image
        }
        @IBAction func filterTapped(sender:UIButton) {
            switch sender.tag {
            case 1:
                mainImageView.image = (self.view.viewWithTag(1) as! UIButton).imageView?.image
            case 2:
                mainImageView.image = (self.view.viewWithTag(2) as! UIButton).imageView?.image
            case 3:
                mainImageView.image = (self.view.viewWithTag(3) as! UIButton).imageView?.image
            default:
                break
            }
        }
    }
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/PJYiC.png)](https://i.stack.imgur.com/PJYiC.png)

[![画像の説明をここに入力](https://i.stack.imgur.com/M5JUk.png)](https://i.stack.imgur.com/M5JUk.png)

[![画像の説明をここに入力](https://i.stack.imgur.com/jqCqt.png)](https://i.stack.imgur.com/jqCqt.png)

[![画像の説明をここに入力](https://i.stack.imgur.com/0YtdD.png)](https://i.stack.imgur.com/0YtdD.png)

ビルド前のエラーマークはない状態でした。  
また、storyboard上では、UISliderを作成をせずに、コードでUISliderを作成している状態です。  
エラーの内容や文法上おかしな点などございましたら、ご教示いただけますでしょうか。


CC BY-SA 3.0
2016-08-04T07:11:28.323
28055
2016-08-04T09:40:05.630
14329
question
swift xcode swift2 xcode7
1つのUISliderで複数のフィルターの色相変化をさせるには(前回、前々回の続き)


以前の質問で指摘された通り、UIControlに応答するメソッドの形式は、`func doSomething()`、`func
doSomething(sender: UIButton)`、`func doSomething(sender: UIButton, forEvent
event:
UIEvent)`のいずれかである必要があります。そして、最初の引数は応答するオブジェクト自身（ここではUISlider）、２番目の引数はイベントオブジェクト（タッチの情報などが含まれる）が渡されると決まっています。あなたのコードではUISliderを操作した時に

[code]

    func sepiaFilter(image: UIImage, slider: UISlider) -> UIImage
    
[/code]

を呼ぶように指定している（以下のコード）

[code]

    slider.addTarget(self, action: #selector(ViewController.sepiaFilter(_:slider:)), forControlEvents: UIControlEvents.ValueChanged)
    
[/code]

ので、スライダを動かした時は`func sepiaFilter(image: UIImage, slider: UISlider) ->
UIImage`が呼ばれます。  
この時、最初の引数には先述の通り、UISliderのオブジェクトが入ります。それをこの行で

[code]

    guard let ciImage: CIImage = CIImage(image: image) else {
    
[/code]

CIImageを生成するイニシャライザに渡しているので、UIImageのオブジェクトを渡すべきところにUISliderのオブジェクトを渡しているのでクラッシュしています。  
この場合の`unrecognized
selector...`はUIImageの`CGImage`プロパティにCIImageのイニシャライザがアクセスしようとしたが、UISliderのオブジェクトが渡されたので存在しないプロパティ（＝メソッド）にアクセスして発生しています。

やりたいことはおそらく、スライダーの操作ではもう一つの`func sepiaFilter(sender:
UISlider)`が呼ばれて、その中から`func sepiaFilter(image: UIImage, slider: UISlider) ->
UIImage`メソッドを呼ぶ、ということでしょうから、以下の行の

[code]

    slider.addTarget(self, action: #selector(ViewController.sepiaFilter(_:slider:)), forControlEvents: UIControlEvents.ValueChanged)
    slider.addTarget(self, action: #selector(ViewController.monoFilter(_:slider:)), forControlEvents: UIControlEvents.ValueChanged)
    
[/code]

`#selector(...)`の部分を修正すれば正しく動くようになると思います。


CC BY-SA 3.0
2016-08-04T09:40:05.630
28060
2016-08-04T09:40:05.630
5519
28055
answer