
Thread 1:signal SIGABRTの解決方法の考察
備忘録の為に非常に雑に、非常に自分勝手に書いてます。あとで暇だったら整理します
モノクロを押せばThread 1:signal SIGABRT
成功したらこんな感じ
謎のエラーThread 1:signal SIGABRT、どこでバグってるのか突き止める全ての方法
手順としては、viewdidlordから一つずつ順を追っう。その際、エラーが出ないログは消していく。
2、エラーが出てる場所っぽいところでブレークポイントをつけて一つずつ進めてく
3、一つづつ進めていくとエラーが出て止まってるところで、処理が弾かれてappデリゲートのところでThread 1:signal SIGABRTが出る
appデリゲートのところでThread 1:signal SIGABRTへ飛んだその、そのポイントが、まさしくバグってるところである。
なぜ、最初っから、ここに
エラーが出てるよと教えてくれないのか。不親切である。いや、自分が馬鹿である。分かって当たり前だろと言ってるのか。?
エラーコード
import UIKit
class ViewController: UIViewController , UIImagePickerControllerDelegate, UINavigationControllerDelegate {
@IBOutlet weak var imageView: UIImageView!
// var originalImage: UIImage?
//画像を編集するために画像を保持しておく変数
var originalImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func handleTap(sender: UITapGestureRecognizer) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
let ipc:UIImagePickerController = UIImagePickerController();
ipc.delegate = self
//sourceTypeってなんすか??
ipc.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
//presentViewControllerってなんすか??
self.presentViewController(ipc, animated: true, completion: nil)
}
}
//ImagePickerで画像が選択されたときに呼ばれる
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if info [UIImagePickerControllerOriginalImage] != nil {
//選択した画像を UIImageViewに設定する
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
//加工用にメンバ変数に保持
originalImage = info[UIImagePickerControllerOriginalImage]as? UIImage
}
//Imageviewを閉じる
picker.dismissViewControllerAnimated(true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// モノクロボタンが押された時に呼ばれる
@IBAction func pushedMonochrome(sender: UIButton) {
guard let image = imageView.image else {
return
}
let monochroImage = monochromeImages(image)
imageView.image = monochroImage
originalImage = monochroImage
}
//引数のUIImage の画像をモノクロ化した UIImageを返す
func monochromeImages (srcImage: UIImage) -> UIImage {
//どうしてpushedMonochromeの中に処理を書かないのだろう
//UIImageからCIImageを作る
let ciImage: CIImage = CIImage(image:srcImage)!;
//コンテキストを作成する
let ciContext:CIContext = CIContext(options: nil)
//フィルターを作成する
let ciFilter:CIFilter = CIFilter(name: "CIMinimumComponent")!
CIFilter.setValue(ciImage, forKey: kCIInputImageKey)
//フィルターを通した画像を生成する
let cgimg:CGImageRef = ciContext.createCGImage(ciFilter.outputImage!, fromRect: ciFilter.outputImage!.extent)!
//CGImageRefからUIImageを作成して返す
return UIImage(CGImage: cgimg, scale: 1.0, orientation: UIImageOrientation.Up)
}
// スライダーの値が変わった時に呼ばれる
@IBAction func valueChanged(sender: UISlider) {
}
// 保存ボタンが押された時に呼ばれる
@IBAction func save(sender: UIButton) {
}
}
正しいコード
import UIKit
class ViewController: UIViewController , UIImagePickerControllerDelegate, UINavigationControllerDelegate {
@IBOutlet weak var imageView: UIImageView!
// var originalImage: UIImage?
//画像を編集するために画像を保持しておく変数
var originalImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func handleTap(sender: UITapGestureRecognizer) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
let ipc:UIImagePickerController = UIImagePickerController();
ipc.delegate = self
//sourceTypeってなんすか??
ipc.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
//presentViewControllerってなんすか??したからビューだす
self.presentViewController(ipc, animated: true, completion: nil)
}
}
//ImagePickerで画像が選択されたときに呼ばれる
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if info [UIImagePickerControllerOriginalImage] != nil {
//選択した画像を UIImageViewに設定する
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
//加工用にメンバ変数に保持
originalImage = info[UIImagePickerControllerOriginalImage]as? UIImage
}
//Imageviewを閉じる
picker.dismissViewControllerAnimated(true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// モノクロボタンが押された時に呼ばれる
@IBAction func pushedMonochrome(sender: UIButton) {
guard let image = imageView.image else {
return
}
let monochroImage = monochromeImages(image)
imageView.image = monochroImage
originalImage = monochroImage
}
//引数のUIImage の画像をモノクロ化した UIImageを返す
func monochromeImages (srcImage: UIImage) -> UIImage {
//どうしてpushedMonochromeの中に処理を書かないのだろう
//UIImageからCIImageを作る
let ciImage: CIImage = CIImage(image:srcImage)!;
//コンテキストを作成する
let ciContext:CIContext = CIContext(options: nil)
//フィルターを作成する
let ciFilter:CIFilter = CIFilter(name: "CIMinimumComponent")!
//ここでエラーになる↓
ciFilter.setValue(ciImage, forKey: kCIInputImageKey)
//フィルターを通した画像を生成する
let cgimg:CGImageRef = ciContext.createCGImage(ciFilter.outputImage!, fromRect: ciFilter.outputImage!.extent)!
//CGImageRefからUIImageを作成して返す
return UIImage(CGImage: cgimg, scale: 1.0, orientation: UIImageOrientation.Up)
}
// スライダーの値が変わった時に呼ばれる
@IBAction func valueChanged(sender: UISlider) {
}
// 保存ボタンが押された時に呼ばれる
@IBAction func save(sender: UIButton) {
}
}
ブレークポイントを指定しないで止めないでエラー時点までのすべてのログを見る
一つ一つのログを順を追ってみる
ViewdidLodの時に出たログ。これは動いてるから右下のゴミ箱ボタンでログを消す
viewをタップした時のログ、ここまで動いてるからこれも消す
viewに写真が出たログ
モノクロボタンを押した瞬間に出たログ
ここでエラーになってるから、ここらへんのログがエラーの原因
ログの一番上のコードを読む。
2016-10-03 12:10:32.687 ImageProcessing[29842:718409] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<CIFilter 0xc8521c> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key inputImage.'
*** First throw call stack:
なんとなく
key valu
key inputImage
というログに目をつけた。このコードから、ソースコード上のkey valu とかkey inputImageとかそんな感じの文字探す
見つけた、ここらへんだ
//引数のUIImage の画像をモノクロ化した UIImageを返す
func monochromeImages (srcImage: UIImage) -> UIImage {
//どうしてpushedMonochromeの中に処理を書かないのだろう
//UIImageからCIImageを作る
let ciImage: CIImage = CIImage(image:srcImage)!;
//コンテキストを作成する
let ciContext:CIContext = CIContext(options: nil)
//フィルターを作成する
let ciFilter:CIFilter = CIFilter(name: "CIMinimumComponent")!
//↓怪しい怪しい怪しい怪しい怪しい怪しい
"CIFilter.setValue(ciImage, forKey: kCIInputImageKey)"
//フィルターを通した画像を生成する
let cgimg:CGImageRef = ciContext.createCGImage(ciFilter.outputImage!, fromRect: ciFilter.outputImage!.extent)!
//CGImageRefからUIImageを作成して返す
return UIImage(CGImage: cgimg, scale: 1.0, orientation: UIImageOrientation.Up)
}
// スライダーの値が変わった時に呼ばれる
@IBAction func valueChanged(sender: UISlider) {
}
// 保存ボタンが押された時に呼ばれる
@IBAction func save(sender: UIButton) {
}
}
そもそも、モノクロボタンを押した瞬間に止まったので、ここら辺でエラーが起こってるんだろうと予測はしていた。でも、まだこの段階でなぜここでエラーになるのかわかってない
88行目、ここら辺で止める矢印を置いておく。一つ一つ処理を純追ってみていく
1個目動いてる
2個目、93行目、動いてる
95行め動いてる。はい、次で止まります
//ここでエラーになる↓
CIFilter.setValue(ciImage, forKey: kCIInputImageKey)
はい、ここまでは来ていました。ここで次へ行くと死にます。つまり、ここから先の処理に行けない。このコードが間違ってるよと言われました。なぜ、どこが間違っているのでしょうか。よく見てみる
ここら辺をよく見て発見する
//UIImageからCIImageを作る
let ciImage: CIImage = CIImage(image:srcImage)!;
//コンテキストを作成する
let ciContext:CIContext = CIContext(options: nil)
//フィルターを作成する
let ciFilter:CIFilter = CIFilter(name: "CIMinimumComponent")!
//ここでエラーになる↓
CIFilter.setValue(ciImage, forKey: kCIInputImageKey)
//フィルターを通した画像を生成する
let cgimg:CGImageRef = ciContext.createCGImage(ciFilter.outputImage!, fromRect: ciFilter.outputImage!.extent)!
バカな、型に代入しているじゃないか、俺は
//フィルターを作成する
let ciFilter:CIFilter = CIFilter(name: "CIMinimumComponent")!
//ここでエラーになる↓
CIFilter.setValue(ciImage, forKey: kCIInputImageKey)
型にアクセスなんかできない。ちゃんと変数に代入させてアクセス
//フィルターを作成する
let ciFilter:CIFilter = CIFilter(name: "CIMinimumComponent")!
//ここでエラーになる↓
ciFilter.setValue(ciImage, forKey: kCIInputImageKey)
詳しくはteratailにも質問した
https://teratail.com/questions/50050