0

I have a simple Swift extension on NSManagedObject, in which I have a parametrized method for finding a single object - the signature looks like:

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

I'm trying to call this from Objective-C, but it seems like it cannot be seen. If I create a non-parameterized version I can see and call it just fine from Objective-C:

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

Is there any way for ObjectiveC to be able to reach the parameterized version of the call?

I would use Self like so:

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

using the technique found here:

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

However, that causes the Swift compiler to segfault when compiling the code (Xcode 6.3.1, or Xcode 6.4 beta 2).

Edit: Here's a link with the full source of the framework I'm trying to build, including bonus Swift compiler crashes caused by templated methods:

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

3
  • Generics can not be used from Objective-C, see "Using Swift from Objective-C" in developer.apple.com/library/ios/documentation/Swift/Conceptual/…. – The second part of your question is unclear to me. Does the referenced code cause a compiler crash or your code which is based on that? Can you give an example demonstrating the problem? Commented May 1, 2015 at 19:17
  • The referenced code based on Self causes a compiler crash, yes. Very sad as I think that would work exactly as I wanted. I'll upload a sample project later after I've run a few more tests, and make sure the latest XCode beta does not fix this issue. Commented May 1, 2015 at 20:17
  • I have checked my code from stackoverflow.com/a/27112385/1187415 again. It compiles and works as expected. I have added a findFirst() variant as an answer, hope that is what you are looking for. Commented May 1, 2015 at 20:22

1 Answer 1

1

Generic methods are not visible from Objective-C. However you can use the ideas from How to use generic types to get object with same type to define a findFirst() class method which returns Self? (the Swift equivalent of instancetype) without being generic:

// 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
        }
    }
}

This can be used from Swift

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

and from Objective-C:

YourEntity *obj = [YourEntity findFirst:context withPredicate:nil];
Sign up to request clarification or add additional context in comments.

12 Comments

Self is great, but as I explained I cannot use Self because it cause the Swift compiler to segfault (So I cannot even compile the code).
@KendallHelmstetterGelner: Strange, that code does compile in my Xcode 6.3.1.
The code probably compiles in most circumstances. In the case of my specific class it segfaults he compiler using any form I can think of to try.
@KendallHelmstetterGelner: Are you using Xcode 6.3.1? Could you provide a (minimal) project demonstrating the problem?
Will put one up after I verify it's still a problem with the latest Beta XCode.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.