ios - IBOutlet class 未调用初始化且成员为零

ios - IBOutlet class init not called and members are nil

我正在尝试向我在 XCode swift 中从事的基于地图的项目添加搜索功能 6. 我已将 SearchDisplayController 添加到包含地图的主视图控制器。我创建了一个名为 MapSearchDisplayController 的 class,它实现了必要的方法。我还在故事板中将 SearchDisplayController 的 Custom Class 属性 更改为 MapSearchDisplayController。

在故事板中,我将 SearchDisplayController 拖到我的主视图控制器以创建一个 IBOutlet。主视图控制器的主 viewDidLoad 如下所示:

class ViewController: UIViewController, CCHMapClusterControllerDelegate, MKMapViewDelegate, ADBannerViewDelegate {

    @IBOutlet weak var mapSearchDisplayController1: MapSearchDisplayController!
    @IBOutlet var mapSearchDisplayController: MapSearchDisplayController!
    @IBOutlet weak var banner: ADBannerView!
    @IBOutlet weak var mMap: MKMapView!
    var clusterController:CCHMapClusterController?
    let mMaxZoomLevelForClustering : Double = 13
    let mMinUniqueLocationsForClustering : UInt = 1
    var formatter = NSNumberFormatter()

    var databasePath = NSString()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        banner.delegate = self

        // Add button to navbar
        var filterButton : UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Organize, target: self, action: nil)
        self.navigationItem.leftBarButtonItem = filterButton

        var aboutButton : UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: self, action: "aboutAction")
        var searchButton : UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Search, target: self, action: "searchAction")
        var rButtons : [UIBarButtonItem] = [aboutButton, searchButton]
        self.navigationItem.rightBarButtonItems = rButtons


        // Deal with Search Display Controller
        self.mapSearchDisplayController.delegate = self.mapSearchDisplayController;
        self.mapSearchDisplayController.searchResultsDataSource = self.mapSearchDisplayController;
        self.mapSearchDisplayController.searchResultsDelegate = self.mapSearchDisplayController;
        self.mapSearchDisplayController.searchBar.placeholder = "Search Destination";
        self.mapSearchDisplayController.searchResultsTableView.delegate = self.mapSearchDisplayController
        self.mapSearchDisplayController.searchResultsTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")

问题 1: 我必须添加一个额外的 mapSearchDisplayController1 - 否则我的 mapSearchDisplayController 为零,我在尝试时出现异常去使用它。现在,当我有一个额外的变量 mapSearchDisplayController1 (已声明但从未使用过)时,它不会抛出异常并且某些功能正在运行。尝试 add/remove weak,但它没有任何区别。我不知道我错过了什么导致了这种行为。

问题 2: 我遇到的更大的问题是,处理搜索相关功能的 mapSearchDisplayController 的实例变量为 nil,它的 init 方法未被调用,但委托方法中的功能有效。因此,尽管已初始化为硬编码字符串数组,但 data1 变量为 nil。所有其他成员也是如此,包括常量 googleAPIKey。如果 shouldReloadTableForSearchString 再次设置 data1 data1 = ["1111", "222", "ZAAAA"] 那么它会保持初始化状态,但是如果我为 data1 分配我作为搜索结果获得的值 - 它会丢失。我会理解如果整个对象为零,但方法正在被调用和工作,它只是一个实例变量和 init 不是 "working"。代码如下:

class MapSearchDisplayController: UISearchDisplayController, UISearchDisplayDelegate, UITableViewDataSource, UITableViewDelegate, LPGoogleFunctionsDelegate
{
    var data1 : [String]! = ["1111", "222", "ZAAAA"]
    var googleFunctions : LPGoogleFunctions? = LPGoogleFunctions()
    let googleAPIKey = "myKey"
    //MARK: UITableViewDelegate

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        println("In numberOfRowsInSection - \(data1.count)")
        return self.data1.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        println("In cellForRowAtIndexPath")
        var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
        if !(cell != nil) {
            println("new cellForRow")
            cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
        }
        // Get the corresponding candy from our candies array
        let candy = self.data1[indexPath.row]

        // Configure the cell
        cell!.textLabel.text = candy
        cell!.detailTextLabel?.text = "Cell Details"
        return cell!
    }   

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        // Dismiss search display controller
        self.active = false;

        // Force selected annotation to be on map
    }


    func tableView(tableView: UITableView, numberOfSectionsInTableView indexPath: NSIndexPath) -> Int{
        println("numberOfSectionsInTableView")
        return 1
    }

    //MARK: Search methods
    func filterContentForSearchText (searchText: String) {
        println(searchText)
    }

    func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
        var  length : Int32 = Int32(countElements(searchString))
        if (countElements(searchString) < 3 ) {
            println("Short searchString. Not enough info")
            return false
        }
        data1 = []
        if (googleFunctions == nil)
        {
            googleFunctions = LPGoogleFunctions()
            googleFunctions!.sensor = false
            googleFunctions!.delegate = self
            googleFunctions!.googleAPIBrowserKey = "myKey"
        }
        println(googleFunctions?.googleAPIBrowserKey)
        googleFunctions?.loadPlacesAutocompleteWithDetailsForInput(searchString, offset: length, radius: 0, location: nil, placeType: LPGooglePlaceTypeGeocode, countryRestriction: nil, successfulBlock: {(pd : [AnyObject]!) in
            println("--------------GOOGLE search success")

            for place in pd{
                var pl = place as LPPlaceDetails
                self.data1.append(pl.name)
                println(pl.name)
            }
            }
            , failureBlock: {(status : LPGoogleStatus) in
            println("---- GOOGLE failed")
            })
        //data1 = ["1111", "222", "ZAAAA"]
        return true
    }

    func searchDisplayControllerWillBeginSearch(controller: UISearchDisplayController!){
        controller.searchBar.showsCancelButton = true
    }

    func searchDisplayControllerWillEndSearch(controller: UISearchDisplayController!){
        println("searchDisplayControllerWillEndSearch")
    }

    //MARK: LPGogleFunctions methods
    override init() {

        println("Initializing GoogleFunctions")
        if (googleFunctions == nil){
            googleFunctions = LPGoogleFunctions()
        }
        data1 = []
        super.init()

        googleFunctions!.sensor = false
        googleFunctions!.delegate = self
        googleFunctions!.googleAPIBrowserKey = "myKey"
    }
}

如有任何帮助,我们将不胜感激。

我正在回答我自己的问题,以防有人遇到同样的问题。

问题 #1 我通过删除 IBOutlets 并在故事板中重新添加它们来解决。

发出 #2:我没有调用 searchResultsTableView.reloadData()。 由于网络调用是异步的,因此在更新表视图后在 lambda 中收到结果。强制更新解决了这个问题。