【问题标题】:Using custom sections with NSFetchedResultsController?使用带有 NSFetchedResultsController 的自定义部分?
【发布时间】:2010-11-25 22:36:07
【问题描述】:

我正在制作一个带有提取结果的分区表,但很难制定出自定义部分。

通常只有一个属性作为排序依据,并使用sectionNameKeyPath: 来生成这些部分。但是我的排序属性是动态计算的,我似乎无法让fetchedResultsController 正确使用它...

更新:使用下面jbrennan 的建议,我真的很接近预期的功能。我在NSDate 中添加了一个返回“几天前”数字的类别;把它放在这里会给我基于这些数字的部分:

NSFetchedResultsController *aFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
    managedObjectContext:managedObjectContext
    sectionNameKeyPath:@"myDateAttribute.daysAgo"
    cacheName:@"Root"];

这就是我卡住的地方:我不需要它们按“几天前”排序,我需要通过基于实体中的 other 属性的一些计算对它们进行排序。所以我不能只调用那个自定义的 Category 方法,我需要调用一个带有 arguments 的方法,像这样:

[myDateAttribute sortingRoutine:thisObject.value]

或者类似的东西。我希望这有一定的意义。如果您能提供帮助,非常感谢:)

【问题讨论】:

    标签: iphone cocoa-touch uitableview core-data


    【解决方案1】:

    我在(即将)发布的 iPhone 应用程序中做了类似的事情。我的部分按如下日期划分:昨天、今天、明天、未来……

    无论如何,对我来说,诀窍是向 NSDate 添加一个类别以确定我获取的对象属于哪个部分。

    我的托管对象有一个名为dueDate 的属性,它是一个NSDate。在配置获取结果控制器时,我使用了@"dueDate.relativeDate" 作为部分键路径。

    在类别中,-relativeDate 被声明为返回 NSStringreadonly 属性(其中任何一个都可能就足够了,我没有尝试两者都没有,但拥有这并没有什么坏处方法和属性声明)。然后我简单地实现了这个方法,效果很好。

    【讨论】:

    • 好的,我想我和你在一起。但是,如果我的 NSDates 实际上是在一个单独的实体中怎么办?我有Tasks 作为获取的主要实体,而Resets 是相关的(对多)。所以每个Task 都有一堆Reset 日期,其中最近的日期是最重要的日期。我尝试使用@"reset.specialDateMethod 作为排序键,但它不喜欢那样...
    • 这取决于你的specialDateMethod 做什么。在这种方法中,您可能可以使用 NSPredicate 过滤您的重置集以找到重要的重置集,然后使用它的date 随心所欲。您可能还想缓存Reset,因为我想这会变得昂贵。也许你的Task 可能有一个类似“mostRecentReset”或任何相关的属性。
    • 更重要的是:sectionNameKeyPath: 期待什么?它必须是一个字符串,它对应于实体中的一个属性吗?我想这就是我感到困惑的地方。
    • 更新:我想我很接近了。但是:我只能在sectionNameKeyPath: 中放置一个不带参数的方法。所以使用@"myAttribute.myMethod" 可以正常工作,但我需要传递有关对象的方法信息——我需要能够执行@"[myAttribute myMethod:var otherArg:otherVar]" 之类的操作,但这会让人窒息。
    • 哇,这是一个很好的解决方案。我需要一个 NSDate 上的瞬态属性,就像你一样,但不能完全弄清楚瞬态属性。在 NSDate 上放置一个类别就可以了,而且更干净,保持我的模型很小。谢谢。
    【解决方案2】:

    您可以尝试以下方法。

    在任务实体中为您的核心数据模型添加一个瞬态属性。然后实现

    - (void)awakeFromFetch
    

    Task NSManagedObject 类中的方法。请参阅其文档。在该方法中,您可以使用其他属性的值设置瞬态属性的值。请注意,您可以做什么有一些限制,但这在文档中有很好的解释(最值得注意的是,您不能修改关系或传递参数;但是,如果您可以仅使用其他属性的值来计算瞬态属性/关系应该很好)。

    完成此操作后,您只需使用瞬态属性作为传递的属性即可取回这些部分。

    【讨论】:

    • 啊哈!这很好用,谢谢。现在应用程序在保存新任务时崩溃了,但我会在这方面做一些工作,如果需要的话,我会发布一个单独的问题。 :)
    • 保存时您的应用程序不应崩溃:暂态属性未存储,因此无论如何这都不是原因。
    • 它实际上并没有在保存过程中崩溃,而是在之后,当视图切换回分段表时。在这些更改之前没有这样做,我还没有做任何其他事情,所以我认为这是相关的。当视图重新出现时,也许 awakeFromFetch: 没有被调用?
    • awakeFromFetch: 在获取对象之前被调用一次。当您切换回表格时,如果您实现了 NSFetchedResultsController 委托方法,则会调用它们。
    • 那么我是否需要将我放入awakeFromFetch: 的相同内容也放入其中一种方法中?任何想法最合适? (旁白:你是如何找到这些东西的?即,你怎么知道awakeFromFetch: 何时被调用?我似乎在参考文档中找不到任何此类信息......)
    【解决方案3】:

    这是实现此目的的一堆代码(感谢 jbrennan):

    @implementation NSDate (MyExtensions)
    
    
    // Return today.
    + (NSDate *)today {
    
        return [NSDate date];
    }
    
    
    // Return yesterday (today minus 24 hours).
    + (NSDate *)yesterday {
    
        return [NSDate dateWithTimeIntervalSinceNow:-60*60*24];
    }
    
    
    // Return tomorrow (today plus 24 hours).
    + (NSDate *)tomorrow {
    
        return [NSDate dateWithTimeIntervalSinceNow:60*60*24];
    }
    
    
    // Convert a date comporting a time into a rounded date (just the day, no time).
    - (NSDate *)dayDate {
    
        unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
        NSDateComponents *comps = [[NSCalendar currentCalendar] components:unitFlags fromDate:self];
        return [[NSCalendar currentCalendar] dateFromComponents:comps]; 
    }
    
    
    // Return a string representing the date relatively (today, tomorrow, yesterday, etc.)
    // If no relative sentence is found, return the NSDateFormatterLongStyle formatted date.
    - (NSString *)relativeDate {
    
        if ([self.dayDate isEqualToDate:[[NSDate today] dayDate]]) {
    
            return NSLocalizedString(@"Today", @"NSDate extensions");
        }
        if ([self.dayDate isEqualToDate:[[NSDate yesterday] dayDate]]) {
    
            return NSLocalizedString(@"Yesterday", @"NSDate extensions");
        }
        if ([self.dayDate isEqualToDate:[[NSDate tomorrow] dayDate]]) {
    
            return NSLocalizedString(@"Tomorrow", @"NSDate extensions");
        }
    
        return [NSDateFormatter localizedStringFromDate:self
                                              dateStyle:NSDateFormatterLongStyle
                                              timeStyle:NSDateFormatterNoStyle];    
    }
    
    
    @end
    

    【讨论】:

    • 这是旧的,但任何读到这里的人:不要使用这样的秒常量,使用 NSCalendar 函数。去看看任何关于日期的 WWDC 演讲
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多