web-dev-qa-db-ja.com

割り当て解除中にView Controllerのビューをロードしようとしています... UISearchController

UISearchController' in my UIVIew'sviewDidLoad`を作成するコードがあります。

 self.resultSearchController = ({
        let controller = UISearchController(searchResultsController: nil)
        controller.searchResultsUpdater = self
        controller.searchBar.delegate = self
        controller.dimsBackgroundDuringPresentation = false
        controller.searchBar.sizeToFit()
        controller.hidesNavigationBarDuringPresentation = false //prevent search bar from moving
        controller.searchBar.placeholder = "Search for song"

        self.myTableView.tableHeaderView = controller.searchBar

        return controller

    })()

この閉鎖が終了した直後に、コンソールに次の警告が表示されます。

Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UISearchController: 0x154d39700>)

私が間違っていることを理解できません。 この同様の質問 は実際には私の状況ではありません(少なくともそうは思わない)。何が起こっている?

79
MortalMan

UISearchControllerのビューは、割り当てを解除する前にスーパービューから削除する必要があります。 (バグだと思います)

Objective-C ...

-(void)dealloc { 
    [searchController.view removeFromSuperview]; // It works!
}

スイフト3 ...

deinit {
    self.searchController.view.removeFromSuperview()
}

私はこの問題に数週間苦労しました。 ^^

118
JJH

解決しました!簡単な修正でした。このコードを変更しました

class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController = UISearchController()

これに:

 class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController: UISearchController!

これにより問題が修正されます。

36
MortalMan

これが私のために働いたSwiftバージョンです(JJHの回答に似ています):

deinit{
    if let superView = resultSearchController.view.superview
    {
        superView.removeFromSuperview()
    }
}
20
nijm
class SampleClass: UITableViewController, UISearchBarDelegate {

private let searchController =  UISearchController(searchResultsController: nil)

 override func viewDidLoad() {
        super.viewDidLoad()

        searchController.loadViewIfNeeded() // Add this line before accessing searchController
 }

}
11
harsh_v

ViewDidLoad before UISearchControllerを完全に設定するために行を追加することで、いくつかのソリューションを一緒にハックして、機能するようになりました。

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationItem.rightBarButtonItem = self.editButtonItem()

    if #available(iOS 9.0, *) {
        self.resultSearchController.loadViewIfNeeded()// iOS 9
    } else {
        // Fallback on earlier versions
        let _ = self.resultSearchController.view          // iOS 8
    }
    self.resultSearchController = ({
        let controller = UISearchController(searchResultsController: nil)
        controller.searchResultsUpdater = self
        controller.dimsBackgroundDuringPresentation = false
        controller.searchBar.sizeToFit()

        self.tableView.tableHeaderView = controller.searchBar

        return controller
    })()

    self.tableView.reloadData()

}
10
Derek

私のために働いたSwift 2.2バージョン

deinit {
    self.searchController?.view.removeFromSuperview()
}

役立つと思います!

7
Milos Mandic

Swift2では、明らかなバグが原因で同じエラーメッセージが表示されました。

let alertController = UIAlertController(title: "Oops",
    message:"bla.", preferredStyle: UIAlertControllerStyle.Alert)

alertController.addAction(UIAlertAction(title: "Ok", 
     style: UIAlertActionStyle.Default,handler: nil))

self.presentViewController(alertController, animated: true, completion: nil)

自分からの愚かなコピーエラーのため、self.presentViewController行を含めていませんでした。これにより、同じエラーが発生しました。

7
Vincent

私はこのように働いています

func initSearchControl(){

        searchController = UISearchController(searchResultsController: nil)

        if #available(iOS 9.0, *) {
            searchController.loadViewIfNeeded()
        } else {
            let _ = self.searchController.view
        }

        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        definesPresentationContext = true
        tableView.tableHeaderView = searchController.searchBar
        searchController.searchBar.sizeToFit()
    }

searchController.loadViewIfNeeded()は問題を解決しますが、searchControllerを初期化した後に呼び出す必要があります

2
mehmetsen80

viewDidLoad()で検索コントローラーを作成し、その検索バーをナビゲーションアイテムのタイトルビューとして設定しても、検索コントローラーへの強い参照が作成されないため、割り当てが解除されます。

したがって、これを行う代わりに:

override func viewDidLoad() {
    super.viewDidLoad()
    // Create search controller
    let searchController = UISearchController(searchResultsController: nil)
    // Add search bar to navigation bar
    navigationItem.titleView = searchController.searchBar
    // Size search bar
    searchController.searchBar.sizeToFit()
}

これを行う必要があります:

var searchController: UISearchController!

override func viewDidLoad() {
    super.viewDidLoad()
    // Create search controller
    searchController = UISearchController(searchResultsController: nil)
    // Add search bar to navigation bar
    navigationItem.titleView = searchController.searchBar
    // Size search bar
    searchController.searchBar.sizeToFit()
}
2
Niels

バグではありません。 ViewControllerを表示せずに作成しないようにする必要があるようです。したがって、SomeViewController()またはlet variable: SomeViewControllerの後に、このself.presentViewController(yourViewController ...etc)のようなものを呼び出す必要があります。そうしないと、このView Controllerの割り当てが解除されるときにこの警告が表示されます。

1
Nikolai Ischuk

Derekの回答を使用しましたが、少し変更する必要がありました。 resultSearchControllerが定義される前にloadViewIfNeeded()の呼び出しが発生したため、提供された回答がクラッシュしました。 (私の宣言は

var resultSearchController: UISearchController!

)。だから私は後でそれを動かしただけでうまくいきました。

呼び出しを完全に省略した場合、バグは残ったため、答えの重要な部分であると確信しています。 iOS 8でテストできませんでした。

1
Michael L. Mehr

ビューが遅延ロードされているように見えます。コントローラーを割り当てて表示しない場合、ビューはロードされません。この場合、コントローラーの割り当てが解除されると、この警告が表示されます。一度表示するか、loadViewIfNeed()メソッドを呼び出すか、 'let _ = controller.view'を使用してビューを強制的にロードし、この警告を回避します。

1
david

私はパーティーに少し遅れましたが、ここに私の解決策があります:

var resultSearchController: UISearchController!

override func viewDidLoad()
{
    super.viewDidLoad()

    self.resultSearchController = ({
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        searchController.searchBar.sizeToFit()
        return searchController
    })()

    self.tableView.tableHeaderView = self.resultSearchController.searchBar
    self.tableView.reloadData()
}

私はそれがあなたのために働くことを望みます。

0
titusmagnus