【问题标题】:Objective-C calling parameterized Swift method crashes Swift compilerObjective-C 调用参数化 Swift 方法使 Swift 编译器崩溃
【发布时间】:2015-05-05 09:46:21
【问题描述】:

我在 NSManagedObject 上有一个简单的 Swift 扩展,其中我有一个用于查找单个对象的参数化方法 - 签名看起来像:

public class func findFirst<T:NSManagedObject>(inContext context : NSManagedObjectContext? = .None) -> T?

我试图从 Objective-C 中调用它,但似乎看不到它。如果我创建一个非参数化版本,我可以从 Objective-C 中看到并调用它:

public class func findFirstUntypedWithPredicate(predicate:NSPredicate?, inContext context : NSManagedObjectContext? = .None) -> NSManagedObject?

ObjectiveC 有什么方法可以达到调用的参数化版本?

我会像这样使用 Self:

public class func findFirst(inContext context : NSManagedObjectContext? = .None) -> Self?

使用此处找到的技术:

How can I create instances of managed object subclasses in a NSManagedObject Swift extension?

但是,这会导致 Swift 编译器在编译代码(Xcode 6.3.1 或 Xcode 6.4 beta 2)时出现段错误。

编辑:这是我正在尝试构建的框架的完整源代码的链接,包括模板化方法导致的额外 Swift 编译器崩溃:

https://www.dropbox.com/s/fixaj9ygdoi4arp/KiGiCoreData.zip?dl=0

【问题讨论】:

  • 泛型不能在 Objective-C 中使用,请参阅 developer.apple.com/library/ios/documentation/Swift/Conceptual/… 中的“在 Objective-C 中使用 Swift”。 - 我不清楚你问题的第二部分。引用的代码是否会导致编译器崩溃或基于此的代码?你能举个例子来说明这个问题吗?
  • 基于 Self 的引用代码导致编译器崩溃,是的。非常可悲,因为我认为这将完全按照我的意愿工作。稍后我会在运行更多测试后上传一个示例项目,并确保最新的 XCode 测试版无法解决此问题。
  • 我再次检查了来自stackoverflow.com/a/27112385/1187415 的代码。它按预期编译和工作。我添加了一个findFirst() 变体作为答案,希望这就是你要找的。​​span>

标签: objective-c swift generics


【解决方案1】:

通用方法在 Objective-C 中是不可见的。但是你可以使用 来自How to use generic types to get object with same type 的想法来定义一个findFirst() 类方法 它返回Self?(Swift 等效于instancetype) 通用:

// Used to cast `AnyObject?` to `Self?`, `T` is inferred from the context.
func objcast<T>(obj: AnyObject?) -> T? {
    return obj as! T?
}

extension NSManagedObject
{
    class func entityName() -> String {
        let classString = NSStringFromClass(self)
        // The entity is the last component of dot-separated class name:
        let components = split(classString) { $0 == "." }
        return components.last ?? classString
    }

    // Return any matching object, or `nil` if none exists or an error occurred
    class func findFirst(context : NSManagedObjectContext, withPredicate pred : NSPredicate?) -> Self? {
        let name = entityName()
        let request = NSFetchRequest(entityName: name)
        request.predicate = pred
        var error : NSError?
        let result = context.executeFetchRequest(request, error: &error)
        if let objects = result  {
            return objcast(objects.first)
        } else {
            println("Fetch failed: \(error?.localizedDescription)")
            return nil
        }
    }
}

这可以在 Swift 中使用

if let obj = YourEntity.findFirst(context, withPredicate: nil) {
    // found
} else {
    // not found
}

来自 Objective-C:

YourEntity *obj = [YourEntity findFirst:context withPredicate:nil];

【讨论】:

  • Self 很棒,但正如我解释的那样,我不能使用 Self,因为它会导致 Swift 编译器出现段错误(所以我什至无法编译代码)。
  • @KendallHelmstetterGelner:奇怪,该代码确实在我的 Xcode 6.3.1 中编译。
  • 代码可能在大多数情况下都可以编译。在我的特定类的情况下,它会使用我能想到的任何形式尝试编译器。
  • @KendallHelmstetterGelner:您使用的是 Xcode 6.3.1 吗?你能提供一个(最小的)项目来证明这个问题吗?
  • 在我确认最新的 Beta XCode 仍然存在问题后会放一个。
猜你喜欢
  • 2018-01-15
  • 2015-01-01
  • 2021-11-26
  • 1970-01-01
  • 2015-09-25
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
  • 1970-01-01
相关资源
最近更新 更多