How to write blocks (closures) in swift3 right way? - ios

I am trying to find how I can write this blocks in swift3, any help would be appreciated.
I am using obj-c PocketSDK in swift3 project.
https://github.com/Pocket/Pocket-ObjC-SDK
I can use this SDK fine with proper Bridge-Header settings, but still not sure how I can write blocks part.
obj-c
[[PocketAPI sharedAPI] callAPIMethod:#"get"
withHTTPMethod:PocketAPIHTTPMethodGET
arguments:arguments
handler:^(PocketAPI *api, NSString *apiMethod, NSDictionary *response, NSError *error) {
}];
This is the type def in PocketSDK.
-(void)callAPIMethod:(NSString *)apiMethod withHTTPMethod:(PocketAPIHTTPMethod)HTTPMethod arguments:(NSDictionary *)arguments delegate:(id<PocketAPIDelegate>)delegate;
typedef void(^PocketAPIResponseHandler)(PocketAPI *api, NSString*apiMethod, NSDictionary *response, NSError *error);
swift? (This shows error.)
let arguments: [String: Any] = [
"state": "unread",
"count": 20
]
PocketAPI.shared().callMethod("get", with: PocketAPIHTTPMethodGET, arguments: arguments) {
(api: PocketAPI,
apiMethod: String,
esponse: [AnyHashable:Any],
error: Error) in
}
#Updated
I could avoid the compile error without type def, but still get the unrecognized selector if I put arguments. If I set nil in arguments, I don't get it though. Anything wrong with the dictionary?
var arguments = [String : Any]()
arguments["count"] = 20
arguments["state"] = "unread"
PocketAPI.shared().callMethod("get", with: PocketAPIHTTPMethodGET, arguments: arguments) {
(api,
apiMethod,
response,
error) in
}
Error.
-[_SwiftTypePreservingNSNumber length]: unrecognized selector sent to instance 0x174624540 2017-08-15 14:05:51.345611+0900
Voicepaper2[1062:286998] * Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[_SwiftTypePreservingNSNumber
length]: unrecognized selector sent to instance 0x174624540'
* First throw call stack:

Solved! This was the final answer, thanks!
let arguments: [String: Any] = [
"state": "unread",
"count": "20"
]
PocketAPI.shared().callMethod("get", with: PocketAPIHTTPMethodGET, arguments: arguments) {
(api,
apiMethod,
response,
error) in
}

Related

FCNDEFMessage queryNDEFStatusWithCompletionHandler:]: unrecognized selector sent to instance

