I am using FTPHelper to perform basic download/upload FTP functions. I have been getting frequent crashes when using it to upload to my destination. The crashes don't seem to ever occur on the first upload but become more and more likely as I make subesequent calls. Xcode spits out EXC_BAD_ACCESS(code=1, address=0x30) at line 517 of the helper class::
success = CFWriteStreamOpen(writeStream);
I've enabled exception breakpoints and zombies but I'm not seeing anything I can make sense of. Here's a snap of what my stack trace looks like at each crash:
I have been able to recreate this same stack trace with several other FTP libraries (BlackRaccon and FTPManager).
The file being uploaded is a simple one generated from the user's interaction with the UI, meaning it's dynamic based on what the user selects on screen. Here is the code that generates, locally saves, and uploads the file:
//Prepare to write a new file to the device and then upload it
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *putContent = [NSString stringWithFormat:#"V%d\n", (int)(funnySlider.value * -1)];
NSString *writepath = [documentsDirectory stringByAppendingPathComponent:#"foo.dat"];
//if the path exists
if([[NSFileManager defaultManager] fileExistsAtPath:writepath]){
//Upload the newly created file
[putContent writeToFile:writepath atomically:NO encoding:NSASCIIStringEncoding error:nil];
[FTPHelper upload:#"foo.dat"];
}
Some odd things I wanted to highlight as well... Filling foo.dat with lots of mumbo jumbo content to increase its file size makes the app much more stable. It's almost reliable at 100KB+. I also have no crashes when using an iPod Touch 4th Generation (okay, I had ONE but it was after dozens and dozens of test sessions). iPhones and iPads do however. Any ideas on how to fix this or why it might be happening? Should I abandon this mode of uploading?
The issue encountered in the posted question is actually a reported bug in CFFTPStream. I received this information from another posting I made to the Apple dev forums when this post wasn't getting any attention.
After calling CFWriteStreamCreateWithFTPURL, immediately disable the stream's persistent connections like so:
CFWriteStreamSetProperty(writeStream,
kCFStreamPropertyFTPAttemptPersistentConnection,
kCFBooleanFalse);
More information can be found here in another StackOverflow question I stumbled upon when doing some more research and in the post I made to the dev forums. Hope this helps somebody!
Related
After reading Apple documentation, I used URLsForDirectory to obtain the Library destination within my app, and my objective is to download content from a hosted service & cache it in the Library folder, so that User cannot interact with the contents through iTunes.
NSArray *docPaths= [[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask];
NSLog(#"%#",[docPaths description]);
NSString *docPath=[(NSURL *)[docPaths objectAtIndex:0] path];
docPath = [docPath stringByAppendingPathComponent:#"audios"];
Running & executing the code several times(various simulators, and iOS 8.0 device) I realized that somehow the content being fetched seems to be no longer accessible, so I logged the library destination path, and after running app every time the destination path seems to have changed:
/var/mobile/Containers/Data/Application/83725F33-C7EA-4F89-B69F-0AECF26FA77A/Library/"
/var/mobile/Containers/Data/Application/4627FC86-C3A4-4A1A-9721-AF73D808433E/Library/"
/var/mobile/Containers/Data/Application/709CCA84-936A-4596-933A-D6779758FF85/Library/
Has anybody faced a similar issue? If so how did it got corrected? And is there anything I've missed out here?
I had the same issue. I think the variable part changes only when the code is recompiled (ie not if you just rerun without making changes), so should not affect a live app. But I decided in the end not to save the path - just to use the same code (as you use above) both when saving and retrieving the data. It seems to work, in spite of the fact that the path actually changes between runs (so the simulator must copy the files across, or rename the folder).
With the upgrade to IOS8 and Xcode 6.0.1, I have noticed that adding images, writing them to file, and displaying them is broken in my app that has been working for over 2 years. It works fine at the time of taking the photo and saving it - it displays it fine. I store the FilePath in Core Data. But as soon as I close the app and reopen, or run the simulator again, it disappears.
I have tracked the problem that every time it runs on both the device or the simulator, the documents directory string changes, with the APPLICATION ID changing, so the image is not found in the path as it can't seem to access the path of the previous APPLICATION ID that it had.
I looked for this and couldn't find any answers. Has anyone else seen this and have any suggestions for how I can get around it. Thanks so much!
Kat
Edit - I have added this code example. Every time I run my app, this is the path that changes.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(#"documents directory %#", documentsDirectory);
Store your relative path, here by calling the temp directory, but not the full absolute path. The App container is changed at every start, due to sandboxing safety.
NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:#"MyPic"] URLByAppendingPathExtension:#"jpg"];
NSLog(#"fileURL: %#", [fileURL path]);
In the end I added the files into Core data, as they were referenced from Core Data objects.
This is a new change in iOS8 for safety enhancement, so you never should keep absolute path.
You save a file name instead of file URL. Each time when you use file URL, you make file URL from file name by your computed property.
On iOS, our application is downloading a zip file that's approximately 400MB. We're getting intermittent crashing while the file is downloading.
Current I'm using [NSFileHandle writeData:] to write the data as it comes in, and is not being stored in memory. But I'm wondering if the operating system is somehow storing it in memory?
Would NSOutputStream be a better solution to downloading large file? Or possibly standard unix file descriptors?
Our file handle is setup like this:
NSFileManager * fileManager = [NSFileManager defaultManager];
[fileManager createFileAtPath:tmpFilePath.path contents:nil attributes:nil];
_zipFile = [NSFileHandle fileHandleForWritingAtPath:tmpFilePath.path];
Currently my NSURLConnection delegate method looks like this:
- (void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data {
[_zipFile writeData:data];
}
So the data that comes in from the request is not stored or appended to any other data objects. Shouldn't this just write to disk and not effect memory?
Thanks
I don't think there's anything wrong with your use of NSFileHandle. I confess that I've always used NSOutputStream, but I just tried it both ways (NSFileHandle and NSOutputStream), and both appear to be quite respectful in terms of the memory consumed. Downloading a 40mb file, the allocations spiked to 3mb at the start of the download but quickly leveled off at 1mb):
So, I'd run your app through "Allocations" and "Leaks" (if you choose "Leaks", you get both) and see what it looks like.
If you haven't already, run your code through the static analyzer ("Analyze" on the "Product" menu), to make sure you don't have any issues. (You should have a clean bill of health there; if there are any issues reported, you must fix those.) I'd also make sure that zombies are turned off (because in the process of keeping track of all of those released objects, it creates a zombie object for each ... small, but it will consume memory.
I keep save files in a private directory in my iPad app, namely the one returned when I use:
paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:#"Private Documents"];
Notice that I also append a subdirectory to it. When I update the app, users are telling me that their progress in the app is getting destroyed. Are files in this NSLibraryDirectory destroyed every time I update the app? If so, should I be using NSDocumentDirectory instead?
Additionally, is there no way to make a further update to my app to remedy this without destroying all my my current users' save files? It doesn't seem like there is.
When a user downloads an app update, iTunes installs the update in a new app directory. It then moves the user’s data files from the old installation over to the new app directory before deleting the old installation. Files in the following directories are guaranteed to be preserved during the update process:
Application_Home/Documents
Application_Home/Library
Although files in other user directories may also be moved over, you should not rely on them being present after an update.
This is provided by apple officially. See this link :
iOS Developer Library - File Saved During App Updates
I would also like to add this info as a personal experience with a big online game. You can't rely at 100% that your "Document" and "Library" folder will always be there. In fact, you can't rely that your app folder will still be at the same place on your device after an update.
Let me explain it a little bit more. When you install an app on your device, the real path will be /var/mobile/Applications/[some class id]/[your app].app/...
We're not sure who defines the class id of your app (either the iOS or app store), but this Id can change when updating the game resulting in having your app in a totaly different folder so your old files aren't there anymore. Our QA experienced it and our users too.
I won't go through the details on how we found that out and how we managed to get around this (private company stuff, usual shit...), but you need to consider it if you're doing an app that affects tons of users and might be updated a couple of times. It might have been fixed since, but it's always good to have a backup plan.
You should save them in the Documents folder, it is persistent across updates.
Monotouch: documentsDirectory = environment.specialfolder.personal;
Objective-C: NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
I'm not sure how best to word the Title of this, so if someone can suggest a better one, please feel free to edit.
I'm writing an app for iPad that requires me to create some of the app data files with the iPad itself during development, i.e. a tool I am building with the iPad will be used by the developers themselves to create sample files that can be played by the app itself.
My question is, how can I best do this? I tried writing files to a local dir on my mac while the iPad was connected but I get a crash. Ideally if there is some way for me to generate an output file on my iPad and get it transferred to my Mac while my dev build is running, I'd do that.
Suggestions?
It looks like the trick it to use Apple's File Sharing to place files in a folder accessible through iTunes, explained here:
Standard Application Behaviors
The gist is to add a UIFileSharingEnabled plist key set to true and then query the Documents folder for your application like so:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];