I have an app that runs a synchronization algorithm.
When I build and run it in debug mode (onto my iPhone 5) it all works fine.
However, when I archive it and upload it to TestFlight and then download and install to the same iPhone 5 then part of the sync doesn't work.
It doesn't crash or anything, it just doesn't run that part of the sync.
The stupid thing is that it is a line of code inside a single function that isn't running. Everything else in that function does run.
I have no idea where to start looking for this.
EDIT
With help from Mindaugas I've found exactly why and which bit of code is not being run.
The function is...
- (void)uploadData
{
NSLog(#"pushing photos");
for (StoredImage *storedImage in self.recordArray) {
NSURL *url = [self urlForImageUpload:storedImage];
if (url == nil) {
continue;
}
ImageUploadOperation *uploader = [[OJFImageUploadOperation alloc] init];
uploader.image = storedImage.image;
uploader.url = url;
[self.recordQueue addOperation:uploader];
}
}
When I set the optimisation level to "Fastest, Smallest" it seems to mess the order of this function up.
When it enters I can see that there is a single object in the array and it enters into the loop. But then it completely skips past the first line NSURL *url = [self urlForImageUpload:storedImage]; and goes to the end. So the upload never actually starts and it moves onto the next item.
Release configuration by default uses different code optimization than Debug configuration, so some code lines can be optimized and skipped
You can check/change configurations at
Target -> Build Settings -> search for Optimization Level
Related
I'm building a cordova app (primarily for IOS & Android) in which the user can take an image, retake (, etc.) it and save it locally.
I'm currently struggling with the cordova cameraPlugin. So, here a short description of the problem.
When the user takes an image, it's saved locally in the apps temp folder and the user is able to view in in the UIWebView. On retaking, the image will be deleted from the temp folder and should not be available any longer (in RAM and local FS).
It works as long as the user doesn't retakes the image 2 or more times, if he does instead of the last image the first image will be referenced/rendered in WebView. After reopening the app, the image is displayed correctly.
An Example:
The user takes the first image. ==> cdv_photo_001.png
The second. ==> cdv_photo_002.png and the first one will be deleted (which seems to work correctly)
And the third. ==> cdv_photo_001.png and the second image will be deleted.
The third image will look the same as the deleted first one. This happens with every image after the third one.
It works fine after restarting the app
I've already tried to disable the App-Cache, delete the app cache before updating the image, refreshing the page and looking for answers online.
I'm getting an error when opening the camera UI, but I could not find a solution for it either.
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before
snapshotting or snapshot after screen updates.
The code for the camera Call:
function getPhoto() {
navigator.camera.getPicture(getPhotoOnSuccess, getPhotoOnFail, {
quality: 25,
destinationType: Camera.DestinationType.FILE_URL,
correctOrientation: true,
encodingType: Camera.EncodingType.PNG
});
}
In getPhotoOnSuccess I'm basically saving the image path to a db and appending it with jQuery to the view.
And the code to delete the image: (sidenote I`m new to Objective C)
- (void) deleteImageByPath:(NSString *)imagePath withSelector:(SEL)selector{
NSError *error = nil;
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *tempFolder = NSTemporaryDirectory();
if([mgr removeItemAtPath: imagePath error:&error] == NO) {
NSLog(#"File deleted");
}
//The files can be edited as well, so there can be two files in different directories
if(error != nil){
NSString *imgEl = tempFolder;
imgEl = [imgEl stringByAppendingPathComponent:imagePath.lastPathComponent];
if(![mgr removeItemAtPath:imgEl error:&error]){
NSLog(#"Old element couln't be deleted.");
}
}
[self performSelector:selector withObject:error];
}
The file is not in the directory anymore after deleting it, so I guess it works.
An important detail could be, that I wrote my own IOS cordova plugin, because the method for the file system access provided by cordova sucks.
So thats it.
The specific question is: Why and how is this happening and is there a chance to change this behavior? If yes, how should I proceed?
By the way, I`m using cordova 3.1.0 and the build target is IOS 7.
Thanks in advance.
Ok folks, I finally got it.
The whole problem was not related to my code or any of the cordova code.
So why did it happen? ==> I don't exactly know that, for it seems that this bug or whatever you might call it, has occurred to many people.
And they all tried to delete or deactivate the cache as I did, some of their problems are very close to my own but most aren't, so it took a while til I found a solution.
I read this thread and tried to append a timestamp to the image path and it worked!
My conclusion to this it, that there might be a problem with the UIWebView and the cache management.
Or it might proof as a general WebView problem, I will be able to check that in a few days on an Adroid device.
[UIImage imageNamed:filename]
This method returns null only on the device.
I know it's known problem and it's usually due to the fact that simulator is case insensitive.
I have tried solutions proposed here: UIImage imageNamed returns nil
But nothing worked out for me.
The case is simple: I have 4 files named:Bar#2x~ipad.png, Bar#2x~iphone.png, Bar~ipad.png, Bar~iphone.png.
All of them are in project with target checkbox checked.
NSLog(#"%#",[UIImage imageNamed:#"Bar"]);
That line of code gives me null for device and I really have no idea what I'm doing wrong right now.
I did have such a problem recently too.
After playing with filenames and paths sometimes it helps when you clean and rebuild your project.
I found myself in the same situation recently.
The solution in my case was adding the extension to the file name.
[UIImage imageNamed:#"Bar.png"]
Completely clean your build and redo it:
delete the app from the device
option-clean the whole build directory in Xcode (⌘-Shift-K)
quit xcode
delete ~/Library/Developer/Xcode/DerivedData
restart xcode, build and run
This just happened to me, and to discover was very tough: I had one image which where nil just on device
logoWhite.png
my code:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"LogoWhite"] forBarMetrics:UIBarMetricsDefault];
After a while of debugging, I noticed that the name of the image is beginning with capital case letter. Obviously this doesn't matter on OSX with a ignore case file system. iOs file system isn't, so the image worked on the simulator but not on the device.
I bet that all the solutions about cleaning derived data and rebuild did randomly end with renaming the image, and this would do the trick as well. Just posting here for future reference :)
I encountered this issue and just fixed it. I listed the solution below as a reference.
I have several images, and use [UIImage imageNamed:filePath] to show them. All of images displayed well except 1 on simulator/device, but all of them can be seen on OS X. For that image, [UIImage imageNamed] always return null.
After few minutes' investigation, I found that the image cause problem is far big in file size: 4.1M. Others are all around 800kb. They have nearly same size in dimension.
Then I try to open it in image editor, then re-save it. After this, the size dropped to 800k. problem solved.
The reasons I guess,
[UIImage imageNamed:filePath] has a max file size limit? (low possibility, but need to check official document)
the image itself has some error. But OS X has better tolerance than iOS. so iOS cannot read and return null. This issue is like OS X can play more types of video files than iOS since it support more codecs.
so if you encounter this issue in the future, take a few seconds look at the file size. Hope help.
This is an odd problem, which I hadn't seen until this week.
Below are my findings, and a workaround to your problem.
In my iPhone app, I download an image and store it locally, and this had always worked fine.
But now when I run the same code, it was suddenly failing to create a UIImage out of it using the imageNamed function, and now it was returning nil.
Three notes though:
This exact code did work before, using the same source code and .png image files. I'm not sure if my copy of XCode 6.x or iOS 8.x quietly updated itself in the meantime.
The code continues to work okay (with the same image file) on the iPhone simulator. It just doesn't work on a real device.
Take a look at the code below. When UIImage:imageNamed failed, I ran some code to check if the file actually existed.. and it did. Then I loaded the binary data from the file using NSData:contentsAtPath (which also proves that the file exists and was in the right folder), then created a UIImage out of that, and it worked fine.
Huh ?!
UIImage* img = [UIImage imageNamed:backgroundImageFilename];
if (img != nil)
{
// The image loaded fine (this always worked before). Job done.
// We'll set our UIImageView "imgBackgroundView" to contain this image.
self.imgBackgroundView.image = img;
}
else
{
// We were unable to load the image file for some reason.
// Let's investigate why.
// First, I checked whether the image was actually on the device, and this returned TRUE...
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:backgroundImageFilename];
if (fileExists)
NSLog(#"Image file does exist.");
else
NSLog(#"Image file does not exist.");
// Next, I attempted to just load the bytes in the file, and amazingly, this also worked fine...
NSData *data = [[NSFileManager defaultManager] contentsAtPath:backgroundImageFilename];
if (data != nil)
{
// ..and then I COULD actually create a UIImage out of it.
img = [UIImage imageWithData:data];
if (img != nil)
{
// We have managed to load the .png file, and can now
// set our UIImageView "imgBackgroundView" to contain this image.
self.imgBackgroundView.image = img;
}
}
}
As I said, this code does provide a workaround for this problem, but it's very odd that it's suddenly started happening.
And, I should say, I did try the other suggestions in this thread, cleaning the project, removing the DerivedData, completely removing the app from the device, and so on, but they didn't make any difference.
I would be interested in knowing if anyone else hits this issue, and finds that my code sample works for them.
Update
I'm an idiot.
I'm not sure if the UIImage:imageNamed function has changed or something (and if so, why it continues to work okay on the iPhone 8.1 Simulator), but I found the following one line does work okay:
UIImage* img = [[UIImage alloc] initWithContentsOfFile:backgroundImageFilename];
So it seems as though you should use this function for loading images which aren't a part of your app's bundle.
I also have same issue then : XCode - Build Phases - Copy Bundle Resources -{see image is available or not}- add{image} - clean - delete app - Run .
I would like to add one more important point to all the above solutions
Make sure you add your image resource to right target
By mistake if Developer mess-up link with resource and target then conditions arise.
if you have multiple target then double check the resource are set to correct target.
Attached screenshot example in case of resource link between multiple targets.
I am localizing my iOS app, and in the Simulator it runs correctly in my chosen language every time.
When testing on my iPhone 5, it only detects the language properly the first time the app runs. Every other time I recompile and run my app on the device, it detects "en" as the language, even though I am testing with Español ("es") selected.
I detect the language using:
[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]
I've also used:
[[NSLocale preferredLanguages] objectAtIndex:0]
Same result.
If I kill the app after the first run, and restart it on the device, it continues to detect the language properly.
But if I kill the app and then recompile/restart via Xcode after the initial run, it will load with "en" (English) detected instead.
After that, killing and re-starting the app continuously detects as English unless I delete the app completely, and recompile/reinstall/run the app via Xcode. The cycle then repeats... subsequent rebuild/restart without first deleting the app from the device results in misdetection.
All other apps on my device display with Spanish language the entire time. The entire UI shows in Spanish.
UPDATE: I've now tested on my iPad (3rd gen) also running iOS 6, and am experiencing the same behavior.
UPDATE 2:
In didFinishLaunchingWithOptions, I have this code to detect language: (language is an NSString*):
language = [[NSLocale preferredLanguages] objectAtIndex:0];
Followed by this debugging statement, to compare the value I'm getting, as well as a slightly different way of detecting it, just for debugging:
NSLog(#"Detected language: %# / %#", language, [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);
The output shows as "Detected language: es / es" when the app works properly in Spanish mode, and then shows as "Detected language: en / en" when it doesn't. Still no idea why it decides to load as English sometimes...
UPDATE 4: I appreciate everybody's answers, and I've tried the various suggestions. Unfortunately I was unable to award the +100 bounty as none of the suggestions seemed to fix the issue. If someone does ultimate find a solution that works for me, I will award another +50 bounty to them at that time.
UPDATE 5: I have updated from Xcode 4.5 to 4.5.2, and experiencing this same issue.
UPDATE 6: I have now created a new test project from scratch, and it works perfectly fine! Obviously something must be wrong in the way my project is laid out, or perhaps in one of the data files. I guess my next journey will be to re-create the project from scratch, copying file data over one by one...
UPDATE 7 (MONTHS LATER): Sadly, I am again facing this issue after temporarily resolving it (seemingly) by painstakingly recreating my project. On first load, the language is correctly rendered, but on subsequent loads, it reverts back to English.
SOLVED See my final solution below. Thanks for the help everyone. I may dole out some of the bounty since it will go to waste anyway.
I have FINALLY solved this problem after many months! Thanks to all for the help (I also had some good back and forth with an Apple developer via the dev channels).
TL;DR: I was accidentally syncing language preferences (among many other unexpected things) between devices, using my app's iCloud key value store (via MKiCloudSync)! Read on...
I am using a third-party class called MKiCloudSync, which helps with syncing [NSUserDefaults standardUserDefaults] to my app's iCloud key value store. My intention when I began using it was to let it handle some user favorites syncing in the background.
However, not understanding how standardUserDefaults works, what I didn't realize is that there are a lot of other things being written into standardUserDefaults other than just my own custom app settings!
So what was happening was this:
Start the app up for the first time. Fresh standardUserDefaults in place, and the internal "AppleLanguages" key that stores the ordered list of language preferences is correct based on the current device choices.
App displays properly in the designated language.
In the background, MKiCloudSync syncs ALL standardUserDefaults to iCloud. Conversely, if you had run this app elsewhere, say with an English set device, that device would have also synced it's language settings up to iCloud. So now this current running app is actually having it's language preferences overwritten.
BOOM ... next time the app is run, no matter what you have selected on the device, it's whatever was pulled down from iCloud that will be used as the default language!
What I plan to do to solve the issue with my next app update:
Use a forked version of MKiCloudSync that allows for syncing only whitelisted key names.
Add code that will do a one-time cleanup, first cleaning out the iCloud keystore for my app, then (based on this SO answer), calling this code to reset the user defaults:
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
In my testing so far, this sort of solves the issue... unfortunately, the user would have to restart the app for the language fix to kick in. However, my guess is most users are not experiencing this issue, as they are unlikely to be using multiple devices with different default languages.
In settings->general->international, there is an option to set the location language etc. if you set that to the language you are trying to test it will work if your code is correct.
I tested your steps on my iPhone 5 without issues. This leads me to think there's something else at play here: most probably there's something interferring with the way in which you're reading the locale value.
The steps I'd recommend you take to help you debug this issue are:
Post the complete code of the method in which you're obtaining the preferred language value. Make sure the method is executed each time the app is run.
Make sure the code you post includes the location of the NSLog directive you're using to test for the language setting.
Are you storing the preferred language somewhere else after the first run?
Try with following code:
LocalizationSystem.h===
#import <Foundation/Foundation.h>
#define AMLocalizedString(key, comment) \
[[LocalizationSystem sharedLocalSystem] localizedStringForKey:(key) value:(comment)]
#define LocalizationSetLanguage(language) \
[[LocalizationSystem sharedLocalSystem] setLanguage:(language)]
#define LocalizationGetLanguage \
[[LocalizationSystem sharedLocalSystem] getLanguage]
#define LocalizationReset \
[[LocalizationSystem sharedLocalSystem] resetLocalization]
#interface LocalizationSystem : NSObject {
NSString *language;
}
+ (LocalizationSystem *)sharedLocalSystem;
//gets the string localized
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment;
//sets the language
- (void) setLanguage:(NSString*) language;
//gets the current language
- (NSString*) getLanguage;
//resets this system.
- (void) resetLocalization;
#end
LocalizationSystem.m===
#import "LocalizationSystem.h"
#implementation LocalizationSystem
//Singleton instance
static LocalizationSystem *_sharedLocalSystem = nil;
//Current application bundle to get the languages.
static NSBundle *bundle = nil;
+ (LocalizationSystem *)sharedLocalSystem{
#synchronized([LocalizationSystem class])
{
if (!_sharedLocalSystem){
[[self alloc] init];
}
return _sharedLocalSystem;
}
// to avoid compiler warning
return nil;
}
+(id)alloc{
#synchronized([LocalizationSystem class])
{
NSAssert(_sharedLocalSystem == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedLocalSystem = [super alloc];
return _sharedLocalSystem;
}
// to avoid compiler warning
return nil;
}
- (id)init{
if ((self = [super init]))
{
//empty.
bundle = [NSBundle mainBundle];
}
return self;
}
// Gets the current localized string as in NSLocalizedString.
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment{
return [bundle localizedStringForKey:key value:comment table:nil];
}
// If this function is not called it will use the default OS language.
// If the language does not exists y returns the default OS language.
- (void) setLanguage:(NSString*) l{
NSLog(#"preferredLang: %#", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:#"lproj" ];
if (path == nil)
//in case the language does not exists
[self resetLocalization];
else
bundle = [[NSBundle bundleWithPath:path] retain];
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:l, nil] forKey:#"AppleLanguages"];
}
// Just gets the current setted up language.
// returns "es","fr",...
//
// example call:
// NSString * currentL = LocalizationGetLanguage;
- (NSString*) getLanguage{
NSArray* languages = [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"];
NSString *preferredLang = [languages objectAtIndex:0];
return preferredLang;
}
// Resets the localization system, so it uses the OS default language.
//
// example call:
// LocalizationReset;
- (void) resetLocalization{
bundle = [NSBundle mainBundle];
}
#end
This code works perfectly as you mentioned.
It worked for me and that game is live now app store, if you want to check(HueShapes).
Do you by chance use NSUserDefaults to save something language related?
Look into your Simulator App directory -> Library -> Preferences -> <YourAppBundleName>.plist
See: How to force NSLocalizedString to use a specific language for description of the NSUserDefaults method of setting a language.
Perhaps you just save your language and thus detection just returns the saved value.
I have a file handle set up to read the contents of stdout, and when I try to pull the data out of it using availableData it hangs, but only when the app is run manually on my device. When I run the app on my device through Xcode or on the simulator, it pulls the data out as expected and the rest of my code works perfectly. Any ideas what is happening? My code is below:
int pipefd[2];
pipe(pipefd);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
NSFileHandle *stdoutReader = [[NSFileHandle alloc] initWithFileDescriptor:pipefd[0]];
// this method writes output to stout
int result = [self createOutput:string1:string2];
// code hangs on this next line when app is run manually on device)
NSData *stdoutData = [stdoutReader availableData];
I am wondering if on my device, the createOutput method runs more slowly and so by the time I try to get data out of stdout there isn't any yet?
Well, it looks like iOS 5.1 doesn't allow writing to stdout anymore. For anyone interested in reading more, here's an informative blog post: http://spouliot.wordpress.com/2012/03/13/ios-5-1-vs-stdout/
I am using a UIManagedDocument in iOS 5.0, running the app on the simulator, using XCode 4.2 under OSX 10.6. The code in question looks as follows:
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.photoDatabase.fileURL path]]) {
// does not exist on disk, so create it
[self.photoDatabase saveToURL:self.photoDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self fetchFlickrDataIntoDocument:self.photoDatabase];
}];
} else if (self.photoDatabase.documentState == UIDocumentStateClosed) {
// exists on disk, but we need to open it
// *** the following line generates the message ***
[self.photoDatabase openWithCompletionHandler:^(BOOL success) {
//[self setupFetchedResultsController];
}];
} else if (self.photoDatabase.documentState == UIDocumentStateNormal) {
// already open and ready to use
[self setupFetchedResultsController];
}
Running the marked line creates the following message on the log:
2012-01-10 22:33:17.109 Photomania[5149:4803] NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid
After the message is sent, the UIManagedDocument may or may not work—I have not found the circumstances that determine this, yet.
I am pretty sure that the code is correct, as it's actually one of the code examples in the CS193p course from Stanford. The whole example can be downloaded at their website under
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/
Direct link to the code:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/system/files/sample_code/Photomania_0.zip
Additionally, the code runs fine on the device itself, without generating the "surprising" message, and running all the code that comes afterwards just fine.
I have not found anything on Google, neither on the Apple Developer pages. Restarting the simulator, or XCode, or reinstalling both of them does not change the behaviour.
Any ideas?
I can only say that I've had this happen to me several times. For me, I'm lazy after I update my dataModel and so far, each time I've gotten this error it was because I had changed my data model. Usually, all I need to do is delete my app from the simulator and re-run it and it has always turned out fine. Hope this helps someone out there.
I think I have found the answer. It looks like the automatic saving for UIManagedDocument kicks in only after a few seconds on the simulator.
So I minimized the app on the simulator, by pressing the home button, and then clicked on the icon to maximize it again. And then I terminated the app in simulator.
When I re-launched the app, the database was loaded. The error still shows up - it comes because the document is in "closed" state (that's normal - that's why CS193P asked to call openWithCompletionHandler), but my data across launches is preserved. Unfortunately I have to do the minimize/maximize routine before terminating the app, or the changes are discarded at next launch.
Can you verify that this is the behavior you are able to recreate? At least for testing purposes this should be a good enough trick to use.
Try upgrading to the latest iOS 5.1. I don't think UIManagedDocument with iCloud works reliably in 5.0. This has been my experience.
I love the Stanford iTunes class. However, I think the sample code for using UIManagedDocument is wrong. In fact, he notes in the demo that he is only doing it that way because he wants to just fetch the information right then. In the code comments, he says not to use the auto-save features because the data will not be saved if the app quits. however, UIManagedDocument will save anything that's necessary before quitting. It has all pertinent handlers for quitting/multitasking/etc to make sure the data is saved.
So, if you are using that code as your example, here's a version that should work, and does not use saveToURL (I don't have a flickr account, so I didn't actually run it - but this is how the class is designed to work). Please let me know if it does not work.
- (void)fetchFlickrDataIntoDocument:(UIManagedDocument *)document
{
NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType];
ctx.parentContext = document.managedObjectContext;
[ctx performBlock:^{
NSArray *photos = [FlickrFetcher recentGeoreferencedPhotos];
for (NSDictionary *flickrInfo in photos) {
[Photo photoWithFlickrInfo:flickrInfo inManagedObjectContext:ctx];
// Push changes to document MOC
[ctx save:0]; // propagates changes to parent MOC
// and tell the document it is dirty and needs to be saved
// It will be saved when the document decides its time to save
// but it *will* be saved.
[document updateChangeCount:UIDocumentChangeDone]
}
}];
}
Still had errors when the last path component for document file url was #"Database". Adding an extension #"Database.db" seems to have fixed it, everything running fine now. Have also upgraded to Lion though.
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"Database.db"];