2016-10-15 3 views
1

一つは、奇妙なランタイムエラーのクラッシュを引き起こしています私はエラーが発生します。スウィフト2〜3移行エラー(libcの++ abi.dylib:タイプNSExceptionのキャッチされない例外で終了)、それはスウィフト2に</p> <p>しなかったとき、私のコントローラの

のlibC++ abi.dylib:NSExceptionタイプのキャッチされない例外で終了

私はすべての私のインターフェイスビルダー要素がフックアップしたことを示すスクリーンショットを添付。

エラーが発生した場所を確認するためにいくつかの実験を行いましたが、おそらくtextViewを設定することに関連すると思われますが、わかりません。

1.)コンソールメッセージがprint("Draw Undo HTML")の後に停止することに注意してください。もともと、私はコンソールメッセージprint("Set attributed text accordingly")を見たことがないので、エラーは回線に関連していると思っていました。私は、エラーがまだ発生しますラインincrementListTextView.attributedText = html.html2AttributedString

をコメントアウトした場合

2)は、それが起こる前に、ちょうど残りのコードが実行されるけれども判明します。非常に奇妙ですが、エラーが最初にその行の周りに表示されるように見えますが、私はTextViewに関連していると思っていますが、何ができるかは不明です。

このシナリオの画像も添付されています。

enter image description here enter image description here

InventoryItemController.Swift(完全なファイル参照)

// 
// InventoryItemController.swift 
// Inventory Counter 
// 
// Created by Joseph Astrahan on 4/3/16. 
// Copyright © 2016 Joseph Astrahan. All rights reserved. 
// 

import UIKit 
import CoreData 

class InventoryItemController: UIViewController, UITextFieldDelegate { 

    var inventoryItem : Inventory? 
    var m_incrementAmount = 0 //amount it will increment everytime you press (+) 
    var m_itemHistory = [Int]() //create array to store undo/redo history 
    var m_undoIndex = 0 


    @IBOutlet weak var inventoryBarCodeLabel: UILabel! 

    @IBOutlet weak var inventoryTotalLabel: UILabel! 

    //List of increments 
    @IBOutlet weak var incrementListTextView: UITextView! 

    //Amount to increment by 
    @IBOutlet weak var incrementAmountTextField: UITextField! 

    @IBOutlet weak var inventoryNameNavItem: UINavigationItem! 

