What is equivalent of respond to selector for background tasks? I found the code in Objective-C. I'm trying to get the same in Swift.
Here is the Objective-C code:
if ([application respondsToSelector:#selector(beginBackgroundTaskWithExpirationHandler:)]){
bgTaskId = [application beginBackgroundTaskWithExpirationHandler:^{
})
Swift code:
if application.responds(to: #selector(self.beginBackgroundTaskWithExpirationHandler)) {
bgTaskId = application.beginBackgroundTask(expirationHandler: {() -> Void in
print("background task \(UInt(bgTaskId!)) expired")
})
It's saying BackgroundTaskManager has no member 'beginBackgroundTaskWithExpirationHandler'.
What is the exact thing we can replicate in Swift 3?
Unless you are attempting to support iOS 3 or earlier, there is no need to check for the existence of the selector since it was added in iOS 4.0.
But the Swift selector would be: beginBackgroundTask(expirationHandler:).
Here's a simple trick when trying to convert an Objective-C API into Swift. Pull up the API documentation in Xcode or online. Choose the Objective-C APIs. Find the method you wish to convert. Then switch the documentation to the Swift APIs. In a case like this you will now see the same method but in Swift.
Related
A particular SpriteBuilder app I am developing utilises SpriteBuilder SB version 1.4.7, X Code 6.2 with iOS 8.2 iPhone deployment and func
ccPhysicsCollisionBegin(pair: ...) -> Bool { return true }.
The app runs perfectly on the iPhone 5S and iPhone 6 simulators but terminates at the above function when I use an iPhone 5, iPhone 4S or iPad 2 simulator and also when I try to load it on my 5th generation iTouch.
The error message I get is
'NSInternalInconsistencyException' reason: 'CCPhysicsCollisionBegin
delegate methods must return a BOOL.'
Can anyone advise me why this might be?
You can also call the function and return an ObjCBool instead.
For example:
ccPhysicsCollisionBegin(pair: ...) -> ObjCBool{ return true }
I just had the same issue and I found some hotfix for this to change in the Cocos Code. Seems it's a bug in CCPhysicsNode.m due to the differences between Objective-C (BOOL) and Swift (Bool). Until they fix the bug, replace the condition with:
NSAssert((strcmp(returnType, #encode(BOOL)) == 0 || strcmp(returnType, "B") == 0), #"CCPhysicsCollisionBegin delegate methods must return a BOOL.");
Hope this helps someone.
My code suddenly can't be compiled in Xcode 6.1 (I'm sure it's working in Xcode 6 GM and beta version). It shows the error message:
'NSInvocationOperation' is unavailable
My code is:
let operation = NSInvocationOperation(target:self, selector:"backgroundRun:", object:self)
Can anybody help? Thanks.
As of Xcode 6.1, NSInvocation is disabled in Swift, therefore, NSInvocationOperation is disabled too. See this thread in Developer Forum
Because it's not type-safe or ARC-safe. Even in Objective-C it's very very easy to shoot yourself in the foot trying to use it, especially under ARC. Use closures/blocks instead.
You have to use NSBlockOperation in Swift.
or addOperationWithBlock to NSOperationQueue
queue.addOperationWithBlock { [weak self] in
self?.backgroundRun(self)
return
}
This question already has answers here:
Alternatives to dispatch_get_current_queue() for completion blocks in iOS 6?
(7 answers)
Closed 9 years ago.
I am developing a chat application using xmppframework in iOS 5; it works perfectly.
But I updated my Xcode to 4.5.1, iOS 5 to iOS 6 and my Mac OS to 10.7.5, and the project did not work due to deprecation issues. I replaced all methods with new methods in iOS 6 except this one:
dispatch_get_current_queue()
How can I replace this method in iOS 6?
It depends what you need to achieve with this call.
Apple states that it should be used for debugging anyway.
Perhaps the queue does not matter (as you just need a background queue) so get a global queue with specific priority (dispatch_get_global_queue(dispatch_queue_priority_t priority,
unsigned long flags);)
OR,
If you do need to execute some pieces of code in the same queue , create a queue, retain it and dispatch all your tasks there.
How about using NSOperationQueue?
-(void) doSomeThing:(void (^)(BOOL success)) completionHandler
{
NSOperationQueue* callbackQueue = [NSOperationQueue currentQueue];
if(!callbackQueue) {
callbackQueue = [NSOperationQueue mainQueue];
}
dispatch_async(...,^{
// do heavyweight stuff here
// then call completionHandler
if(completionHandler) {
[callbackQueue addOperationWithBlock:^{
completionHandler(...);
}];
}
});
how i can exectute a function if the iOS version is above 4.* in a if statement?
Thanks
Please, take a look at weak linking of classes and methods in Apple's documentation — http://developer.apple.com/library/ios/#DOCUMENTATION/DeveloperTools/Conceptual/cross_development/Using/using.html they provide explicit instructions how to do support of multiple iOS'es in the same build. host answer from this big Apple's documentation:
if ([UIImagePickerController instancesRespondToSelector:
#selector (availableCaptureModesForCameraDevice:)]) {
// Method is available for use.
// Your code can check if video capture is available and,
// if it is, offer that option.
} else {
// Method is not available.
// Alternate code to use only still image capture.
}
Less flexible ways can be done on checking exact match of iOS by use of following code:
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
You can do breakdown of osVersion to components and analyze them separately as numbers.
Cases when you class is not available for some particular iOS type is more complex and it is better to review a link to the document provided above.
i'm trying to add printing features to an ios app.
while printing itself works fine, and the app works on ios > 4, i haven't figured out yet how to keep the ios 3.1 compatibility...
i guess the issue is this: completionHandler:(UIPrintInteractionCompletionHandler)
A block of type UIPrintInteractionCompletionHandler that you implement to handle the
conclusion of the print job (for instance, to reset state) and to
handle any errors encountered in printing.
once i add the block:
void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
};
the app won't even launch on iOS 3.1
probably because blocks aren't available there.
yes, i made sure that this code won't be run when launched on iOS 3.1...
if (([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.2) && ([UIPrintInteractionController isPrintingAvailable]))
so i wonder if there's a way to have printing support for iOS >4.2, but keeping it to run on iOS 3.1?
maybe there's a way to use a method instead of the "block"?
or how would be the correct way to have printing available on supported iOS devices, and remain backwards compatible to iOS 3.1?
just add -weak_framework UIKit to the project settings under "Other Linker Flags" and make sure you use conditional code for printing API.
Conditional code should check feature availability, not OS version:
if (NSClassFromString(#"UIPrintInteractionController")){
void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
};
}
Set your project target to iOS 3, and you're good to go.
The best practice for detecting if AirPrint is available is to use NSClassFromString. If you use this method in general, then you always know if exactly the class you want is available, without having to hard-code which features correspond with which version. Example code:
Class printControllerClass = NSClassFromString(#"UIPrintInteractionController");
if (printControllerClass) {
[self setupCanPrintUI];
} else {
[self setupCannotPrintUI];
}
That way your app can still work on previous iOS versions, although it won't be able to print from them.
I've been able to use this technique and run it on an iOS 3.0 device without any problems with the block code (the ^-based stuff). In my build settings, I have the Base SDK set to iOS 4.2, and the Deployment Target set to iOS 3.0.
I posted a sample Xcode project at the end of this blog post on printing in iOS. This is the project that successfully runs for me on a device with iOS 3.0 and another device with iOS 4.2. You may have to change the bundle identifier in the info.plist to get the code-signing to work for you, but that's independent of the printing stuff.
Set Deployment Target in your Project Settings to iOS 3.x. However, set the Base SDK to 4.2. Now you can use the 4.2 classes and iPhones running 3.x can install your app too.
Keep in mind that when you use a 4.2 class on an iPhone 3.x, the application will crash (so keep checking the system version on-the-go).
NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare:#"3.2" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending && [[UIDevice currentDevice]isMultitaskingSupported]) {
// >4.2
}
else {
//< 4.2
}
Note:
also change UIKit framework setting from "required" to "weak" this will help you to run application on iOs < 4.2 as well as iOs >= 4.2