Fred
Fred

Reputation: 33

Calling a Method on an Objective-C Delegate from Swift

I'm writing some Swift classes that build upon functionality in our objective-c app. I have a objective-c class with a delegate that conforms to a protocol. I'm trying to call a method on that delegate from inside of a Swift class I'm simplified it down to this.

FredTestProtocol.h:

@protocol FredTestProtocol
- (void) dumbMethod;
@end

FredTestClass.h:

#import <Foundation/Foundation.h>
#import "FredTestProtocol.h"

@interface FredTestClass : NSObject <FredTestProtocol>
@property (nonatomic, weak) NSObject <FredTestProtocol> *delegate;
@end

FredTestClass.m:

#import "FredTestClass.h"

@implementation FredTestClass
- (void) dumbMethod
{
    NSLog(@"Boy, this is a dumb method");
}
@end

FredSwiftClass.swift

import Foundation

class FredSwiftClass {
    func test()
    {
        let ocObject = FredTestClass()
        ocObject.delegate.dumbMethod() // Error occurs here.
    }
}

The indicated line produces the error "'NSObject' does not have a method named 'dumbMethod'" I've tried a lot of ways to eliminate the error, to no avail. I'm sure I'm missing something really fundamental. Can someone tell me how I should go about calling the delegate method from Swift?

Upvotes: 3

Views: 4226

Answers (2)

Fred
Fred

Reputation: 33

Pretty sure I've got it.

func test()
{
    let ocObject = FredTestClass()

    if let myDelegate = ocObject.delegate as? FredTestProtocol
    {
        myDelegate.dumbMethod()
    }
}

Upvotes: 0

Paulw11
Paulw11

Reputation: 114826

When Swift examines the property delegate it simply sees that is is an NSObject and the fact that you have noted that it implements a protocol is ignored. I can't find any specific documentation as to why this is the case.

You can address this in a couple of ways.

First, you can redefine your delegate property to use class anonymity, then Swift will just see it as some object that implements the protocol -

FredTestClass.h

#import <Foundation/Foundation.h>
#import "FredTestProtocol.h"

@interface FredTestClass : NSObject <FredTestProtocol>
@property  id<FredTestProtocol> delegate;
@end  

Then your Swift code will compile as written.

or you can leave your delegate definition as is and tell Swift that you want to access the delegate as an instance of an object that implements the protocol via downcast -

FredTestSwift.swift

import Foundation

class FredSwiftClass {
    func test()
    {
        let ocObject = FredTestClass()
        let theDelegate=ocObject.delegate as! FredTestProtocol
        theDelegate.dumbMethod()
    }
}

Upvotes: 2

Related Questions