'Array<(Object)>' 不可转换为 'Bool'
'Array<(Object)>' is not convertible to 'Bool'
假设有一个名为 Post
的 class(如在论坛 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.
class Thread: NSManagedObject {
@NSManaged var topic: String
@NSManaged var id: NSNumber
@NSManaged var posts: NSSet
}
一个线程包含一组 Post
个对象。
我从本地核心数据数据库中检索了 Thread
个对象的数组到 var threads = [Thread]()
。
现在我需要过滤掉投票数大于 0 的线程中的 posts。换句话说,我需要一个 Thread
对象数组,不包括 Post
s 有 0 票。
这是我目前为止尝试过的方法。
var filteredThreads = threads.filter() { [=14=].posts.filter() { [=14=].voteCount > 0 } }
但是我收到错误 'Array<(Post)>' is not convertible to 'Bool'.
看来我不能像这样使用嵌套过滤器。还是我做错了?
编辑: 我也试过下面的代码。没有编译时错误,但它没有按预期过滤返回的结果数组。
threads = items.filter() {
for post in [=15=].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 [=16=].voteCount!.integerValue > 0 {
return true
} else {
return false
}
}
}
}
[=12=].posts.filter() { [=12=].voteCount > 0 }
returns Post
的数组 voteCount
为正数。你必须检查它的 count
:
var filteredThreads = threads.filter() {
[=10=].posts.filter({ [=10=].voteCount > 0 }).count > 0
// ^^^^^^^^^^
}
但是,这将无条件地迭代所有 posts
。相反,您应该尽快return true
:
var filteredThreads = threads.filter() {
for p in [=11=].posts {
if p.voteCount > 0 {
return true
}
}
return false
}
过滤器中的函数必须 return 类型为 'Bool'
我认为以下代码可能对您有用
var filteredThreads = threads.filter({
var result = false;
for (var i = 0; i<[=10=].posts.count;i++) {
if ([=10=].posts[i].voteCount > 0){
result = true;
}
}
return result
})
This 博客 post 可能会有用
你的方法不行。您不能过滤这样的 Thread 对象
获得 "modified" Thread 对象数组的方式
与投票数为正的 Post 相关。过滤总是给出一个
原始对象的子集,但这些对象未被修改。
实现您想要的目标的正确方法是获取所有 Post 对象
票数为正,并根据
他们的主题。
最简单的方法是 NSFetchedResultsController
。
这是您的 ForumViewController 的快速版本
使用获取的结果控制器。大部分是样板代码
你得到一个标准 "Master-Detail Application + Core Data"
在 Xcode。它当然可以改进,但希望能帮助你
在正确的轨道上。
要在您的示例项目中进行编译,managedObjectContext
在 ForumViewModel
需要一个 public 属性。
或者,您可以移动获取的结果控制器创建
进入 ForumViewModel
class.
// 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()
}
}
结果:
假设有一个名为 Post
的 class(如在论坛 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.
class Thread: NSManagedObject {
@NSManaged var topic: String
@NSManaged var id: NSNumber
@NSManaged var posts: NSSet
}
一个线程包含一组 Post
个对象。
我从本地核心数据数据库中检索了 Thread
个对象的数组到 var threads = [Thread]()
。
现在我需要过滤掉投票数大于 0 的线程中的 posts。换句话说,我需要一个 Thread
对象数组,不包括 Post
s 有 0 票。
这是我目前为止尝试过的方法。
var filteredThreads = threads.filter() { [=14=].posts.filter() { [=14=].voteCount > 0 } }
但是我收到错误 'Array<(Post)>' is not convertible to 'Bool'.
看来我不能像这样使用嵌套过滤器。还是我做错了?
编辑: 我也试过下面的代码。没有编译时错误,但它没有按预期过滤返回的结果数组。
threads = items.filter() {
for post in [=15=].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 [=16=].voteCount!.integerValue > 0 {
return true
} else {
return false
}
}
}
}
[=12=].posts.filter() { [=12=].voteCount > 0 }
returns Post
的数组 voteCount
为正数。你必须检查它的 count
:
var filteredThreads = threads.filter() {
[=10=].posts.filter({ [=10=].voteCount > 0 }).count > 0
// ^^^^^^^^^^
}
但是,这将无条件地迭代所有 posts
。相反,您应该尽快return true
:
var filteredThreads = threads.filter() {
for p in [=11=].posts {
if p.voteCount > 0 {
return true
}
}
return false
}
过滤器中的函数必须 return 类型为 'Bool'
我认为以下代码可能对您有用
var filteredThreads = threads.filter({
var result = false;
for (var i = 0; i<[=10=].posts.count;i++) {
if ([=10=].posts[i].voteCount > 0){
result = true;
}
}
return result
})
This 博客 post 可能会有用
你的方法不行。您不能过滤这样的 Thread 对象 获得 "modified" Thread 对象数组的方式 与投票数为正的 Post 相关。过滤总是给出一个 原始对象的子集,但这些对象未被修改。
实现您想要的目标的正确方法是获取所有 Post 对象 票数为正,并根据 他们的主题。
最简单的方法是 NSFetchedResultsController
。
这是您的 ForumViewController 的快速版本 使用获取的结果控制器。大部分是样板代码 你得到一个标准 "Master-Detail Application + Core Data" 在 Xcode。它当然可以改进,但希望能帮助你 在正确的轨道上。
要在您的示例项目中进行编译,managedObjectContext
在 ForumViewModel
需要一个 public 属性。
或者,您可以移动获取的结果控制器创建
进入 ForumViewModel
class.
// 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()
}
}
结果: