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
}
Related
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.
I'm using matt gallagaher's AudioStreamer class. I've used it before in a project before ARC came along and it worked fine. When I added the class to a project which uses ARC, I came across lots of errors which I could fix by adding __bridge references etc...
So the app now runs, but when I start the streamer with [streamer start] I keep coming across this error which I don't know how to fix. The compiler stops at the function below in Audiostreamer.m with the error Thread 8: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0) - I don't know what to do from here...please help.
if (CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue) == false)
{
[self presentAlertWithTitle:NSLocalizedStringFromTable(#"File Error", #"Errors", nil)
message:NSLocalizedStringFromTable(#"Unable to configure network read stream.", #"Errors", nil)];
return NO;
}
I have exactly error with using FreeStreamer by muhku (good library, recommended).
Check that you give correct/not nulled url to AudioStreamer.
Give my StreamingKit library a go. It has the same functionality as AudioStreamer but is built with ARC and has quite a few additionally pieces of functionality.
https://github.com/tumtumtum/StreamingKit
I was getting the same problem, but I disable arc and now is working fine, the only problem that I got is that when I slide my slider I get a new value to seekToTime: , but is not playing starting from the new value. Any idea what that is ?
CoreAudio seems to work internally using exceptions, so if you have an exception breakpoint installed, this is what you will see. Just disable the breakpoints and it'll work.
My application was launched on the App Store on Oct. 5. It is working well on all iOS versions except iOS 5. On a particular class it is crashing on this statement:
[[self.tableView cellForRowAtIndexPath:lastIndex]
setAccessoryType:UITableViewCellAccessoryNone];
I am getting the error "Executing Bad Access."
Could this be because of ARC, introduced by Apple in iOS 5?
That indexPath should be retained.
Add [lastIndex retain]; before your statement.
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
I have a code for UIImage picker
photoImagePicker=[[UIImagePickerController alloc]init];
photoImagePicker.delegate=self;
photoImagePicker.sourceType=UIImagePickerControllerSourceTypeCamera;
photoImagePicker.mediaTypes=[UIImagePickerController availableMediaTypesForSourceType:photoImagePicker.sourceType];
[self presentModalViewController:photoImagePicker animated:YES];
photoImagePicker.showsCameraControls = YES; //Doesnot work on 3.0
photoImagePicker.navigationBarHidden = YES;
photoImagePicker.toolbarHidden = YES;
photoImagePicker.allowsEditing=YES; //Doesnt work on 3.0
Now everything works fine when the sdk is 3.1 or higher but when i put the os version as 3.0, the code starts showing errors. Turns out these methods were not present in 3.0 and so errors. I want to keep a mechanism which will enable these for higher versions(3.1) and at the same time work properly for 3.0 version.
How do i do it?
One solution i have thought of is to verify the version value and then put that code. But i am not sure how this is got. Any help will be appreciated.
I think you should be able to do it using Weak Linking. This article How to build a single iPhone application support both 2.x and 3.0 at the same time should also help.