NSBundle returning NULL - objective-c

I have been using pathForResource for a while but suddenly its giving up on me.
I have added an additional file to my resources called untitled.obj and untitled.mtl.
And following two lines of code:
NSString *path = [[NSBundle mainBundle] pathForResource:#"untitled" ofType:#"obj"];
NSLog(#"thePath = %#", path);
All other *.obj files work fine, except untitled.obj.
The output from NSLog is nothing when i use that file, so i assume its unable to find it for some reason.
The resource is also located in the temp. simulation library:

Delete the app from your device and reset contents and settings in the simulator. Also delete Derived Data of the project. After you do that, test again and it should work.

Everything looks correct to me. Have you checked that you haven't accidentally named the file with a trailing space or other invisible character? Try naming it something entirely different (including changing the extension) and then renaming it back.

I think you need the .plist file. There you have the Bundle name and identifier.

Related

Files Copied to Clipboard are empty and "Missing Sandbox Extension" When Pasted

I have an application that is copying files to the clipboard. Here is the relevant code (arguments is an array of NSStrings containing file paths):
NSMutableArray *filesToCopy = [[NSMutableArray alloc] init];
int i;
for (i=1; i < [arguments count]; i++) {
NSString* pathToFile = [arguments objectAtIndex:i];
NSURL* fileURL = [[NSURL alloc] initFileURLWithPath:pathToFile];
[filesToCopy addObject:fileURL];
}
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSInteger changeCount = [pasteboard clearContents];
BOOL OK = [pasteboard writeObjects:filesToCopy];
However, in testing when trying to paste a file copied to the clipboard by the program into an empty email in Mail, often the file shows up as zero bytes and the following error appears on the console:
11/13/13 6:27:12.173 AM Mail[627]: Failed to obtain a valid sandbox extension for item: [789514] of flavor: [public.file-url] from the pasteboard.
11/13/13 6:27:12.174 AM Mail[627]: Failed to get a sandbox extensions for itemIdentifier (789514). The data for the sandbox extension was NULL
and then that is followed by the following error on the console:
11/13/13 8:24:41.947 AM sandboxd[172]: ([627]) Mail(627) deny file-read-xattr [full path of file]
What is strange is that if I copy the file from Finder then it pastes just fine with no errors every time. In other words, somehow Finder copies the file to the clipboard with different information than the way I am doing it. To verify this, I did a simple AppleScript to return clipboard info. After I copy a file to the clipboard that returns the following:
{{«class furl», 115}, {«class utf8», 115}, {«class ut16», 232}, {string, 115}, {Unicode text, 230}}
After I copy the same file to the clipboard using Finder, the Applescript returns the following:
{{«class furl», 33}, {«class icns», 795020}, {«class ut16», 112}, {«class utf8», 55}, {«class 8BPS», 1630436}, {«class BMP », 4194358}, {«class TPIC», 1059291}, {TIFF picture, 4197954}, {«class PNGf», 392648}, {«class jp2 », 213480}, {GIF picture, 121307}, {JPEG picture, 116181}, {Unicode text, 110}, {string, 55}}
So Finder is putting more information about the file on the clipboard and different information. For example, the furl class has a different length. This extra information is obviously what is cause Mail to successfully past a file copied from Finder while it has an error pasting a file copied by my program.
Any clues to what information I'm missing when I put the file on the clipboard or what extra information I should be adding to the paste? I'm guessing that Finder is pasting not just an array of NSURL's, but an array of Dictionary Keys that includes other file information. It also seems to be creating the furl class differently than I am. I've spent time pouring over documentation and I'm stuck on this one.
I believe I found the problem. It seems like when command line applications copy to the pasteboard, there is a permission related to sandboxing that is not transferred. The files copied could be pasted fine into any non-sandboxed app, but not into a sandboxed application. The solution in this case was to just create a regular Cocoa based .app program. I'm still not sure how, but it copies the files in a way that the permissions are properly transferred and the file can be pasted in both non-sandboxed and sandboxed applications.
There is is lot written out there about avoiding triggering the Sandboxing mechanism in Sandboxed Apps.
But all answers lack the most obvious trouble that can trigger Sandboxing.
When you make a copy of a NSURL (which is still based on NSString) into NSPasteboard without properly escaped characters still containing non-valid signs and spaces before transforming into 'NSURL'.
This is one of the ways URLs can become malicious, so it is only a little bit annoying that the Error Message you get while trying to expose the link to pasteboard is not telling you what the obvious reason was in detail. But maybe this is also because, "never give too much informations how to circumvent the safety barriers".
It just says:
[sandbox] CreateSandboxExtensionData failed: urlData: 0x0000000000XYZ length: 0 (-1 means null)
then you have to properly escape the string with
NSString *encodedStringForURL = [yourString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
this will exchange special characters that should not be part of n URL.
After that you can transform to NSURL as usually.
or
Failed to obtain a valid sandbox extension
then you also used a wrong NSPasteboardType that exposes a URL without proper type. In example when you exposed a String that poses as Link because you tried to avoid the [sandbox] trigger by being clever and telling the pasteboard this is only a random string. The Sandbox is still more clever when you prepend the string with file://.
Then the solution is to use NSPasteboardTypeFileURL and/or NSPasteboardTypeURL. This will inform the sandbox that you exposed links on purpose with proper type.
There are more pitfalls, but also remember you have to use YourURL.absoluteString when you paste to Pasteboard.

How do I programmatically find the user's logging directory?

Given an app called ExampleApp, I want to find "~/Library/Logs/ExampleApp" basically without using hard coded paths. There exists NSSearchPathForDirectoriesInDomains, which you can use to find things like "~/Library/Application Support/ExampleApp" using the NSApplicationSupportDirectory search term, but there doesn't seem to be a search term for logging.
I don't think ~/Library/Logs is non-standard, since CrashReporter puts its logs there.
Try this :
NSString* libraryPath = [NSHomeDirectory stringByAppendingPathComponent:#"Library/Logs"];
Update (~/Library/Logs/AppName) :
NSString* bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleName"];
NSString* logsPath = [NSString stringWithFormat:#"Library/Logs/%#",bundleName];
NSString* libraryPath = [NSHomeDirectory stringByAppendingPathComponent:logsPath];
Cocoa doesn't provide a means for finding all of the standard directories. The old FSFindFolder() function can provide many more, but does involve converting from an FSRef back to a path or URL. Apple discourages its use, but it's still the only way to get certain standard directories without hard-coding. That said, it won't ever incorporate your app name. You have to append that.
Edited to add: the link to the legacy docs.

Incorporate a text file into the build of my app

I want to incorporate a text file into the "Build" of my program for the iPhone. Other then copying and pasting into the code, how can I do this? I have many data files that I would like to include in the build.
You can use the NSString method stringWithContentsOfFile:encoding:error: to read the contents of any file in your project into an NSString.
Include the file in your project (no copy and paste required). Simply right click on the list of files, select Add, select Existing files, and navigate to the file to include.
Then, in the code where you want to load the file, use
NSString *txtFilePath = [[NSBundle mainBundle] pathForResource:#"myTxtFile" ofType:#"txt"];
NSString *txtFileContents = [NSString stringWithContentsOfFile:txtFilePath encoding:NSASCIIStringEncoding error:&error];
However, if you want to have more structure, then you should use a plist to store an NSDictionary.
You can add a .txt file to your application bundle. Please explain more what actually you want to do?
You can use plists to provide prepared data lists in your app. You can read them in with the NSArray function arrayWithContentsOfFile: or the NSDictionary function dictionaryWithContentsOfFile:.

SQLite wrapper in iOS?

I have an iPhone app that stores information to a SQLite database. It works splendid on my phone as well as my brothers. Stuff get's written to it and it can read from it. However, when running it on other people's phone's, it just crashes. Why?
I am using Matteo Bertozzi's SQLite wrapper (put files in the classes folder and linked to them in my .h like this: #import "Sqlite.h")
I have also imported the libsqlite3.dylib to my project.
Declared my SQLite database like this in my .h as well: Sqlite *database;
Set up my database like this:
if (database == nil) {
// Set up database connection
NSString *myDBTwo = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"flashpics.db"];
database = [[Sqlite alloc] init];
[database open:myDBTwo];
}
And call a query like this (none of my variables are nil) :
[database executeNonQuery:#"INSERT INTO images (id, thumbnail, album, caption) VALUES (?, ?, ?, ?)", photoID, thumbnailLocation, photoAlbumID, photoCaption];
However it crashes on my friend's phone and returns EXC_BAD_ACCESS when trying to read it.. Nothing happens when you try to write to it.
Please help!
Thanks
PS: Here's the link to the wrapper: http://th30z.blogspot.com/2008/11/objective-c-sqlite-wrapper_8445.html
Edit #1: Here's some of the errors I get when loading the app. Maybe this is causing it? Or it's not linking to the correct library?
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.2.1 (8C148)/Symbols/usr/lib/info/dns.so (file not found).
And here's what I get when I do the action that makes it crash.
Program received signal: “EXC_BAD_ACCESS”.
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.2.1 (8C148)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).
The problem is that you are trying to write to the resources folder in your app bundle, which is read only on a non-jailbroken system, due to safety/security reasons, you have to create the database in the documents folder, so you change your code to this...
EDIT: SORRY I pasted the WRONG code, here is the fixed version.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *myDBTwo = [[paths objectAtIndex:0]stringByAppendingPathComponent:#"flashpics.db"];
RTS is right, you have to copy it over to the Documents directory (or someplace similar) that is writable.
The reason it worked on your devices? If I had to guess I'd say you're both jailbroken and that notion of a code-signed bundle that cannot be modified isn't really enforced.

Cocoa: basic problem getting string from file

Is there some blindingly obvious reason why this is producing a nil string instead of the actual text content of the file?
NSString *fromFile = [NSString stringWithContentsOfFile:
#"file://localhost/Users/username/Desktop/test.txt"];
NSLog(#"%#", fromFile);
PRINTS: "(null)"
The file is a plain ASCII text file saved from TextWrangler with contents ' abc '.
The path comes from dragging the actual file from the desktop into the Xcode editor window.
I've also tried without "file://localhost".
The method documentation says "Returns nil if the file can't be opened". There's nothing unusual about the file (not locked, etc.). It has default Unix permissions and was created by the same user as is running Xcode.
I know this method is deprecated -- trying to get this working first.
You have stringWithContentsOfFile: and stringWithContentsOfURL: mixed up.
If you are passing in a URL e.g.
#"file://localhost/Users/username/Desktop/test.txt"
the you want stringWithContentsOfURL: and make the parameter a NSURL e.g.
[NSURL URLWithString:#"file://localhost/Users/username/Desktop/test.txt"]
If you want to use stringWithContentsOfFile: the the parameter should be
#"/Users/username/Desktop/test.txt"
Have you tried ~/Desktop/test.txt or /Users/username/Desktop/test.txt?