1

tableView(MasterViewController内)にsearchBarとsearchDisplayControllerを実装しました。tableView のセルを表示するためには正常に機能する CustomCell がありますが、検索 tableView のセルでは機能せず、その理由がわかりません。

ここに私の CustomCell クラスがあります:

import UIKit

class CustomCell: UITableViewCell {

@IBOutlet weak var pgrmLabel: UILabel!
@IBOutlet weak var noteLabel: UILabel!
@IBOutlet weak var logoView: UIImageView!


override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    // Configure the view for the selected state
}

func setCell(pgrmName:String, noteInt:Int, logoName:String){
    println("setCell")
    if let itemName=self.pgrmLabel{
        itemName.text=pgrmName
        println("pgrmName: \(pgrmName)")
    }
    if let itemNote=self.noteLabel{
        itemNote.text=String(noteInt)
    }
    if let itemLogo=self.logoView{
        itemLogo.image=UIImage(named: logoName)
    }
    else{
        println("setCell ELSE")
        self.pgrmLabel.text=pgrmName as String
        self.noteLabel.text=String(noteInt)
        self.logoView.image=UIImage(named: logoName as String)
    }   
}
}

masterViewController の cellForRowAtIndexPath メソッド:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

var program:Program
var cell: CustomCell!=tableView.dequeueReusableCellWithIdentifier("Cell") as CustomCell!

    if(cell==nil){
        println("cell nil")
        tableView.registerClass(CustomCell.classForCoder(), forCellReuseIdentifier: "Cell")
        cell=CustomCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    }
    else{
    if tableView == searchDisplayController?.searchResultsTableView{
        println("SearchCell")
        program=filteredPrograms[indexPath.row]
    }
    else{
        println("MasterCell")
        program=arrayOfPrograms[indexPath.row]
    }
    cell.setCell(program.name as String, noteInt: program.note, logoName: program.imageName as String)
    }
    return cell
}

また、 Program クラスは次のとおりです。

import Foundation

class Program{
    var name:String
    var note:Int
    var imageName:String
    var channel:String

init(name:String, note:Int, imageName:String, channel:String){
    self.name=name
    self.note=note
    self.imageName=imageName
    self.channel=channel
}
}

setCell メソッドの searchBar に文字を入力すると、アプリがクラッシュします。それは印刷します:

cell nil
SearchCell
setCell
setCell ELSE
fatal error: unexpectedly found nil while unwrapping an Optional value

誰かが何が起こっているのか知っていれば、それは非常に役に立ちます。

どうもありがとう。

編集: クラッシュしませんが、setCell メソッドを次のように変更すると、検索 tableView が空になります。

self.pgrmLabel?.text=pgrmName
self.noteLabel?.text=String(noteInt)
self.logoView?.image=UIImage(named: logoName)

3 つのパラメーター pgrmName、noteInt、および logoName は nil ではありませんが、pgrmLabel、noteLabel、および logoView は nil です。私は(これらはオプションの値であるため)正しい方法で値を割り当てていないと思います。

4

1 に答える 1

1

最後に別の方法を実行しました。メインストーリーボードのテーブルビューからセルを削除し、新しいファイル (xib ファイルを使用) を作成してカスタムセルを作成しました。

カスタム クラス セルのコードは次のとおりです。

class TableCell: UITableViewCell {

@IBOutlet weak var pgrmLabel: UILabel!
@IBOutlet weak var noteLabel: UILabel!
@IBOutlet weak var logoView: UIImageView!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    // Configure the view for the selected state
}

func setCell(cell: TableCell, pgrmName:String, noteInt:Int, logoName:String){
    if let itemName=self.pgrmLabel{
        itemName.text=pgrmName
    }
    if let itemNote=self.noteLabel{
        itemNote.text="\(noteInt)"
    }
    if let itemLogo=self.logoView{
        itemLogo.image=UIImage(named: logoName)
        if ((itemLogo.image) == nil){
            itemLogo.image=UIImage(named: "placeholder.jpg")
        }
    }
  }
}

BaseTableViewController クラスも作成しました。MasterViewController (メイン テーブルビュー) と ResultsTableViewController (これも作成しました) はそれを継承します。

BaseTableViewController:

class BaseTableViewController: UITableViewController {
// MARK: Types

struct Constants {
    struct Nib {
        static let name = "TableCell"
    }

