Skip to main content
 首页 » 操作系统

ios之'数组 <(对象)>' is not convertible to ' bool 值'

2024年01月01日37zdz8207

假设有一个名为 Post 的类(如在论坛帖子中)。

class Post: NSManagedObject { 
 
    @NSManaged var id: NSNumber 
    @NSManaged var title: String? 
    @NSManaged var body: String? 
    @NSManaged var voteCount: NSNumber? 
    @NSManaged var thread: Thread? 
} 

还有一个Thread类。

class Thread: NSManagedObject { 
 
    @NSManaged var topic: String 
    @NSManaged var id: NSNumber 
    @NSManaged var posts: NSSet 
} 

一个线程包含一组Post对象。

从本地核心数据数据库中,我将 Thread 对象数组检索到 var threads = [Thread]()。

现在我需要过滤掉线程中投票数大于 0 的帖子。换句话说,我需要一个 Thread 对象数组,不包括 Post 0票。

这是我到目前为止尝试过的方法。

var filteredThreads = threads.filter() { $0.posts.filter() { $0.voteCount > 0 } } 

但我收到错误消息'Array<(Post)>' is not convertible to 'Bool'。

看来我不能像这样使用嵌套过滤器。还是我做错了?


编辑:我也试过下面的代码。没有编译时错误,但它没有按预期过滤返回的结果数组。

threads = items.filter() { 
    for post in $0.posts.allObjects as [Post] { 
        if post.voteCount!.integerValue > 0 { 
            return true 
        } 
    } 
    return false 
} 

我上传了一个 Xcode 项目 here证明问题。感谢您的帮助。

谢谢。


尝试 2:我尝试遍历接收到的 Thread 对象并过滤掉其中的 Post。但是我不知道如何将过滤后的数组添加回 Thread 对象。

if let items = viewModel.getThreads() { 
    for thread in items { 
        let posts = thread.posts.allObjects as [Post] 
        var s = posts.filter() { 
            if $0.voteCount!.integerValue > 0 { 
                return true 
            } else { 
                return false 
            } 
        } 
    } 
} 

请您参考如下方法:

你的方法行不通。您不能过滤这样的 Thread 对象 你得到一个“修改过的”线程对象数组的方式,它们只是 与投票数为正的帖子相关。过滤总是给出一个 原始对象的子集,但这些对象未被修改。

实现你想要的正确方法是获取所有 Post 对象 票数为正,并根据 他们的主题。

最简单的方法是使用 NSFetchedResultsController。

这是您的 ForumViewController 的快速版本 使用获取的结果 Controller 。大部分是样板代码 您通过标准的“主从应用程序 + 核心数据”获得 在 Xcode 中。它当然可以改进,但希望能帮助你 在正确的轨道上。

要在您的示例项目中进行编译,managedObjectContext 在 ForumViewModel 中需要是公共(public)属性。 或者,您可以移动获取的结果 Controller 创建 进入 ForumViewModel 类。

// ForumViewController.swift: 
import UIKit 
import CoreData 
 
class ForumViewController: UITableViewController, NSFetchedResultsControllerDelegate { 
 
    private let viewModel = ForumViewModel() 
 
    var fetchedResultsController: NSFetchedResultsController { 
        if _fetchedResultsController != nil { 
            return _fetchedResultsController! 
        } 
 
        // Fetch "Post" objects: 
        let fetchRequest = NSFetchRequest(entityName: "Post") 
 
        // But only those with positive voteCount: 
        let predicate = NSPredicate(format: "voteCount > 0") 
        fetchRequest.predicate = predicate 
 
        // First sort descriptor must be the section key: 
        let topicSort = NSSortDescriptor(key: "thread.topic", ascending: true) 
        // Second sort descriptor to sort the posts in each section: 
        let titleSort = NSSortDescriptor(key: "title", ascending: true) 
        fetchRequest.sortDescriptors = [topicSort, titleSort] 
 
        // Fetched results controller with sectioning according the thread.topic: 
        let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, 
                managedObjectContext: viewModel.managedObjectContext, 
                sectionNameKeyPath: "thread.topic", cacheName: nil) 
        aFetchedResultsController.delegate = self 
        _fetchedResultsController = aFetchedResultsController 
 
        var error: NSError? = nil 
        if !_fetchedResultsController!.performFetch(&error) { 
            abort() 
        } 
        return _fetchedResultsController! 
    } 
    var _fetchedResultsController: NSFetchedResultsController? = nil 
 
    override func viewDidLoad() { 
        super.viewDidLoad() 
    } 
 
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
        return self.fetchedResultsController.sections?.count ?? 0 
    } 
 
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
        let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo 
        return sectionInfo.numberOfObjects 
    } 
 
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell 
        self.configureCell(cell, atIndexPath: indexPath) 
        return cell 
    } 
 
    func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { 
        let post = self.fetchedResultsController.objectAtIndexPath(indexPath) as Post 
        cell.textLabel!.text = post.title 
        cell.detailTextLabel!.text = "\(post.voteCount!)" 
    } 
 
    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
        let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo 
        return sectionInfo.name 
    } 
 
    func controllerWillChangeContent(controller: NSFetchedResultsController) { 
        self.tableView.beginUpdates() 
    } 
 
    func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { 
        switch type { 
        case .Insert: 
            self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) 
        case .Delete: 
            self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) 
        default: 
            return 
        } 
    } 
 
    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { 
        switch type { 
        case .Insert: 
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) 
        case .Delete: 
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
        case .Update: 
            self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!) 
        case .Move: 
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) 
        default: 
            return 
        } 
    } 
 
    func controllerDidChangeContent(controller: NSFetchedResultsController) { 
        self.tableView.endUpdates() 
    } 
} 

结果: