Filename string is used without and with # sign - ios

The iOS SpeakHere example code has a pair of methods in Class SpeakHereController, stopRecord and record that respectively save and initialize a file for saving the recording. The two methods handle the filename string slightly differently as you can see in the following two lines of code in those methods.
recordFilePath = (CFStringRef)[NSTemporaryDirectory() stringByAppendingPathComponent: #"recordedFile.caf"];
recorder->StartRecord(CFSTR("recordedFile.caf"));
The string "recordedFile.caf" occurs once preceded by an # sign and once without. I am planning on using the following NSString constuct to produce filename, but I don't know how to use the result correctly in the two places mentioned in this paragraph. So my question is how to use the constructed string filename in those lines?
#property int counter;
NSString *filename = [[NSString alloc] initWithFormat:#"recordedFile%d.caf",self.counter];

try
recorder->StartRecord(CFSTR([filename UTF8String]));

The difference is between a C API for string objects (CFStringRef in Core Foundation) vs. an Objective-C API for string objects (NSString in Cocoa).
The compiler knows that #"..." is an Objective-C string literal and constructs a static instance of (a private subclass of) NSString.
The compiler doesn't exactly have a similar native knowledge of CFString literals. Instead, Apple's headers define the CFSTR() preprocessor macro to wrap a C-style string in a Core Foundation string. The argument passed to the macro must be a C string literal (e.g. "foo"). The syntax in the other answer which passes a run-time expression returning a non-literal C string pointer not only isn't correct, I don't believe it can compile. Depending on the compiler, CFSTR() may produce a true compile-time CFString object rather than being a run-time expression.
So: #"recordedFile.caf" is an NSString literal, CFSTR("recordedFile.caf") is a C string literal turned into a CFStringRef. You should just think of it as a CFString literal.
Happily, Apple designed Core Foundation and Cocoa so that NSString and CFString are toll-free bridged. They are, at a certain level of abstraction, the same sort of object. You can just type-cast between the two types freely. With ARC, such a type cast requires a bridge that lets ARC know about the memory management of the change.
So, you can do:
CFStringRef cfstring = CFSTR("recordedFile.caf");
NSString* nsstring = (__bridge NSString*)cfstring;
Or:
NSString* nsstring = #"recordedFile.caf";
CFStringRef cfstring = (__bridge CFStringRef)nsstring;
For your particular case:
recorder->StartRecord((__bridge CFStringRef)filename);

Related

OBJ-C wipe NSData content before nullifying it

For security reasons we need Always to wipe sensitive data from memory.
Usually it is not something that i see done in IOS but for apps and need extended security it is very important.
The Data that Usually needs to be wiped if NSData and NSString objects (pointing to nil does not wipe the data and it is a security breach)
I've managed to wipe my NSStrings with the code below (When password is NSString):
unsigned char *charPass;
if (password != nil) {
charPass = (unsigned char*) CFStringGetCStringPtr((CFStringRef) password, CFStringGetSystemEncoding());
memset(charPass, 0, [password length]);
password = nil;
}
Big remark on this implementation: You HAVE to check for NULL before calling the charPass or it might crash. There is NO guarantee that CFStringGetCStringPtr will return a value!
When password is NSData It suppose to be even more strait forward and the code bellow suppose to work:
memset([password bytes], 0, [password length]);
But this gives me a compilation error:
No matching function for call to 'memset'
I can't find a workaround to point to the password address and wipe the bytes over there like I did with the string (bytes method should let me do just that from what I understand but it doesn't compile for some reason that I cant figure out)
Any one has an idea for this?
10x
Your string deallocator is fragile. You write:
Big remark on this implementation: You HAVE to check for NULL before calling the charPass or it might crash. There is NO guarantee that CFStringGetCStringPtr will return a value!
This is documented behaviour as CFString (and hence NSString) does not guarantee you direct access to its internal buffer. You don't say what how you handle this situation, but if you don't erase the memory you presumably have a security problem.
In the case you do get a valid pointer back you are using the wrong byte count. The call [password length] returns:
The number of UTF-16 code units in the receiver.
which is not the same as the number of bytes. However CFStringGetCStringPtr returns:
A pointer to a C string or NULL if the internal storage of theString does not allow this to be returned efficiently.
If you have a C string you can use C library function strlen() to find its length.
To address the case when CFStringGetCStringPtr returns NULL you could create the string yourself as a CFString and supply a custom CFAllocater. You shouldn't need to write a complete allocator yourself, instead you could build one based on the system one. You can get the default allocators CFAllocatorContext which will return you the function pointers the system uses. You can then create a new CFAllocator based of a CFAllocatorContext which is a copy of the default one except you've changed the deallocate and reallocate pointers to functions which you have implemented in terms of the default allocate, reallocate and deallocate but also call memset appropriately to clear out memory.
Once you've done that doing your security wipe comes down to making sure these custom created CFString objects, aka NSString objects, are deallocated before your app quits.
You can find out about CFAllocator, CFAllocatorContext etc. in Memory Management Programming Guide for Core Foundation.
Which brings us to your actual question, how to zero an NSData. Here you are in luck an NSData object is a CFData object, and CFData's CFDataGetBytePtr, unlike CFStringGetCStringPtr, is guaranteed to return a pointer to the actual bytes, straight from the documentation:
This function is guaranteed to return a pointer to a CFData object's internal bytes. CFData, unlike CFString, does not hide its internal storage.
So code following your pattern for CFString will work here. Note that using NSData's bytes is not guaranteed in the documentation to call CFDataGetBytePtr, it could for example call CFDataGetBytes and return a copy of the bytes, use the CFData functions.
HTH
While I cannot speak for the actual safety of doing this, your problem is that NSData's bytes method returns a const void *
https://developer.apple.com/documentation/foundation/nsdata/1410616-bytes?language=objc
You can cast it to a void * if you want by
memset((void *)[password bytes], 0, [password length]);
If you use a NSMutableData, you won't have to do this.

Clarification on NSString methods

I would like to get a clarification/difference on the NSString declaration. Consider the following codes:
NSString *str = #"string";
NSString *str = [NSString stringWithFormat:#"string"];
NSString *str = [[NSString alloc] initWithString:#"string"];
Can anyone help me to understand the difference between the above three type of string declaration? Does the difference come in terms of memory or will there be any other reasons? I have gone through various posts to understand the difference, but I couldn't understand the exact difference.
Sree
Edit (thanks for the comments):
Using ARC, the first statement is used by the compiler to create a string that is accessible during the lifetime of the app and never deallocated.
The last two statements produce the same kind of string.
Using manual memory management, the second statement produces an autoreleased string.
The last produces a retained string. This means, when using the last statement, you would have to add a release later in the code.
for: NSString *str = #"string"; used when you use as a static string .
for Exmple.
int abc=5;
for: NSString *str = [NSString stringWithFormat:#"%d",abc]; used when you convert your integer or float into string.
for: NSString *str = [[NSString alloc] initWithString:#"string"]; used when above same same reason but only difference is you alloc string and then passes static string.
but in ARC no need to alloc string.
as I remember in this case
NSString *str = #"string";
the memory for the string will be allocated once and will be reused for all same strings in whole application. Something like global constant.
https://en.wikipedia.org/wiki/String_literal
There is the proof: "Objective-C string constant is created at compile time and exists throughout your program’s execution. The compiler makes such object constants unique on a per-module basis, and they’re never deallocated"
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Strings/Articles/CreatingStrings.html
The others 2 is the same, also you can formate string with stringWithFormat method: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Strings/Articles/FormatStrings.html#//apple_ref/doc/uid/20000943
NSString literal
#"string"
This will make the compiler emit a statically allocated NSString instance. The object itself will never be deallocated (release is a no-op).
Unique instance from format
[NSString stringWithFormat:#"string"]
Here the string is created from parsing and transforming the format string. This involves runtime overhead and returns an autoreleased instance.
Initialize by copying a literal
[[NSString alloc] initWithString:#"string"]
This will (1) create the literal, (2) allocate a default string, (3) throw away the default string, (4) call copy on the literal, and (5) return the result (again, the literal, because copy just returns it). The logic retain count is +1 (automatically handled by ARC).

Want Autorelease lifetime with ARC

Transitioning to ARC on iOS.
I have an autoreleased NSString that I use to generate a UTF-8 representation, and rely on pool lifetime to keep the UTF-8 pointer alive:
char *GetStringBuffer(something)
{
NSString *ns = [NSString stringWithSomething:something];
return [ns UTF8String];
}
The nature of something is not important here.
Pre-ARC rules make sure the returned data pointer will stay valid for the lifetime of current autorelease pool. Crucially, I don't carry the NSString pointer around.
Now, under ARC, won't the string be released when the function returns? I don't think ARC will consider a char * to a structure deep inside an NSString a strong reference, especially seeing that it's not explicitly freed ever.
What's the best ARC idiom here?
If you want to guarantee that the return value of UTF8String is valid until the current autorelease pool is drained, you have two options:
Define GetStringBuffer in a file that is compiled with ARC disabled. If stringWithSomething: follows convention, it must return an autoreleased NSString to a non-ARC caller. If it doesn't (e.g. it acts like -[NSArray objectAtIndex:]), you can explicitly retain and autorelease it.
Use toll-free bridging and CFAutorelease:
char *GetStringBuffer(something) {
NSString *ns = [NSString stringWithSomething:something];
CFAutorelease(CFBridgingRetain(ns));
return [ns UTF8String];
}
(I can't delete this because it's accepted, but this answer is incorrect. See Rob Mayoff's answer, and the comments on that answer for an explanation. There is no promise that this pointer is valid past the return statement.)
Rewriting my whole answer. Had to dig and dig, but I believe this is surprisingly safe today (due to improvements in ARC since I had my crashes; I knew something like that was rolling around in the back of my head). Here's why:
#property (readonly) __strong const char *UTF8String NS_RETURNS_INNER_POINTER; // Convenience to return null-terminated UTF8 representation
UTF8String is marked NS_RETURNS_INNER_POINTER, which is really objc_returns_inner_pointer. Calling that method:
the object’s lifetime will be extended until at least the earliest of:
the last use of the returned pointer, or any pointer derived from it, in the calling function or
the autorelease pool is restored to a previous state.
Which is pretty much what you wanted it to do.

Swift - which types to use? NSString or String

With the introduction of Swift I've been trying to get my head round the new language
I'm an iOS developer and would use types such as NSString, NSInteger, NSDictionary in an application. I've noticed that in the "The Swift Programming Language" ebook by Apple, they use the Swift types String, Int, Dictionary
I've noticed the Swift types don't have (or are differently named) some of the functions that the Foundation types do. For example NSString has a length property. But I've not been able to find a similar one for the Swift String.
I'm wondering, for an iOS application should I still be using the Foundation types?
You should use the Swift native types whenever possible. The language is optimized to use them, and most of the functionality is bridged between the native types and the Foundation types.
While String and NSString are mostly interchangeable, i.e, you can pass String variables into methods that take NSString parameters and vice versa, some methods seem to not be automatically bridged as of this moment. See this answer for a discussion on how to get the a String's length and this answer for a discussion on using containsString() to check for substrings. (Disclaimer: I'm the author for both of these answers)
I haven't fully explored other data types, but I assume some version of what was stated above will also hold true for Array/NSArray, Dictionary/NSDictionary, and the various number types in Swift and NSNumber
Whenever you need to use one of the Foundation types, you can either use them to type variables/constants explicitly, as in var str: NSString = "An NSString" or use bridgeToObjectiveC() on an existing variable/constant of a Swift type, as in str.bridgeToObjectiveC().length for example. You can also cast a String to an NSString by using str as NSString.
However, the necessity for these techniques to explicitly use the Foundation types, or at least some of them, may be obsolete in the future, since from what is stated in the language reference, the String/NSString bridge, for example, should be completely seamless.
For a thorough discussion on the subject, refer to Using Swift with Cocoa and Objective-C: Working with Cocoa Data Types
NSString : Creates objects that resides in heap and always passed by reference.
String: Its a value type whenever we pass it , its passed by value.
like Struct and Enum, String itself a Struct in Swift.
public struct String {
// string implementation
}
But copy is not created when you pass. It creates copy when you first mutate it.
String is automatically bridged to Objective-C as NSString. If the Swift Standard Library does not have, you need import the Foundation framework to get access to methods defined by NSString.
Swift String is very powerful it has plethora of inbuilt functions.
Initialisation on String:
var emptyString = "" // Empty (Mutable)
let anotherString = String() // empty String immutable
let a = String(false) // from boolean: "false"
let d = String(5.999) // " Double "5.99"
let e = String(555) // " Int "555"
// New in Swift 4.2
let hexString = String(278, radix: 18, uppercase: true) // "F8"
create String from repeating values:
let repeatingString = String(repeating:"123", count:2) // "123123"
In Swift 4 -> Strings Are Collection Of Characters:
Now String is capable of performing all operations which anyone can
perform on Collection type.
For more information please refer apple documents.
Your best bet is to use Swift native types and classes, as some others have noted NSString has toll free translation to String, however, they're not the same a 100%, take for example the following
var nsstring: NSString = "\U0001F496"
var string: String = "\U0001F496"
nsstring.length
count(string)
you need to use the method count() to count the characters in string, also note that nsstring.length returns 2, because it counts its length based on UTF16.
Similar, YES
The same, NO
String and NSString are interchangeable, so it doesn't really matter which one you use. You can always cast between the two, using
let s = "hello" as NSString
or even
let s: NSString = "hello"
NSInteger is just an alias for an int or a long (depending on the architecture), so I'd just use Int.
NSDictionary is a different matter, since Dictionary is a completely separate implementation.
In general I'd stick to swift types whenever possibile and you can always convert between the two at need, using the bridgeToObjectiveC() method provided by swift classes.
Swift 4 update
String gets revisions in swift 4. Now you can directly call count on it and it consider grapheme clusters as 1 piece, like an emoji. NSString is not updated and is counting it in another way.
var nsstring: NSString = "👩‍👩‍👧‍👦"
var string: String = "👩‍👩‍👧‍👦"
print(nsstring.length) // 11
print(string.count) // 1
Since the objective C types are still dynamically dispatched they're probably going to be slower. I'd say you're best served using the Swift native types unless you need to interact with objective-c APIs
Use the Swift native types whenever you can. In the case of String, however, you have "seamless" access to all the NSString methods like this:
var greeting = "Hello!"
var len = (greeting as NSString).length
Swift Strings are quite elegant and easy to use, unless you need to parse them. The whole concept of indexing into Swift strings is just plain crazy. Whenever I need to parse through a typical unicode string, I convert it to NSString. Swift makes this a bit tricky though in that the common "character" integer expressions like ' ' or 'A' or '0' don't work in Swift. You have to use 32, 65, 48. Unfortunately, I'm not kidding! Because of this, I've put most of my string parsing code into an NSString extension written in Objective-C.
Yes I do know WHY Swift's designers made String indexing so crazy: They wanted to be able to express many-byte characters like emoji as single "Characters". My choice would have been to let this rare use case be expressed as multiple UTF16 characters, but what the heck.
String is a struct
// in Swift Module
public struct String
{
}
NSString is a class
// in Foundation Module
open class NSString : NSObject
{
}

iOS Conversion from a dictionary to a NSString

I have a NSMutableDictionary holding EXIF metadata from a picture.
An example:
const CFStringRef kCGImagePropertyExifExposureTime;
Instead of accessing every key individually, I just want write the whole dictionary content into a label.
When I want to write this data into the console I would just use:
NSLog(#"EXIF Dic Properties: %#",EXIFDictionary );
That works fine, but if I use:
NSString *EXIFString = [NSString stringWithFormat:(#"EXIF Properties: %#", EXIFDictionary)];
I get warnings that the result is not a string literally and if I try to use that string to set my label.text, the program crashes.
Any idea where my error is?
[NSString stringWithFormat:(#"EXIF Properties: %#", EXIFDictionary)] is not, as you may think, a method with two arguments. It's a method with one argument. That one argument is (#"EXIF Properties: %#", EXIFDictionary), which uses the comma operator and ends up returning EXIFDictionary. So in essence you have
[NSString stringWithFormat:EXIFDictionary]
which is obviously wrong. This is also why you're getting a warning. That warning tells you that the format argument is not a string literal, because using variables as format strings is a common source of bugs. But more importantly here, that argument isn't even a string at all, and so it crashes.
Remove the parentheses and everything will be fine. That will look like
[NSString stringWithFormat:#"EXIF Properties: %#", EXIFDictionary];
I get warnings that the result is not a string literally
Nah. You get a warning saying that the format string of stringWithFormat: is not a string literal. That's because you don't know how the comma operator (and a variadic function) works (that's why one should master the C language before trying to make an iOS app). Basically what you have here:
[NSString stringWithFormat:(#"EXIF Properties: %#", EXIFDictionary)]
is, due the behavior of the comma operator, is equivalent to
[NSString stringWithFormat:EXIFDictionary]
which is obviously wrong. Omit the parentheses, and it will be fine:
[NSString stringWithFormat:#"EXIF Properties: %#", EXIFDictionary]
You don't want those parentheses:
NSString *EXIFString = [NSString stringWithFormat:#"EXIF Properties: %#", EXIFDictionary];

Resources