user1689158
user1689158

Reputation: 169

Adopting Objective-C protocol and returning NSArray

I have a delegate class coded in Swift. I have an Objective-C class that has a delegate property of this Swift class. The Swift delegate class adopts an Objective-C protocol with a required property of type NSArray*. The Swift code builds a mutable array class var then returns that as [AnyObject].

The building of the mutable array and the assignment of that to the Swift class var works, but sometimes the function returns nil back to my Objective-C class.

When I set a breakpoint and step through line by line it works, but if I just let it run it returns nil every time.

I have also put in log statements that verify the Swift class builds the mutable array every time but the Objective-C code keeps getting nil. The only thing I have gotten to work is to change my Objective-C protocol property to NSMutableArray but that seem like I am bypassing the problem. How can I make this work using NSArray?

If I make the Swift code return NSArray! I get a compile error saying the Swift class does not implement the required delegate method.

If I change the Swift code to return

Array<AnyObject>

it compiles but still has the same problem of returning nil to my Objective-C class.

The Objective-C protocol looks like this:

@protocol MySocialDelegate <NSObject>
-(NSArray*)availableChannels;
@end

The Swift delegate class looks like this:

class MySocialDelegateSwiftClass: NSObject, MySocialDelegate {

    private var socialChannels = NSMutableArray()

    func availableChannels() -> [AnyObject]! {

        if ( self.socialChannels.count == 0 ) {
            let channel = ...getChannel()
            if ( channel != nil && channel?.guid != nil ) {
                self.socialChannels.addObject(channel)
            }

            if( someCondition ) {
                let channel = ...getChannel()
                if ( channel != nil && channel?.guid != nil ) {
                    self.socialChannels.addObject(channel!)
                }
            }
        }

        // self.socialChannels will contain 2 objects

        return self.socialChannels as [AnyObject]
    }
}

And the Objective-C class that calls into that Swift delegate looks something like this:

ViewController *vc = [[UIStoryboard storyboardWithName... 
vc.socialDelegate = instanceOfMySocialDelegateSwiftClass;
if([vc.socialDelegate respondsToSelector:@selector(availableChannels)])
    vc.availableChannels = [vc.socialDelegate availableChannels];

// vc.availableChannels will be nil

Upvotes: 1

Views: 1408

Answers (2)

user1689158
user1689158

Reputation: 169

I fixed my issue. The Objective-C code was trying to assign the NSArray returned from the Swift code to a weak property. I never even noticed the weak property. I changed it to strong and it works. I thought the issue was with the cast to AnyObject.

Upvotes: 0

timgcarlson
timgcarlson

Reputation: 3146

Have you tried returning a NSArray in the Swift implementation of availableChannels?

private var socialChannels = NSMutableArray() 

func availableChannels() -> NSArray? {
   ...
   return self.socialChannels  // socialChannels is a NSMutableArray
}

Upvotes: 0

Related Questions