यह डील-डॉकिंग करते समय किसी व्यू कंट्रोलर के दृश्य को लोड करने का प्रयास कर रहा है ... UISearchController


80

मेरे पास कोड है जो एक 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>)

मुझे वह नहीं मिला जो मैं गलत कर रहा हूं। यह समान प्रश्न वास्तव में मेरी स्थिति नहीं है (कम से कम मुझे ऐसा नहीं लगता)। क्या हो रहा है?


xkcd.com/583 ठीक है अगर मैं अपनी तालिका कुलपति में फेंक दूं viewDidLoad()। पूरे वीसी सोर्स लिस्टिंग और बी) सहित अनुशंसा करें कि यह सुनिश्चित करना कि त्रुटि वास्तव में कहां और कब हो रही है।
बेसजेन

इसके अलावा और अधिक शोध करें जैसे: stackoverflow.com/questions/31006045/… जिसमें एक ही त्रुटि है
बेसजेन

तो, मैंने एक स्विफ्ट प्रोजेक्ट बनाया, क्या सब कुछ progrmatically है, कोई स्टोरीबोर्ड नहीं है, और मुझे कोई समस्या नहीं है, क्या यह एक स्टोरीबोर्ड का मुद्दा है जो आप कर रहे हैं, शायद, मुझे नहीं पता, लेकिन मुझे लगता है कि आप स्टोरीबोर्ड का उपयोग कर रहे हैं, है ना? जब मैं प्रोग्रामेटिक रूप से कहता हूं, तो मेरा मतलब है कोई nibs, कोई स्टोरीबोर्ड, सभी कोड और यह ठीक काम करता है
लैरी अचार

@ बेससेन मैंने पहले })()और बाद में एक ब्रेकपॉइंट सेट किया })()। बंद होने के बाद त्रुटि हो जाती है। मेरे पास ए है UIViewController, ए नहीं tableViewController
मॉर्टेलमैन

@Larcerax मैं एक स्टोरीबोर्ड है। इसमें केवल एक नेविगेशन नियंत्रक और एक UIViewController (वे जुड़े हुए हैं।)
मॉर्टालमैन

जवाबों:


119

डील-डॉक करने से पहले UISearchController का दृश्य अपने पर्यवेक्षक से हटा दिया जाना चाहिए। (लगता है कि यह एक बग है)

उद्देश्य सी...

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

स्विफ्ट 3 ...

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

मैं कुछ हफ़्ते के लिए इस मुद्दे से जूझता रहा। ^ ^


1
यह वास्तव में अजीब है ... लेकिन इसने मेरे लिए भी चाल चली। मुझे लगता है कि यह वास्तव में एक बग है।
मिहाई फ्रेटु

22
मेरे पास एक ही समस्या थी जिसमें UISearchControlerमैं एक आवंटित कर रहा था -viewDidLoad। यह निश्चित रूप से एक बग है - यदि UISearchControllerइसका दृश्य लोड होने से पहले ही इसे हटा दिया जाता है, तो यह चेतावनी दिखाई देगी। यदि मैं खोज फ़ील्ड में टैप करता हूं (जिससे दृश्य लोड हो रहा है), तो यह प्रकट नहीं होता है। तो मेरे में dealloc, मैं कहता हूं [self.searchController loadViewIfNeeded](आईओएस 9 में नया),
लीह्रो

4
@ लीहरो की टिप्पणी मेरे लिए जवाब है। यह बाहर आयाif #available(iOS 9.0, *) { self.searchController?.loadViewIfNeeded() }
टिम

6
मैं @ लीहरो की टिप्पणी से जोड़ता हूं कि डीलॉक में ऐसा करने की कोई आवश्यकता नहीं है, आप इसके बजाय viewDidLoad में loadViewIfNeeded कर सकते हैं।
क्फ्फौ

@Leehro और @Clafou के लिए धन्यवाद ... कॉल जोड़ना [self.searchController loadViewIfNeeded];( ओबज -सी) वह उत्तर है जिसने मेरे कोड में समस्या को हल किया।
andrewbuilder

36

हल किया! यह एक साधारण तय था। मैंने यह कोड बदल दिया है

class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController = UISearchController()

इसके लिए:

 class ViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    var resultSearchController: UISearchController!

यह समस्या को ठीक करता है।


1
मैंने इसका मतलब बदल दिया। :-) वैसे भी इस सवाल में पूरे स्रोत को शामिल करना बेहतर है, लेकिन इसे अपने दम पर ढूंढना सबसे अच्छा है ;-)
बेसजेन

मुझे यह गुस्सा चेतावनी भी दे रहा था और आपके जवाब के बाद, मैंने सब कुछ ठीक कर दिया। लेकिन मुझे पता नहीं क्यों! एक नया UISearchController आवंटित करने के बजाय आवश्यक है ... क्या आप मुझे बहिष्कृत करेंगे?
धनु

यकीन नहीं है, मैं एक स्पष्टीकरण भी चाहूंगा।
मोर्टलमैन

अगर मैं var resultSearchController = UISearchController () से var resultSearchController में बदलूं: UISearchController! मुझे घातक त्रुटि मिलती है: अनापत्ति प्रमाण में वैकल्पिक मूल्य को हटाते समय अप्रत्याशित रूप से शून्य पाया जाता है। मेरे पास बड़ी संख्या है, क्या यह त्रुटि पैदा कर रहा है? मुझे सलाह दो।
पवनवीस

