Objective-c output parameter in Swift

The Objective-C function in the Pinterest API is defined as:


(void)getAuthenticatedUserBoardsWithFields: (NSSet *)fields
success:(PDKClientSuccess)successBlock
andFailure:(PDKClientFailure)failureBlock;


fields is an output parameter that will be populated by the function.


This is how I invoke the function in Swift, having already created a bridge file, which gives me access to the Objective-C function.


var fields = Set<AnyHashable>()


PDKClient.sharedInstance().getAuthenticatedUserBoards(withFields: fields,
     success: { (_ pdkResponseObject: PDKResponseObject?) in
        if let pdkResponseObject = pdkResponseObject
        {
           print(fields)
        }
      },
      andFailure: { (_ error: Error?) in
         if let error = error
         {
             print(error.localizedDescription)
         }
      })


I am getting a "Request failed: bad request (400)" response.


So, how do I represent (NSSet *)fields as an output parameter of an Objective-C function when invoking the function in Swift?


Thanks

Replies

The set isn't an output parameter in the code you've shown. Not even in the Obj-C version. Since the parameter type is "NSSet*", you're passing an immutable object (or an object that is treated as immutable, even if it's actually a NSMutableSet). That means it can't return anything.


So, somewhere along the line, something is being fudged, and it's not clear what.


It's also not clear what you mean by "a bridge file". Is this a bridging header? Or an Obj-C source file that contains a bridging function? In particular, the automatically bridged name of method "getAuthenticatedUserBoardsWithFields:success:andFailure:" would be "getAuthenticatedUserBoards(field:success:andFailure)" in Swift, which is not what you have.


In general, if you want to pass a Swift mutable (var) Set, you would need the parameter to be declared "inout Set<…>". That would allow the function to modify the original set. However, I don't believe there's any automatic bridging between this and NSMutableSet, so you would still need some kind of wrapper function.


I dunno, I may not have this exactly right, but there do seem to be more moving parts to this than you've shown so far. Can you clarify?

Thanks Quincey


1. By a "bridge file", I mean the bridging header file that is needed to call an Objective-C function in Swift.


Here is the content of the bridging header file, where I import "PinterestSDK/PDKClient.h", allowing me to reference the Objective-c function it contains from Swift


//

// Use this file to import your target's public headers that you would like to expose to Swift.

//

#ifndef MyApp_Bridging_Header_h

#define MyApp_Bridging_Header_h


#import "PinterestSDK/PDKClient.h"


#endif / MyApp_Bridging_Header_h */


2. Here is the definition of the objective-c function in the .h file: Note that the "fields" parameter is used to return data from the api


This is the value that I am having problems referencing in Swift.


/*

* Get a list of the authorized user's boards. The reponse can be used to

* get the next page of boards.

*

* @param fields The board fields that will be returned by the api

* @param successBlock Called when the API call succeeds

* @param failureBlock Called when the API call fails

*/

- (void)getAuthenticatedUserBoardsWithFields:(NSSet *)fields

success:(PDKClientSuccess)successBlock

andFailure:(PDKClientFailure)failureBlock;




3. Here is the actual objective-c function in the .m file:


- (void)getAuthenticatedUserBoardsWithFields:(NSSet *)fields

success:(PDKClientSuccess)successBlock

andFailure:(PDKClientFailure)failureBlock

{

NSDictionary *parameters = @{@"fields" : [[fields allObjects] componentsJoinedByString:@","]};

[self getPath:@"me/boards/" parameters:parameters withSuccess:successBlock andFailure:failureBlock];

}


4. Here my Swift code where i am trying to use the Objective-C function. XCode is suggesting tha I define the "withFields" parameter as a Set<AnyHashable>.


PDKClient.sharedInstance().getAuthenticatedUserBoards(withFields: Set<AnyHashable>,

success: PDKClientSuccess!,

andFailure: PDKClientFailure!)


Note that I need to provide 3 values, the last 2 are just closures to be invoked on success and failure. The problem I have is with the 1st parameter, which will be used to return data from the call.


I don't know how to define the 1st parameter in Swift.


Thanks

No, the first parameter isn't for returning anything. It's just a list of the fields you want information for. (This is not a Swift issue. You are expecting something from the API that just isn't true.) I assume the information corresponding to the requested fields is a parameter to the PDKClientSuccess closure, but you'll have to research that to find out.

Hi,


Below is exactly what is in the API, including the comments.


This function is to return the boards that a user has on Pinterest.


So, it is my understanding, based on the comments below, that the list of board names is to be returning via the "fields" parameter.


* Get a list of the authorized user's boards. The reponse can be used to

* get the next page of boards.

*

* @param fields The board fields that will be returned by the api

* @param successBlock Called when the API call succeeds

* @param failureBlock Called when the API call fails

*/

- (void)getAuthenticatedUserBoardsWithFields:(NSSet *)fields

success:(PDKClientSuccess)successBlock

andFailure:(PDKClientFailure)failureBlock;

Hi,


I was able to find the example on the web:


PDKClient.sharedInstance().getAuthenticatedUserBoardsWithFields(NSSet(array: ["id","name"]) as Set, success: { (responseObject: PDKResponseObject!) -> Void in

for object in responseObject.boards(){

let board = boardsModel()

board.boardName = object.name

board.boardId = (object.identifier)!!

self.boards.append(board)

}


So, the first parameter, (NSSet *)fields, in Objective-c, is defined as the following in Swift:

NSSet(array: ["id","name"]) as Set


I don't understand that and will need to research it more.


But, it seems to work.


Thanks

Hi,


The responseObject that is return as part of the success closure contains the data from the API.


I am not sure what the fields parameter is used for except may to determine the data type of the data that is returned.


Thanks

Yes, that what it means:


@param fields The board fields that will be returned by the api


In less abbreviated form:


A set containing the names of the fields for which data is returned, in the authorized boards requested by this API.

Hi,


But, it is the responseObject that contains the boards.


I don't even use the fields value.