【问题标题】:'Array<(Object)>' is not convertible to 'Bool''Array<(Object)>' 不能转换为 'Bool'
【发布时间】:2015-04-25 21:14:09
【问题描述】:

假设有一个名为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 对象数组,不包括 0 票的 Posts。

这是我迄今为止尝试过的。

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

但我收到错误 'Array' 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 对象并过滤掉其中的 Posts。但我不知道如何将过滤后的数组添加回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
            }
        }
    }
}

【问题讨论】:

    标签: ios arrays swift core-data filter


    【解决方案1】:

    你的方法行不通。您不能过滤这样的 Thread 对象 获取“修改”线程对象数组的方式,这些对象仅 与票数为正的帖子有关。过滤总是给出一个 原始对象的子集,但这些对象没有被修改。

    实现您想要的正确方法是获取所有 Post 对象 具有积极的投票计数,并根据 他们的主题。

    最简单的方法是NSFetchedResultsController

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

    要在您的示例项目中进行编译,managedObjectContext ForumViewModel 中的需要是公共属性。 或者,您可以移动获取的结果控制器创建 进入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()
        }
    }
    

    结果:

    【讨论】:

      【解决方案2】:

      $0.posts.filter() { $0.voteCount &gt; 0 } 返回一个 Post 数组,其中 voteCount 为正数。你必须检查它的count

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

      但是,这无条件地迭代所有posts。相反,您应该尽快return true

      var filteredThreads = threads.filter() {
          for p in $0.posts {
              if p.voteCount > 0 {
                  return true
              }
          }
          return false
      }
      

      【讨论】:

      • 您好,感谢您的回复。但我似乎无法让它发挥作用。尽管代码编译没有错误,但仍显示相同的旧结果集。我用更多的说明和信息更新了我的原始问题。你能看看吗?
      【解决方案3】:

      过滤器中的那个函数必须返回类型为“Bool”的东西

      我认为下面的代码可能对你有用

      var filteredThreads = threads.filter({
         var result = false;
         for (var i = 0; i<$0.posts.count;i++) {
            if ($0.posts[i].voteCount > 0){
                 result = true;
            }
         }
         return result
      })
      

      This 博文可能有用

      【讨论】:

      • 您好,感谢您的回复。我尝试了@rintaro 发布的带有for in 循环的类似解决方案,但不幸的是它没有正确过滤掉数组。我认为我之前太模糊了,所以我用更多信息更新了上面的原始问题。如果可以,请再看看。
      猜你喜欢
      • 1970-01-01
      • 2018-12-13
      • 2017-11-12
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      相关资源
      最近更新 更多