iOS: Obtaining path of file in c code - objective-c

I am having an iOS Project in which i use some C-Sources.
In the C part I need the path to a file in the mainbundle.
How can I obtain it without using Obj-C?
Basically I want to have the path returned by:
NSLog(#"%s",[[[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"txt"] fileSystemRepresentation]);

So just get the path as you did above, and then get a C string version:
NSString *path = [[[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"txt"] fileSystemRepresentation];
char *cPath = [path cStringUsingEncoding:UTF8StringEncoding];
Just pay attention to the warning in the docs and copy the string if you plan to hang onto it beyond the end of the method/function that you're in:
The returned C string is guaranteed to be valid only until either the
receiver is freed, or until the current autorelease pool is emptied,
whichever occurs first. You should copy the C string or use
getCString:maxLength:encoding: if it needs to store the C string
beyond this time.
Update: If for whatever reason you can't use Foundation, you can do something similar using Core Foundation. You can call CFBundleCopyResourceURL() (or one of its cousins) to get the URL for the resource, and then convert that to a path using CFURLCopyPath().

Best you read the path with objective-c and pass it as char * to the c class by calling a function.
You further could asign a global variable char * which is visible for both objective-c and C.

Related

How to take parameters from plist?

I am quite new at Objective-C programming, I was asked to develop a framework that could be implemented in IOS apps. This framework has three methods (that take a model object as an argument) that perform API comsumption and return a message (that takes from response). The problem is that I was asked to store the module parameters in plist, and I don´t have a good clue what this means. I been reading about plist and I know they can store serialized objects. But I really don´t understand what it means to be storing all parameters on this file.
A plist is essentially a dictionary (or NSDictionary) -- with keys and values -- written to a specific file format that iOS expects.
To write a plist file is easy when you do it from Xcode. In Xcode 10.3 you can go to "File" -> "New" --> "File..." and select "Property List" from the types of files you see:
I created a file (as an example) named "SomeFile.plist" and then added a couple keys & values to it:
Now after you get this file included in your new project, you need to read the keys & values back in. Here is a related question that shows you different ways to read the plist / dictionary, such as:
NSString *path = [[NSBundle mainBundle] pathForResource: #"YourPLIST" ofType: #"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: path];
NSString *name = [dict stringForKey: #"RaphaelName"];

How do you pass in a String variable value to another string

Basically I did this and I got an error:
NSString *searchWord = #"Lilwayne";
NSString *resourceURL = (#"https://api.soundcloud.com/tracks?client_id=546952635e22cc0182d85daceff34381&q=%#&format=json", searchWord);
Error is:
reason: 'Resource 'Lilwayne' is invalid because the scheme is not 'https'.'
I don't understand why this doesn't work. However if I remove the "%#" and replace it with "Lilwayne" it works.
The reason why I am doing it this way is because I have a search feature in my app to search for songs using the soundcloud sdk and I want to dynamically change the value of the variable "searchword" to whatever the user typed in.
Try to use stringWithFormat
NSString *resourceURL = [NSString stringWithFormat:#"https://api.soundcloud.com/tracks?client_id=546952635e22cc0182d85daceff34381&q=%#&format=json", searchWord];
I suggest a trip to the NSString class reference in the Xcode help system. In addition to stringWithFormat, as suggested by Basheer, There is a section on combining strings.

Using a file which is located within the iPhone sandbox

I'm creating an iPhone app that needs the location of .wav which is located in the sandbox. I do this with the following:
recordFilePath = (CFStringRef)[NSTemporaryDirectory() stringByAppendingPathComponent: #"recordedFile.wav"];
How can I convert recordFilePath to a string that can then be passed into a C function?
EDIT 1
By the way, this is the statement that is going to receive the c string:
freopen ("locationOfFile/recordedFile.wav","r",stdin);
That will depend on what type your c function expects to get - you can write a c function that accepts NSString* object as parameter. If you want to convert your NSString to char* then you can use one of the following functions:
– cStringUsingEncoding:
– getCString:maxLength:encoding:
– UTF8String

How to use string hash more than once?

My application generates loads of images and in order to save memory, I write these files to the temporary directory and read them when needed. I write two versions of the same image to the tmp folder one the thumbnail version at lower resolution and the other is full size. To make the file names unpredictable, I add a string hash at the end.
For instance I want to have two images one called "ThumbnailImage.fgl8bda" and the other "FullImage.fgl8bda"
This is the code I use:
NSString *fileName = #"Image.XXXXXXX";
NSString *thumbName = [#"Thumbnail" stringByAppendingFormat:#"%#", fileName];
NSString * thumbPath = [self writeToTempFile:thumbNailImage andName: thumbName];
NSString *fullName = [#"Full" stringByAppendingFormat:#"%#", fileName];
NSString *fullPath = [self writeToTempFile:fullImage andName: fullName];
However, the two files come out with different names, i.e. each time I use the fileName variable the hash is regenerated. For instance, my two images are called "ThumbnailImage.jhu078l" and "FullImage.ksi9ert".
Any idea how I can use the same hash more than once?
It is generally not safe to reuse a temporary file name suffix, because even if you can ensure A.ashkjd does not exist, there is a chance B.ashkjd is occupied.
You could construct a folder and store the two images in it, e.g.
char tmpl[] = "Image.XXXXXX";
char* res = mkdtemp(tmpl);
if (res != NULL) {
NSString* dirName = [NSString stringWithUTF8String:res];
NSString* thumbPath = [dirName stringByAppendingPathComponent:#"Thumbnail.png"];
[thumbImage writeToFile:thumbPath atomically:YES];
NSString* fullPath = [dirName stringByAppendingPathComponent:#"Full.png"];
[fullImage writeToFile:fullPath atomically:YES];
}
(Note: you need to remove the folder manually.)
#KennyTM has a correct solution, but he didn't explain the cause.
writeToTempFile does not use a hash to fill in the unique part of the name. Instead, it uses a new unique random string for each call.
#TimG
It doesn't really make a difference. That too ends up in different names.
When I write
NSString *fileName = #"Image.XXXXXXX";
The XXXXXXX part of the fileName is replaced by 7 random characters so that the filenames are not predictable.
Cheers
I'm new to objc so apologies if this is a stupid suggestion. What happens if you use stringByAppendingString instead of description that you're invoking:
NSString *thumbName = [#"Thumbnail" stringByAppendingString:fileName];
I don't see why the two aren't equivalent for this usage, but still.
Also, how/where are you generating the hash?
EDIT
#ar06 I think you're saying that your (I'm assuming it's your) writeToTempFile method does a replace on the XXXXX' in the fileName parameter to a random value. If so then there's your problem - it generates a new random every time it's called, and you're calling it twice. The code fragment you posted does work, because fileName is immutable; it will save with a 'XXXXX' extension.
Do you need to refer to these random suffixes later? Whatever mechanism you use for tracking them could be also used by writeToTempFile to attach the same value to the thumb and the fullsize.
FWIW I agree that Kenny's approach is better since you can't guarantee uniqueness.

Unfamiliar C syntax in Objective-C context

I am coming to Objective-C from C# without any intermediate knowledge of C. (Yes, yes, I will need to learn C at some point and I fully intend to.) In Apple's Certificate, Key, and Trust Services Programming Guide, there is the following code:
static const UInt8 publicKeyIdentifier[] = "com.apple.sample.publickey\0";
static const UInt8 privateKeyIdentifier[] = "com.apple.sample.privatekey\0";
I have an NSString that I would like to use as an identifier here and for the life of me I can't figure out how to get that into this data structure. Searching through Google has been fruitless also. I looked at the NSString Class Reference and looked at the UTF8String and getCharacters methods but I couldn't get the product into the structure.
What's the simple, easy trick I'm missing?
Those are C strings: Arrays (not NSArrays, but C arrays) of characters. The last character is a NUL, with the numeric value 0.
“UInt8” is the CoreServices name for an unsigned octet, which (on Mac OS X) is the same as an unsigned char.
static means that the array is specific to this file (if it's in file scope) or persists across function calls (if it's inside a method or function body).
const means just what you'd guess: You cannot change the characters in these arrays.
\0 is a NUL, but including it explicitly in a "" literal as shown in those examples is redundant. A "" literal (without the #) is NUL-terminated anyway.
C doesn't specify an encoding. On Mac OS X, it's generally something ASCII-compatible, usually UTF-8.
To convert an NSString to a C-string, use UTF8String or cStringUsingEncoding:. To have the NSString extract the C string into a buffer, use getCString:maxLength:encoding:.
I think some people are missing the point here. Everyone has explained the two constant arrays that are being set up for the tags, but if you want to use an NSString, you can simply add it to the attribute dictionary as-is. You don't have to convert it to anything. For example:
NSString *publicTag = #"com.apple.sample.publickey";
NSString *privateTag = #"com.apple.sample.privatekey";
The rest of the example stays exactly the same. In this case, there is no need for the C string literals at all.
Obtaining a char* (C string) from an NSString isn't the tricky part. (BTW, I'd also suggest UTF8String, it's much simpler.) The Apple-supplied code works because it's assigning a C string literal to the static const array variables. Assigning the result of a function or method call to a const will probably not work.
I recently answered an SO question about defining a constant in Objective-C, which should help your situation. You may have to compromise by getting rid of the const modifier. If it's declared static, you at least know that nobody outside the compilation unit where it's declared can reference it, so just make sure you don't let a reference to it "escape" such that other code could modify it via a pointer, etc.
However, as #Jason points out, you may not even need to convert it to a char* at all. The sample code creates an NSData object for each of these strings. You could just do something like this within the code (replacing steps 1 and 3):
NSData* publicTag = [#"com.apple.sample.publickey" dataUsingEncoding:NSUnicodeStringEncoding];
NSData* privateTag = [#"com.apple.sample.privatekey" dataUsingEncoding:NSUnicodeStringEncoding];
That sure seems easier to me than dealing with the C arrays if you already have an NSString.
try this
NSString *newString = #"This is a test string.";
char *theString;
theString = [newString cStringWithEncoding:[NSString defaultCStringEncoding]];