    @IBAction func resetBarButtonAction(_: UIBarButtonItem) { 
     //Present 'Are you sure?' Dialog & Reset Vars. 

     // create the alert in local scope (no need for weak or unowned reference to self in closures) 
     let alert = UIAlertController(title: "Are You Sure?", message: "This will delete all the counts you have done.", preferredStyle: UIAlertControllerStyle.alert) 

     // add an action (button) 
     alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in 
      self.resetTotals() 
     })) 

     alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)) 

     // show the alert 
     self.present(alert, animated: true, completion: nil) 

    } 

    func resetTotals(){ 
     print("resetting...") 
     m_itemHistory = [Int]() 
     m_itemHistory.append(0)//first count is always 0 after reset. 

     m_undoIndex = 0 //set back to 0 

     updateTotal()//update total and save to disk. 

     print("reset!...") 
    } 

    @IBAction func addInventoryButtonAction(_: UIButton) { 

     //When you add you have to first trim the array of everything that was after it. The redo history is now gone. 
     let slice = m_itemHistory[0...m_undoIndex] 
     m_itemHistory = Array(slice)//create new int array from the slice 

     m_incrementAmount = Int(incrementAmountTextField.text!)! 
     m_itemHistory.append(m_incrementAmount) 

     m_undoIndex = m_undoIndex + 1 //add to the index, because undo always happens from last added~ 

     //Update addCount on actual inventoryItem (save to database) 
     updateTotal() 
    } 

    @IBAction func undoButtonAction(_: UIButton) { 
     print("undo") 

     m_undoIndex = m_undoIndex - 1 

     updateTotal() 
    } 

    @IBAction func redoButtonAction(_: UIButton) { 
     print("redo") 

     m_undoIndex = m_undoIndex + 1 

     updateTotal() 
    } 


    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     textField.resignFirstResponder() 
     return true 
    } 

    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { 
     textField.resignFirstResponder() 
     return true 
    } 

    func textFieldDidEndEditing(_ textField: UITextField){ 
     textField.resignFirstResponder() 
    } 

    func dismissKeyboard() { 
     //Causes the view (or one of its embedded text fields) to resign the first responder status. 
     view.endEditing(true) 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Do any additional setup after loading the view. 
     let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(LoginViewController.dismissKeyboard)) 
     self.view.addGestureRecognizer(tap) 

     print("Showing Inventory Item In Question") 
     print(inventoryItem) 
     print("Inventory Name="+(inventoryItem?.name!)!) 

     //inventoryNameLabel.text = inventoryItem.name! 
    } 

    override func viewWillAppear(_ animated: Bool) { 
     super.viewWillAppear(animated) 

     //add observer for contentSize so it centers vertically 
     incrementListTextView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.new, context: nil) 

     //Draw inventory name & barcode 
     inventoryNameNavItem.title = inventoryItem?.name 
     inventoryBarCodeLabel.text = inventoryItem?.barcode 

     //Load first time only when view appears to set default 
     m_itemHistory.append(Int((inventoryItem?.addCount!)!))//add initial value of last 'count' 

     m_undoIndex = 0 //reset to start. 

     updateTotal() //updates total to screen 

     print("Finished UpdateTotal, Should be Showing Screen Now") 

    } 

    func updateTotal(){ 

     //Get the max Index we can count to -1 (because arrays are 0 indexed) 
     let historyTotalMaxIndex = m_itemHistory.count - 1 
     print("historyTotalCheck: HistoryTotalMaxIndex=\(historyTotalMaxIndex)") 

     //Current state of undoIndex 
     print("Init: m_undoIndex =\(m_undoIndex)") 

     //Do checks to prevent out of index bounds. 
     if(m_undoIndex<0){ 
      m_undoIndex = 0 
     } 

     if(m_undoIndex>historyTotalMaxIndex){ 
      m_undoIndex = historyTotalMaxIndex 
     } 

     //After modifying... 
     print("Current: m_undoIndex =\(m_undoIndex)") 


     //Draw HTML 
     var html = "<html><font size=\"5\"><font color=\"#008800\"><center>" 
     for index in 0...m_undoIndex { 
      let increment = m_itemHistory[index] 
      html = html + "+\(increment), " 
     } 
     html = html + "</center></font></font></html>" 

     print(html) 

     print("Draw Undo HTML") 

     incrementListTextView.attributedText = html.html2AttributedString 

     print("Set attributed text accordingly") 

     //get sum of itemHistory 

     let slice = m_itemHistory[0...m_undoIndex] //returns slice of the array we want. 
     let sumArray = Array(slice)//create new int array from the slice 

     print("SumArray Created") 

     let sum = sumArray.reduce(0, +) //now we can sum up that new sliced array 
     inventoryItem?.addCount = sum as NSNumber? //set the add count 

     print("Reduced the Array") 

     //reset html to different now 
     html = "<font size=\"10\"><center>Current: \(inventoryItem?.currentCount!) , <font color=\"#008800\"> Counted: \(inventoryItem?.addCount!)</font></center></font>" 

     inventoryTotalLabel.attributedText = html.html2AttributedString 

     print("save the context") 
     //Save the changes 
     (UIApplication.shared.delegate as! AppDelegate).saveContext() 

    } 

    override func viewWillDisappear(_ animated: Bool) { 
     super.viewWillDisappear(animated) 
     //have to remove or will crash 
     incrementListTextView.removeObserver(self, forKeyPath: "contentSize") 
    } 

    /// Force the text in a UITextView to always center itself. 
    func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutableRawPointer) { 
     let textView = object as! UITextView 
     var topCorrect = (textView.bounds.size.height - textView.contentSize.height * textView.zoomScale)/2 
     topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect; 
     textView.contentInset.top = topCorrect 
    } 



    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 



} 

extension String { 
    var html2AttributedString: NSAttributedString? { 
     guard let data = data(using: .utf8) else { return nil } 
     do { 
      return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue], documentAttributes: nil) 
     } catch let error as NSError { 
      print(error.localizedDescription) 
      return nil 
     } 
    } 
    var html2String: String { 
     return html2AttributedString?.string ?? "" 
    } 
} 
+0

プロジェクトにlibC++。tbdファイルを追加しましたか? –

+0

どうすればいいですか?または私がしたかどうか私はどのように知っていますか? –

+0

これを一度試してみてください。プロジェクト - >一般 - >リンクされたフレームワークとバイナリ - > CLick ON +をクリックし、libC++を検索します。tbd - > add –

答えて

2

こんにちは、私はあなたの問題を発見し、ここで固定。

スウィフト3スタイルのKVOメソッドコールに従わなかった問題 Swift 3以降、メソッドプロトタイプが変更されました。

func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutableRawPointer) { 
     let textView = object as! UITextView 
     var topCorrect = (textView.bounds.size.height - textView.contentSize.height * textView.zoomScale)/2 
     topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect; 
     textView.contentInset.top = topCorrect 
} 

しかし、新しいプロトタイプは以下の通りですによって:

あなたのコードはここにある

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
     let textView = object as! UITextView 
     var topCorrect = (textView.bounds.size.height - textView.contentSize.height * textView.zoomScale)/2 
     topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect; 
     textView.contentInset.top = topCorrect 
    } 

あなたはここに違いを参照していますか?

私はまた、別の問題を発見しました: viewWillAppear関数でobserverを追加しました。それをviewDidLoad関数に移動し、removeObserverコードを移動してfunc didReceiveMemoryWarning()を無効または上書きしてください。ここで

はコードです:

deinit { 
     incrementListTextView.removeObserver(self, forKeyPath: "contentSize") 
    } 

私は、これは非常にあなたを助けることを願っています!

+0

うん、それを修正しました。うわーはこれらの問題を一度も考えなかったでしょう! –

+0

ありがとうございます。 – softninja

関連する問題