2016-09-30 50 views
0

我正在重构UIViewController以删除不应该在那里的非UI内容。我一直在看Andy Matuschak's great talk about this,在一个例子中,他正在扩展NSPredicate和移动逻辑,该逻辑能够确定谓词应该从视图控制器进入到它将在哪里设置fetchRequest.predicate的结果。我的便利init不能在扩展中工作

我试图做同样的事情,但我发现在我的分机的便利初始化错误:

import Foundation 

extension NSPredicate { 
    convenience init(forLiftLogFilter) { // it doesn't like this line 
     if let logFilter = UserDefaultsManager.sharedInstance.logFilter?.rawValue { 
      filterPredicate = NSPredicate(format: "lift.liftName = [c] %@", logFilter) 
     } else { 
      filterPredicate = nil 
     } 
    } 
} 

我会从一个'的UIViewController”像这样称呼它:

override func viewWillAppear(animated: Bool) { 
     let filterPredicate = NSPredicate.forLiftLogFilter // thinks NSPredicate doesn't have a member named 'forLiftLogFilter' 
     reloadData(filterPredicate) 

    super.viewWillAppear(animated) 
    } 

在我的情况下,我不需要传入任何初始化参数,但我很确定我需要一个外部名称,即forLiftLogFilter,以便我可以拨打电话。 Xcode(8.0/Swift 2.3)告诉我'未命名的参数必须用空的名字'_'写入。我明白这个错误,但我实际上没有任何参数。它一定在想forLiftLogFilter是一个参数什么的。当然,因为这不起作用,在我拨打电话的UIViewController中告诉我'NSPredicate类型没有'forLiftLogFilter'成员。

我做了很多关于扩展,初始化等的阅读,但没有回答关于带名称但没有参数的便利初始值设定项。

任何人都可以帮助我理解我的初始化程序有什么问题吗?

为了便于比较,这里的安迪用在他的演示代码:

extension NSPredicate { 
    convenience init(forTasksWithinNumberOfDays numberOfDays: Int, ofDate: Date, calendar: NSCalendar = NSCalendar.currentCalendar()) { 
    self.init(format: "dueDate = %@" argumentArray: [calendar.dateByAddingUnit(.day, value: numberOfDays, toDate: date, options: NSCalendarOptions())!] 
    } 
} 

,他称之为就像从视图控制器是这样的:

override func viewDidLoad() { 
    super.viewDidLoad() 

    fetchRequest.predicate = NSPredicate(forTasksWithinNumberOfDays: 10, ofDate: NSDate()) 

我已经添加了这个展示我认为我需要遵循什么样的结构...

回答

0

听起来就像你试图创建一个返回实例的类方法的NSPredicate

您的扩展需要是这样的:

import Foundation 

extension NSPredicate { 
    static func forLiftLogFilter() -> NSPredicate? { 
     if let logFilter = UserDefaultsManager.sharedInstance.logFilter?.rawValue { 
      return NSPredicate(format: "lift.liftName = [c] %@", logFilter) 
     } else { 
      return nil 
     } 
    } 
} 

现在可以正确地调用这个类方法:

let filterPredicate = NSPredicate.forLiftLogFilter 
+0

@rmaddy嗨,我不认为这就是我想要做的,但话又说回来,我有点一个新手,所以我不一定知道我在说什么。我添加了一个我试图近似的代码示例。也许这将清除它。 'self.init()'可能会有所作为吗? – Jim

+0

另外,安迪在展示延伸部分时发表了评论,他说:“我可以轻而易举地制造某种工厂类型,这是相当的。”这与你的建议类似吗? – Jim

+0

您不能使用相同的方法,因为您没有任何参数传递给'init'方法来区分它与其他'init'方法。 – rmaddy

0

你并不需要一个方便的初始化。

只需拨打

var filterPredicate: NSPredicate = nil 
    if let logFilter = UserDefaultsManager.sharedInstance.logFilter?.rawValue { 
      filterPredicate = NSPredicate(format: "lift.liftName = [c] %@", logFilter) 
    } 

当您需要它。

或者,如果你想为一个类范围的使用:

private lazy var filterPredicate: NSPredicate = { 
    if let logFilter = UserDefaultsManager.sharedInstance.logFilter?.rawValue { 
     return NSPredicate(format: "lift.liftName = [c] %@", logFilter) 
    } 
    return nil 
} 
+0

由于没有名为'forLiftLogFilter'的类,因此这不起作用。这只是OP想要用于该方法的名称。 – rmaddy

+0

还要注意,一个便捷的init方法必须调用一个指定的init。这个实现不会那样做。 – rmaddy

+0

您的编辑仍然无效。 OP没有任何需要传递给扩展中的这个'init'的东西。 – rmaddy