I'm trying to obtain some information about a NFC tag, the session is successfully started and after reading a tag, we jump into the following function:
- (void) readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray<NSObject<NFCNDEFTag> * > *)tags {
NSLog(#"NFCNDEFReaderSession didDetectNDEFs");
for (NSObject<NFCNDEFTag> *tag in tags) {
[tag queryNDEFStatusWithCompletionHandler:^(NFCNDEFStatus status, NSUInteger capacity, NSError * _Nullable error) {
if (!error) {
NSLog(#"success");
}
}];
}
}
We even get an iteration in the loop, but in the moment I try to obtain some information about my tag, the app crashes with the following error message:
019-11-06 16:01:12.955810+0100 MyApp[336:10691] -[NFCNDEFMessage queryNDEFStatusWithCompletionHandler:]: unrecognized selector sent to instance 0x281cfce30
2019-11-06 16:01:12.956200+0100 MyApp[336:10691] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NFCNDEFMessage queryNDEFStatusWithCompletionHandler:]: unrecognized selector sent to instance 0x281cfce30'
*** First throw call stack:
(0x18e45180c 0x18e179fa4 0x18e35536c 0x18e455c88 0x18e457a6c 0x100636cc0 0x100b097fc 0x100b0abd8 0x100b11b48 0x100b12718 0x100b1dadc 0x18e16ef88 0x18e171ad4)
libc++abi.dylib: terminating with uncaught exception of type NSException
Note: NFCNDEFTag is a protocol, so maybe it's connected with the way I'm declaring it: NSObject<NFCNDEFTag>?
Let's see the doc of NFCNDEFReaderSessionDelegate.
You have:
- (void)readerSession:(NFCNDEFReaderSession *)session
didDetectNDEFs:(NSArray<NFCNDEFMessage *> *)messages;
and
- (void)readerSession:(NFCNDEFReaderSession *)session
didDetectTags:(NSArray<__kindof id<NFCNDEFTag>> *)tags;
You wrote:
- (void)readerSession:(NFCNDEFReaderSession *)session
didDetectNDEFs:(NSArray<NSObject<NFCNDEFTag> * > *)tags {
Which is a mix of the two.
But in Objective-C, the selector will be:
readerSession:didDetectNDEFs & readerSession:didDetectTags: for the official one, and yours is readerSession:didDetectNDEFs, which is the same as the first one. So you lured the compiler and the runtime for yours.
But it doesn't care of the type of the parameters, so it's not the correct object, so it doesn't implement the method queryNDEFStatusWithCompletionHandler:, so it crashes with that error message.
How to fix it?
Implement the real delegate methods, with the good parameters types, use the correct one, you can't modify them like that as you want.

Objective-c Completion handler to Delphi

In Objective-c header I have this :
- (void)offerForConstraints:(RTCMediaConstraints *)constraints
completionHandler:(nullable void (^)(RTCSessionDescription *_Nullable sdp,
NSError *_Nullable error))completionHandler;
That I translate like this:
type
TWebRTCPeerConnectionOfferForConstraintsCompletionHandler =
procedure(sdp: RTCSessionDescription; error: NSError) of object;
procedure offerForConstraints(
constraints: RTCMediaConstraints;
completionHandler: TWebRTCPeerConnectionOfferForConstraintsCompletionHandler); cdecl;
But every time I call offerForConstraints I Have :
Access violation at address 0000000183398910, accessing address
000000004D555468 At address: $0000000183398910 (objc_msgSend + 16)
sometimes I also have this error:
-[__NSCFDictionary offerForConstraints:completionHandler:]: unrecognized selector sent to instance 0x1c0271b40
or this one:
-[_CFXNotificationObserverRegistration offerForConstraints:completionHandler:]: unrecognized selector sent to
instance 0x1c4273a40
Any idea what going wrong?

Swift 3 timed event

I have the following:
let processURLS = processingViewController()
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(processURLS.getURLsToSend),
userInfo: nil,
repeats: true)
When this event is triggered, I received the following error and I'm not sure why this doesn't work
2016-11-09 14:47:00.504932 AcumenJLR[3414:905978] * Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason:
'-[AcumenJLR.homeViewController getURLsToSend]: unrecognized selector
sent to instance 0x100d25c60'
* First throw call stack: (0x1816721c0 0x1800ac55c 0x181679278 0x181676278 0x18157059c 0x18215c8f8 0x1816208f4 0x181620608
0x18161fec4 0x18161dac0 0x18154c048 0x182fd2198 0x1875372fc
0x187532034 0x100114620 0x1805305b8) libc++abi.dylib: terminating with
uncaught exception of type NSException
Here is the getURLsToSend method
func getURLsToSend () {
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<URLsToSend> = URLsToSend.fetchRequest()
let context = getContext()
do {
//Get results
let searchResults = try getContext().fetch(fetchRequest)
print ("num of results = \(searchResults.count)")
//You need to convert to NSManagedObject to use 'for' loops
for urls in searchResults as [NSManagedObject] {
//get the Key Value pairs (although there may be a better way to do that...
//print("\(urls.value(forKey: "url"))")
let currentURL = urls.value(forKey: "url")!
//print(urls.value(forKey: "url")!)
completeLoadAction(urlString: currentURL as! String) { code in
if (code == 200){
context.delete(urls)
}
}
}
} catch {
print("Error with request: \(error)")
}
According to the target / action pattern the method specified in selector must be declared in the class specified in target in this case the current class self.
Either change the target or implement the method in self.
May be you have some paramter in method but you are not sending any value from there

Convert NSData to NSArray error

I use iCloudDocumentSync library to store/retrieve files in iCloud (iCloud Container). I have NSArray of objects and I convert this array to NSData:
NSKeyedArchiver.archivedDataWithRootObject(foundationArray)
and store file to iCloud. All works fine.
When i retrieved this file, and try convert NSData to NSArray I have error:
iCloud.sharedCloud().retrieveCloudDocumentWithName(backupName, completion: { (document, data, error) -> Void in
if error == nil {
print(document.fileURL)
// let addressBook = NSKeyedUnarchiver.unarchiveObjectWithFile(document.fileURL.URLString)
let addressBook = NSKeyedUnarchiver.unarchiveObjectWithData(data)
print(addressBook)
progressHUD.hide(true)
}
})
Eror:
*** Terminating app due to uncaught exception 'AutocodingException', reason: 'Expected 'url' to be a NSURL, but was actually a __NSCFString'
*** First throw call stack:
(0x185cc822c 0x19799c0e4 0x185cc816c 0x1003354f0 0x1003355c8 0x186b40d98 0x186b47fd0 0x186ad67d8 0x186b40d98 0x186b401b4 0x186b43154 0x186b42fec 0x10033540c 0x1003355c8 0x186b40d98 0x186b47fd0 0x186ad67d8 0x186b40d98 0x186b401b4 0x186b3f3dc 0x1000bdfc8 0x1000bcdf4 0x10076a0d0 0x101878fd4 0x101878f94 0x10187dc28 0x185c7f544 0x185c7d5ec 0x185ba8f74 0x18f6036fc 0x18a7aad94 0x1000cccd0 0x198046a08)
libc++abi.dylib: terminating with uncaught exception of type NSException
You have to convert your url into NSURL, you are passing to argument type that accept NSURL.
let UrlToUse = NSURL(string: url)

[NSURLSessionDataTask response]: unrecognized selector sent to instance

I have the following issue:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURLSessionDataTask response]: unrecognized selector sent to instance 0x7fced8599e60'
This is where it comes from:
GET("users/check_email", parameters: parameters, progress: nil, success: { sessionDataTask, response in
//the line with error
let statusCode = (sessionDataTask.response as? NSHTTPURLResponse)?.statusCode ?? 0
completionBlock(self.queryType?.mockStatusCode ?? statusCode, nil)
}) { sessionDataTask, error in
completionBlock(nil, NSError(responseError: error))
}
This happens when I try to mock a response. At some place of code I pass to success block:
var sessionDataTask = NSURLSessionDataTask()
success?(sessionDataTask, queryType?.mockResponse())
Something is wrong with sessionDataTask. NSURLSessionDataTask inherits from NSURLSessionTask which has response property. I don't know why I get this error.
If you declare your mock NSURLSessionDataTask like below, response will be nil.
Obj C:
NSURLSessionDataTask * sessionDataTask = [[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]] dataTaskWithURL:[NSURL URLWithString:#""]];
[sessionDataTask response];
Swift:
var sessionDataTask = NSURLSessionDataTask(NSURLSession(sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration()).dataTaskWithURL(NSURL(string: "")))
sessionDataTask.response()
Apple documentation says:
public class NSURLSessionTask : NSObject, NSCopying {
#NSCopying public var response: NSURLResponse? { get } /* may be nil if no response has been received */
}
So the only solution for this in Swift is:
var statusCode = 0
if sessionDataTask.respondsToSelector(Selector("response")) {
statusCode = (sessionDataTask.response as? NSHTTPURLResponse)?.statusCode ?? 0
}

Resources