草庐IT

ios - 无法在强制转换中将类型 '[Record]' 的值转换为类型 'Record'

coder 2023-09-09 原文

我将使用 C# 和 Xamarin 制作的 iOS 应用重写到 Swift,原因很明显是 Xamarin 的定价和低文档。正在关注this tutorial因为在我的 UITableView 上包含一个 UISearchBar,我遇到了这个错误:Cannot convert value of type '[Record]' to type 'Record in coercion。 Record.swift 是我创建的一个结构文件,用于存储我将使用 cloudkit 检索的数据,但我不确定这个错误是怎么来的。

这是 MasterViewController.swift 的问题部分:

func updateSearchResultsForSearchController(searchController: UISearchController) {
    self.filteredRecords.removeAll(keepCapacity: false)

    let searchPredicate = NSPredicate(format: "SELF CONTAINS [c] %@", searchController.searchBar.text!)
    // Here is where the error shows
    let array = (self.records as Record).filteredArrayUsingPredicate(searchPredicate)
    self.filteredRecords = array as! [Record]

    self.tableView.reloadData()
}

这是完整的 MasterViewController.swift:

import UIKit

class MasterViewController: UITableViewController, UISearchResultsUpdating {

    var detailViewController: DetailViewController? = nil
    var resultSearchController = UISearchController()
    var records = [Record]()
    var filteredRecords = [Record]()

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

        let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "insertNewObject:")
        self.navigationItem.rightBarButtonItem = addButton
        if let split = self.splitViewController {
            let controllers = split.viewControllers
            self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
        }

        // #REMOVE - Testing implementation until iCloud is setup
        self.records = [
            Record(album: "The Awakening", artist: "P.O.D.",  genre: "Hardcore Rock", year: 2015, speed: "33 1/3", size: 12),
            Record(album: "Attack of The Killer B-Sides", artist: "A Day to Remember",  genre: "Post-Hardcore", year: 2010, speed: "33 1/3", size: 7),
            Record(album: "All I Want", artist: "A Day to Remember",  genre: "Post-Hardcore", year: 2011, speed: "33 1/3", size: 7),
            Record(album: "The White Stripes", artist: "The White Stripes",  genre: "Rock", year: 2003, speed: "45", size: 7),
            Record(album: "Save Rock and Roll", artist: "Fall Out Boy",  genre: "Punk Rock", year: 2013, speed: "33 1/3", size: 10),
            Record(album: "A Perfect Sky", artist: "Yellowcard",  genre: "Pop-Punk", year: 2015, speed: "33 1/3", size: 10),
            Record(album: "Noise vs Beauty", artist: "Bassnectar",  genre: "Dubstep", year: 2014, speed: "33 1/3", size: 12)
        ]

        // Configure the search bar controller
        self.resultSearchController = UISearchController(searchResultsController: nil)
        self.resultSearchController.searchResultsUpdater = self
        self.resultSearchController.dimsBackgroundDuringPresentation = false
        self.resultSearchController.searchBar.sizeToFit()

        self.tableView.tableHeaderView = self.resultSearchController.searchBar

        // Reload the data upon startup
        self.tableView.reloadData()
    }

    override func viewWillAppear(animated: Bool) {
        self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed
        super.viewWillAppear(animated)
    }

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

//    func insertNewObject(sender: AnyObject) {
//        objects.insert(NSDate(), atIndex: 0)
//        let indexPath = NSIndexPath(forRow: 0, inSection: 0)
//        self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
//    }

    // MARK: - Segues

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showDetail" {
            if let indexPath = self.tableView.indexPathForSelectedRow {
                let object = records[indexPath.row]
                let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
                controller.detailItem = object
                controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
                controller.navigationItem.leftItemsSupplementBackButton = true
            }
        }
    }

    // MARK: - Table View

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

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if (self.resultSearchController.active) {
            return self.filteredRecords.count
        } else {
            return self.records.count
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell

        if (self.resultSearchController.active) {
            let object = filteredRecords[indexPath.row]
            cell.textLabel!.text = object.album
            cell.detailTextLabel!.text = object.artist
            cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
        } else {
            let object = records[indexPath.row]
            cell.textLabel!.text = object.album
            cell.detailTextLabel!.text = object.artist
            cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
        }

        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 true
    }

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            records.removeAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
        }
    }

    func updateSearchResultsForSearchController(searchController: UISearchController) {
        self.filteredRecords.removeAll(keepCapacity: false)

        let searchPredicate = NSPredicate(format: "SELF CONTAINS [c] %@", searchController.searchBar.text!)
        let array = (self.records as Record).filteredArrayUsingPredicate(searchPredicate)
        self.filteredRecords = array as! [Record]

        self.tableView.reloadData()
    }
}

和 Record.swift:

import Foundation

struct Record {
    let album : String
    let artist : String
    let genre : String
    let year : Int
    let speed : String
    let size : Int
}

希望这将是一个简单的修复。如果没有,是否有任何教程建议?或者其他地方我应该问这个?

最佳答案

filteredArrayUsingPredicate 是一个 NSArray 方法,因此您应该将其转换为 NSArray:

let array = (self.records as NSArray).filteredArrayUsingPredicate(searchPredicate)

但这仍然会产生错误“[Record] 无法转换为 NSArray”。这是因为 NSArray 只能包含 Objective-C 对象,而 Record 是 Swift 结构,不能转换为对象。有两种解决方案。

解决方案一:

将记录声明为一个对象

class Record: NSObject {
    let album : String
    let artist : String
    let genre : String
    let year : Int
    let speed : String
    let size : Int

    init(album : String, artist : String, genre : String, year : Int, speed : String, size : Int) {
        self.album = album
        self.artist = artist
        self.genre = genre
        self.year = year
        self.speed = speed
        self.size = size
    }
}

那么下面的代码应该可以工作了

let searchPredicate = NSPredicate(format: "SELF.artist CONTAINS [c] %@", searchController.searchBar.text!)
let array = (self.records as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredRecords = array as! [Record]

请注意,您的原始谓词没有意义,并且会导致运行时错误,因为 Record 不是字符串,所以我将其替换。

解决方案 2:

使用Swift方式过滤:

let searchText = searchController.searchBar.text!.lowercaseString
filteredRecords = self.records.filter { (aRecord) -> Bool in
    return aRecord.artist.lowercaseString.containsString(searchText)
}

关于ios - 无法在强制转换中将类型 '[Record]' 的值转换为类型 'Record',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33030171/

有关ios - 无法在强制转换中将类型 '[Record]' 的值转换为类型 'Record'的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  5. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  6. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  7. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  8. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  9. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  10. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

随机推荐