    struct TableViewCell {
        static let identifier = "cellID"
    }
}

// MARK: View Life Cycle

override func viewDidLoad() {
    super.viewDidLoad()

    let nib = UINib(nibName: Constants.Nib.name, bundle: nil)

    // Required if our subclasses are to use: dequeueReusableCellWithIdentifier:forIndexPath:
    tableView.registerNib(nib, forCellReuseIdentifier: Constants.TableViewCell.identifier)
}


// MARK:

func configureCell(cell: TableCell, forProgram program: Program) {
    cell.setCell(cell, pgrmName: program.name, noteInt: program.note, logoName: program.imageName)
}

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 100
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 100
}
}

マスター ビュー コントローラー:

class MasterViewController: BaseTableViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating {

struct RestorationKeys {
    static let viewControllerTitle = "ViewControllerTitleKey"
    static let searchControllerIsActive = "SearchControllerIsActiveKey"
    static let searchBarText = "SearchBarTextKey"
    static let searchBarIsFirstResponder = "SearchBarIsFirstResponderKey"
}

//controllers
var detailViewController: DetailViewController? = nil
var searchController: UISearchController!
var resultsTableController: ResultsTableViewController!
var restoredState=SearchControllerRestorableState()

//array of programs to display in the tableview
var arrayOfPrograms=[Program]()

struct SearchControllerRestorableState {
    var wasActive=false
    var wasFirstResponder=false
}

override func awakeFromNib() {
    super.awakeFromNib()
    if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
        self.clearsSelectionOnViewWillAppear = false
        self.preferredContentSize = CGSize(width: 320.0, height: 600.0)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    //self.navigationItem.leftBarButtonItem = self.editButtonItem()
    if let split = self.splitViewController {
        let controllers = split.viewControllers
        self.detailViewController = controllers[controllers.count-1].topViewController as? DetailViewController
    }
    self.setUpPrograms()

    let tableViewController=navigationController?.viewControllers[0] as MasterViewController

    resultsTableController=ResultsTableViewController()
    resultsTableController.tableView.delegate=self

    searchController=UISearchController(searchResultsController: resultsTableController)
    searchController.searchResultsUpdater=self
    searchController.searchBar.sizeToFit()
    tableView.tableHeaderView=searchController.searchBar
    searchController.delegate=self
    searchController.dimsBackgroundDuringPresentation=false
    searchController.searchBar.delegate=self
    definesPresentationContext=true

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    // Restore the searchController's active state.
    if restoredState.wasActive {
        searchController.active = restoredState.wasActive
        restoredState.wasActive = false

        if restoredState.wasFirstResponder {
            searchController.searchBar.becomeFirstResponder()
            restoredState.wasFirstResponder = false
        }
    }
}

func searchBarSearchButtonClicked(searchBar: UISearchBar) {
    searchBar.resignFirstResponder()
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    var selectedProgram:Program

    if tableView == self.tableView {
        selectedProgram=arrayOfPrograms[indexPath.row]
    }
    else{
        selectedProgram=resultsTableController.filteredPrograms[indexPath.row]
    }

    let detailViewController=DetailViewController.forProgram(selectedProgram)
    navigationController!.pushViewController(detailViewController, animated: true)
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

// MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return arrayOfPrograms.count
}



func updateSearchResultsForSearchController(searchController: UISearchController) {
    let searchResults=arrayOfPrograms

    // Strip out all the leading and trailing spaces.
    let whitespaceCharacterSet = NSCharacterSet.whitespaceCharacterSet()
    let strippedString = searchController.searchBar.text.stringByTrimmingCharactersInSet(whitespaceCharacterSet)
    let searchItems = strippedString.componentsSeparatedByString(" ") as [String]

    // Build all the "AND" expressions for each value in the searchString.
    var andMatchPredicates = [NSPredicate]()

    for searchString in searchItems {
        // Each searchString creates an OR predicate for: name, yearIntroduced, introPrice.
        //
        // Example if searchItems contains "iphone 599 2007":
        //      name CONTAINS[c] "iphone"
        //      name CONTAINS[c] "599", yearIntroduced ==[c] 599, introPrice ==[c] 599
        //      name CONTAINS[c] "2007", yearIntroduced ==[c] 2007, introPrice ==[c] 2007
        //
        var searchItemsPredicate = [NSPredicate]()

        // Name field matching.
        var lhs = NSExpression(forKeyPath: "name")
        var rhs = NSExpression(forConstantValue: searchString)
        var finalPredicate = NSComparisonPredicate(leftExpression: lhs, rightExpression: rhs, modifier: .DirectPredicateModifier, type: .ContainsPredicateOperatorType, options: .CaseInsensitivePredicateOption)
        searchItemsPredicate.append(finalPredicate)

        // Channel field matching.
        lhs = NSExpression(forKeyPath: "channel")
        rhs = NSExpression(forConstantValue: searchString)
        finalPredicate = NSComparisonPredicate(leftExpression: lhs, rightExpression: rhs, modifier: .DirectPredicateModifier, type: .ContainsPredicateOperatorType, options: .CaseInsensitivePredicateOption)
        searchItemsPredicate.append(finalPredicate)

        // Add this OR predicate to our master AND predicate.
        let orMatchPredicates = NSCompoundPredicate.orPredicateWithSubpredicates(searchItemsPredicate)
        andMatchPredicates.append(orMatchPredicates)
    }

    // Match up the fields of the Product object.
    let finalCompoundPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(andMatchPredicates)

    let filteredResults = searchResults.filter { finalCompoundPredicate.evaluateWithObject($0) }

    // Hand over the filtered results to our search results table.
    let resultsController = searchController.searchResultsController as ResultsTableViewController
    resultsController.filteredPrograms = filteredResults
    resultsController.tableView.reloadData()
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(Constants.TableViewCell.identifier, forIndexPath: indexPath) as TableCell
    let program=arrayOfPrograms[indexPath.row]
    configureCell(cell, forProgram: program)
    return cell
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return false 
}

override func encodeRestorableStateWithCoder(coder: NSCoder) {
    super.encodeRestorableStateWithCoder(coder)

    // Encode the title.
    coder.encodeObject(navigationItem.title!, forKey:RestorationKeys.viewControllerTitle)

    // Encode the search controller's active state.
    coder.encodeBool(searchController.active, forKey:RestorationKeys.searchControllerIsActive)

    // Encode the first responser status.
    coder.encodeBool(searchController.searchBar.isFirstResponder(), forKey:RestorationKeys.searchBarIsFirstResponder)

    // Encode the search bar text.
    coder.encodeObject(searchController.searchBar.text, forKey:RestorationKeys.searchBarText)
}

override func decodeRestorableStateWithCoder(coder: NSCoder) {
    super.decodeRestorableStateWithCoder(coder)

    // Restore the title.
    if let decodedTitle = coder.decodeObjectForKey(RestorationKeys.viewControllerTitle) as? String {
        title = decodedTitle
    }
    else {
        fatalError("A title did not exist. In your app, handle this gracefully.")
    }

    // Restore the active state:
    // We can't make the searchController active here since it's not part of the view
    // hierarchy yet, instead we do it in viewWillAppear.
    //
    restoredState.wasActive = coder.decodeBoolForKey(RestorationKeys.searchControllerIsActive)

    // Restore the first responder status:
    // Like above, we can't make the searchController first responder here since it's not part of the view
    // hierarchy yet, instead we do it in viewWillAppear.
    //
    restoredState.wasFirstResponder = coder.decodeBoolForKey(RestorationKeys.searchBarIsFirstResponder)

    // Restore the text in the search field.
    searchController.searchBar.text = coder.decodeObjectForKey(RestorationKeys.searchBarText) as String
}

}

ResultsTableViewController

class ResultsTableViewController: BaseTableViewController {

var filteredPrograms=[Program]()

override func viewDidLoad() {
    super.viewDidLoad()
    println("results table view")
}

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

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    println("results table view nb of raws in section")
    return filteredPrograms.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    //let cell=tableView.dequeueReusableCellWithIdentifier(Constants.TableViewCell.identifier) as TableCell!
    let cell = tableView.dequeueReusableCellWithIdentifier(Constants.TableViewCell.identifier, forIndexPath: indexPath) as TableCell
    let program = filteredPrograms[indexPath.row]
    configureCell(cell, forProgram: program)
    return cell
}
}
于 2014-10-27T09:01:34.767 に答える