I have a weird problem that hopefully someone could shed some light on.
I have an ipad app in the AppStore that was released when 3.2 was the only
available iOS for ipad. App ran fine on this iOS but as soon as 4.2.1 came out for ipad
and some of my users therefore updated to the new iOS the app now crashes when a
certain UIBarButtonItem is pressed. In the interim from iOS 3.2 to when iOS
4.2.1 came out i submitted no updates so it was the exact same app running on
each iOS yet i had this problem only on 4.2
After symbolicating in Organizer and viewing the Distribution build crash report
I am able to at least see the line of code that is causing this...
while(i < [filteredData count]) {
thats it!!...just a simple check during a while loop. The last thing in the crash
log points to the above line of code....
filteredData is a NSMutableArray that is definitely allocated/initialized at
this point. It is actually used in another piece of code before this with no
problems.
Again, this line of code gave my app no problems on iOS 3.2 but on iOS 4.2.1 it
causes EXC_BAD_ACCESS (SIGSEGV)
When i install the app on my device via xcode with a debug or release config it works perfect but when installing from AppStore (distribution build) it crashes and only on 4.2!
Just to clarify.....
app works perfect on debug AND distribution modes on 3.2
app works perfect on debug mode on 4.2 BUT app crashes on distribution mode on 4.2
Any thoughts? .....cuz i'm confused/lost
Thanks for taking the time
Possibly an optimisation made by the compiler in Release builds causes this, especially as you dont get the issue in Debug
Can you refactor to...
NSUInteger count = [filteredData count];
while(i < count) {
Or is filteredData mutating in the loop?
NSUInteger count = [filteredData count];
while(i < count) {
blah;
blah;
count = [filteredData count];
}
Related
I'm trying to implement a gamecenter aware app targeted to iOS 6. To give some info on the environment I'm working on mac os 10.7.5 with XCode version is 4.5.2 and xcode is running iphone and ipad simulator version 6.0. The problem is I cannot connect to gamecenter in sandbox mode neither through ipad or iphone simulator, but the same code works as desired while testing in my iphone.
I followed the gamecenter programming guide in apple's developer library and I got this atm it is called from applicationDidFInishLaunching in appdelegate:
- (void)authenticateLocalUser:(UIViewController *)currentViewController
{
if (!gameCenterAvailable) return;
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil)
{
[currentViewController presentViewController:viewController animated:YES completion:nil];
}
else if (localPlayer.isAuthenticated)
{
NSLog(#"Player authenticated");
}
else
{
NSLog(#"Player not authenticated");
}
NSLog(#"Error: %#",error);
};
}
It outputs:
Error: Error Domain=GKErrorDomain Code=2 "The requested operation has been cancelled."
UserInfo=0x8690510 {NSLocalizedDescription=The requested operation has been cancelled.}
GKSConnSettings: set server: {
"gk-cdx" = "17.173.254.218:4398";
"gk-commnat-cohort" = "17.173.254.220:16386";
"gk-commnat-main0" = "17.173.254.219:16384";
"gk-commnat-main1" = "17.173.254.219:16385";
}
I already tried hosts file fix though my OS is not 10.8.2 but it didn't help. https://devforums.apple.com/thread/168811?tstart=0
Any idea what can be the possible cause?
Edit: Well, it turns out the output part starting with GKSConnSettings does not indicate any problems, that's the regular output while connecting to game center as I understood from what I read over internet. I printed the actual error message (GKErrorDomain = 2 ...) inside the authentication block.
I got the inspiration from : https://stackoverflow.com/a/8115807/837244, and decided to log in to game center account with a different piece of code. So in viewdidload I normally called:
[[GCHelper sharedInstance] authenticateLocalUser:self];
Now I commented that out, accessed game center through below URL scheme, logged in to my account and after that logged out.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"gamecenter:"]];
And lastly reverted back by commenting out URL code and using the original code. Now it works fine, I guess the problem was that a game center account was already hooked up in simulator and it denied every login request bc of that. Hope apple goes clearer with error messages, it took a month to fix such a simple issue, may this help to others.
I know this question references specific Xcode and iOS simulation versions, but if your simulator is already logged in one account, and you don't mind losing whatever data you've got on the simulator (chances are small, but you never know), you can simply reset the settings and data on it.
Go to:
Simulator -> Reset Content and Settings...
...and confirm the action when prompted.
This is certainly true for Xcode7.x running an iOS 9.x simulator, someone else might be able to verify whether it's true for earlier versions (especially as I've unearthed quite an old question and answer).
Animal451
Necrothreadomancy: +1
I have an ARC lite enabled app (ARC enabled without zeroing weak reference, Apple LLVM 4.0). Deployment target set to iOS 4.0. It's been tested on iOS 4.0 to 5.1.1. It always works fine when I use debug build and install through Xcode, but when I create an adhoc build with release configuration, it always crash during launch on 2nd gen iPod with iOS 4.2.1, but works fine on other devices (even 3rd gen iPod with iOS 4.3).
The crash log says
symbol not found: _objc_retainAutoreleasedReturnValue
and it crashes when method main is called (then it's dyld_stub_binder, dyld::fastBindLazySymbol)
I did some search and this crash normally happens when an arc enabled library is included in a project without arc. But in my case arc is enabled for the whole project.
Any clues?
Thanks very much.
[EDIT] Update: I can use NSLog to debug the adhoc build.
The main.m is like:
int main(int argc, char *argv[]) {
NSLog(#"ok before entering autorelease pool");
#autoreleasepool {
NSLog(#"ok after entering autorelease pool");
return UIApplicationMain(argc, argv, nil, NSStringFromClass([XXX class]));
}
}
NSLog(#"ok after entering autorelease pool") gets called successfully, but application:didFinishLaunchingWithOptions: is never entered.
It seems that it's related to the command line build tool. I used to use xcodebuild command to archive the adhoc build:
xcodebuild -scheme myscheme clean build archive
And got this crash.
Then I tried archiving from Xcode, the adhoc build actually works fine on all devices. So weird (keep in mind that the command line built adhoc worked for devices newer than iPod 2nd gen).
For now I'll just use the Archive button in Xcode. But I posted this question in Apple dev forum:
https://devforums.apple.com/message/711334
My answer: How i come out from the same problem.
Steps:
1.First make the all the changes in the code sign column and make sure that all the setting are work same as you want in the project tab and target tab as well.
2.Just making all the setting in the first step like selecvting correct provsioning and specify accurate bundle indetifier then now make the xcode quit .
3.After 2 step just restart you computer and then make build for the profile that you selected in first step.
Now its working fine ,hope so this answer may be help you as well.Anyway its my solution of the above problem.....:)
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'm working on a new app that I want to be universal for the iPhone and iPad. I started out with the "Create a Window-based app" wizard, and it created separate app delegates in "iPhone" and "iPad" groups. Since I already was quite familiar with iPhone dev, I did that part of my project, and now I'm ready to do some iPad stuff.
So... I started out by adding a UISplitViewController to my iPad delegate, switch the Active SDK to 3.2, and it works! But when I switch back to 3.1.3, and try to run it in the simulator, Build and Go fails. For starters, I see:
...path.../iPad/AppDelegate_Pad.h:13: error: expected specifier-qualifier-list before 'UISplitViewController'
I've got my Base SDK set to 3.2 and my Deployment Target set to 3.1.3. I thought that was enough. But I also have found in the documentation this method to conditionally compile:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
MyIPadViewController* vc;
// Create the iPad view controller
#else
MyIPhoneViewController* vc;
// Create the iPhone view controller
#endif
So do I need to do this everywhere? It seems like an awful lot of code to add (that I'll be getting rid of in a short time for 4.0 anyway) so I feel like I must be doing something wrong. And, I don't even have any idea how this works for things like #property or #synthesize declarations.
tl;dr version of the question - did I miss a setting somewhere?
I use this C function to help keep the code concise:
BOOL isPad() {
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}
Another thing I do, when I have different xib files for iPhone vs iPad. I have a stripPadSuffixOnPhone() function that helps keep the code simpler:
// Load/create the Delete table cell with delete button
self.deleteCell = [Utilities loadNib:stripPadSuffixOnPhone(#"DeleteCell~ipad")
ClassName:#"DeleteCell"
Owner:self];
Things like that can make coding more straightforward and a lot less conditionals. Still have to test everything twice though.
Quite the opposite. A universal app runs the same binary on iPhone and iPad so you cannot use conditional compilation to differentiate between the two version. But you need to use the macro Apple cites in the documentation:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad-specific code
} else {
// iPhone-specific code
}
Here's what works for me:
Build your app using SDK 3.2.
Switch the active SDK to iPhone Simulator 3.1.3 (or whatever).
From the Run menu select Debug (not Build and Debug).
The binary built under 3.2 will be installed in the 3.x simulator without rebuilding. When you are finished don't forget to set your active SDK back to 3.2.