मुझे पता चला, स्टोरीबोर्ड से प्रतिनिधि और डेटा स्रोत करने के बजाय, मैंने कोड में लिखा था और समस्या हल हो गई थी।
पवनजीस

20

यहाँ स्विफ्ट संस्करण है जो मेरे लिए काम करता है (toJJHs उत्तर के समान):

deinit{
    if let superView = resultSearchController.view.superview
    {
        superView.removeFromSuperview()
    }
}

@alex मैं इसे परिणाम नियंत्रक के अंत में देखने वाले नियंत्रक के अंत में डाल देता है।
निज जन्म

2
आप वास्तव में जरूरत नहीं है if letक्योंकि .removeFromSuperView()कुछ भी नहीं होगा अगरsuperview == nil
NSGangster

11
class SampleClass: UITableViewController, UISearchBarDelegate {

private let searchController =  UISearchController(searchResultsController: nil)

 override func viewDidLoad() {
        super.viewDidLoad()

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

}

10

कुछ समाधानों को एक साथ हैक करके मैं UISearch.ontro को पूरी तरह स्थापित करने से पहले viewDidLoad में लाइनें जोड़कर मेरा काम करने में कामयाब रहा :

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()

}

मैंने यहां दिए गए हर दूसरे समाधान की भी कोशिश की, और किसी ने चेतावनी को दबाया नहीं (हालांकि खोज नियंत्रक रनटाइम पर काम करता है); यह किया। धन्यवाद!
निकोलस मिआरी

इससे मुझे भी मदद मिली है, लेकिन UISearchController इनिशियलाइज़ होने के बाद मुझे उस लाइन को जोड़ना पड़ा । self.searchController = ({ let controller = UISearchController(searchResultsController: nil) controller.searchResultsUpdater = self controller.dimsBackgroundDuringPresentation = false controller.searchBar.delegate = self definesPresentationContext = true controller.searchBar.sizeToFit() return controller })() फिर self.searchController.loadViewIfNeeded()
युजर

हमें ब्लॉक में इनिशियलाइज़ करने की आवश्यकता क्यों है?
194 में code4latte

7

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.pretViewController लाइन को शामिल नहीं किया था। इससे वही त्रुटि हुई।


7

स्विफ्ट 2.2 संस्करण में जो मेरे लिए काम करता था

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

मुझे लगता है कि यह मददगार है!


2

यह बग नहीं है। ऐसा लगता है कि आपको उन्हें प्रस्तुत किए बिना ViewControllers बनाने से बचना होगा। तो इसके बाद SomeViewController()या let variable: SomeViewControllerआपको कुछ इस तरह से कॉल करना होगा self.presentViewController(yourViewController ...etc)। यदि आप ऐसा नहीं करते हैं, तो आपको यह चेतावनी तब मिलेगी जब इस दृश्य नियंत्रक से निपटा जाएगा।


2

मेरा इस तरह काम कर रहा है

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 () समस्या को हल करता है लेकिन आपको खोज को नियंत्रित करने के बाद इसे कॉल करने की आवश्यकता है


2

एक खोज नियंत्रक बनाना 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()
}

1

मैंने डेरेक के उत्तर का उपयोग किया, लेकिन इसे थोड़ा बदलना पड़ा। उत्तर जो प्रदान किया गया था, वह मेरे लिए दुर्घटनाग्रस्त हो गया क्योंकि परिणाम को खोज करने से पहले loadViewIfNeeded () पर कॉल किया गया था। (मेरी घोषणा थी

var resultSearchController: UISearchController!

)। इसलिए मैंने इसे बाद में स्थानांतरित कर दिया और यह काम कर गया।

अगर मैंने कॉल पूरी तरह से छोड़ दिया, तो बग बना रहा, इसलिए मुझे यकीन है कि यह उत्तर का एक अनिवार्य हिस्सा है। मैं इसे iOS 8 पर टेस्ट नहीं कर पाया।


1

ऐसा लगता है कि दृश्य आलसी भरा हुआ है, यदि आपने नियंत्रक आवंटित किया है और इसे कभी नहीं दिखाते हैं, तो दृश्य लोड नहीं किया गया है। इस मामले में, यदि नियंत्रक से निपटा जाता है, तो आपको यह चेतावनी मिलेगी। आप इसे एक बार दिखा सकते हैं, या इसे लोड करने के लिए देख सकते हैं IfNeed () विधि, या इस चेतावनी से बचने के लिए दृश्य को लोड करने के लिए मजबूर करने के लिए 'let _ = कंट्रोलरव्यू' का उपयोग करें।


iOS 8 पर, आप केवल 'लेट _ = कंट्रोलरव्यू' का उपयोग कर सकते हैं।
david

0

मुझे पार्टी में थोड़ी देर हो गई है, लेकिन यहाँ मेरा समाधान है:

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()
}

आशा है कि ये आपके काम आएगा।


यह सीधे शुरू करने और स्थापित करने से अलग कैसे है; मेरा मतलब है ब्लॉक सिंटैक्स का उपयोग किए बिना?
कोड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.