I loaded libqrencode library in my cocoa project but I'm not sure how to use it exactly. I have a text field in which you type a text, and once done you click a button and I log that text with NSLog. Now I want to encode that text to be able to use it later and generate a QRcode out of it, so in the manual it's saying to use this format
QRcode* QRcode_encodeString (const char * string,
int version,
QRecLevel level,
QRencodeMode hint,
int casesensitive
)
I am not sure how to use that in my method to log the results as well
- (IBAction)GenerateCode:(id)sender {
NSString *urlText = [[NSString alloc] initWithFormat:#"%#", [_urlField stringValue]];
NSLog(#"The url is %#", urlText);
}
You need to get from an NSString instance to a const char *. This has been answered several times on SO, but here's one. Once you do that, you can call QRCode_encodeString() directly and pass whatever you desire for the arguments.
If you need more specifics, you'll have to try something, post your code, and describe how it's not working for you so we can help you more directly without just writing it for you.
Related
I am trying to implement code that converts const char * to NSString. I would like to try multiple encodings in a specified order until I find one that works. Unfortunately, all the initWith... methods on NSString say that the results are undefined if the encoding doesn't work.
In particular, (sometimes) I would like to try first to encode as NSMacOSRomanStringEncoding which never seems to fail. Instead it just encodes gobbledygook. Is there some kind of check I can perform ahead of time? (Like canBeConvertedToEncoding but in the other direction?)
Instead of trying encodings one by one until you find a match, consider asking NSString to help you out here by using +[NSString stringEncodingForData:encodingOptions:convertedString:usedLossyConversion:], which, given string data and some options, may be able to detect the encoding for you, and return it (along with the actual decoded string).
Specifically for your use-case, since you have a list of encodings you'd like to try, the encodingOptions parameter will allow you to pass those encodings in using the NSStringEncodingDetectionSuggestedEncodingsKey.
So, given a C string and some possible encoding options, you might be able to do something like:
NSString *decodeCString(const char *source, NSArray<NSNumber *> *encodings) {
NSData * const cStringData = [NSData dataWithBytesNoCopy:(void *)source length:strlen(source) freeWhenDone:NO];
NSString *result = nil;
BOOL usedLossyConversion = NO;
NSStringEncoding determinedEncoding = [NSString stringEncodingForData:cStringData
encodingOptions:#{NSStringEncodingDetectionSuggestedEncodingsKey: encodings,
NSStringEncodingDetectionUseOnlySuggestedEncodingsKey: #YES}
convertedString:&result
usedLossyConversion:&usedLossyConversion];
/* Decide whether to do anything with `usedLossyConversion` and `determinedEncoding. */
return result;
}
Example usage:
NSString *result = decodeCString("Hello, world!", #[#(NSShiftJISStringEncoding), #(NSMacOSRomanStringEncoding), #(NSASCIIStringEncoding)]);
NSLog(#"%#", result); // => "Hello, world!"
If you don't 100% care about using only the list of encodings you want to try, you can drop the NSStringEncodingDetectionUseOnlySuggestedEncodingsKey option.
One thing to note about the encoding array you pass in: although the documentation doesn't promise that the suggested encodings are attempted in order, spelunking through the disassembly of the (current) method implementation shows that the array is enumerated using fast enumeration (i.e., in order). I can imagine that this could change in the future (or have been different in the past) so if this is somehow a hard requirement for you, you could theoretically work around it by repeatedly calling +stringEncodingForData:encodingOptions:convertedString:usedLossyConversion: one encoding at a time in order, but this would likely be incredibly expensive given the complexity of this method.
I am running Xcode and I would like to dump out a NSData*. The variable in question is buffer. Is there a way to do this through the UI or the GDB debugger?
Edit
I've moved my notes into an answer.
No one has ever correctly answered the question. After 2 years I think it's time for one :)
Assuming you have in your code
NSData* myData;
Then in lldb you type
me read `[myData bytes]` -c`[myData length]`
If the format of the dump is not to your liking you can add '-t ' for example
me read `[myData bytes]` -c`[myData length]` -t int
For more help type
help me read
in lldb
From Xcode 5 (lldb), you can use the following:
po (NSString *)[[NSString alloc] initWithData:buffer encoding:4]
Note that this assumes your NSData instance is encoded with NSUTF8StringEncoding, but you can look up the other values in the headers or the documentation.
So if you're debugging something like a JSON request that's wrapped up in an NSURLSessionDataTask, the request data is in task.originalRequest.httpBody, and you can view that in the debugger with
po (NSString *)[[NSString alloc] initWithData:task.originalRequest.HTTPBody encoding:4]
In lldb, the following works to let you examine the contents of NSData objects:
You can get the address of the bytes for use with various debugger commands like this:
p (void *)[buffer bytes]
You see something like this:
(void *) $32 = 0x0b5e11f0
If you know the underlying data is a string, you can do this:
p (char *)[buffer bytes]
and the debugger will output:
(char *) $33 = 0x0b5e11f0 "This is the string in your NSData, for example."
In Swift this should do the trick:
po String(data:buffer!, encoding: NSUTF8StringEncoding)
Right click buffer and click on Print description of "buffer".
The console should say
Printing description of buffer:
<your data here ...>
Unfortunately, none of the suggestions so far solved the problem of actually being able to quickly display the data inside NSData.
I wrote a simple method that works the way I need it to. From the GDB window, I can type in print [Util dumpData:theData] and I will get nice, formatted output.
+(void) dumpData:(NSData *)data
{
unsigned char* bytes = (unsigned char*) [data bytes];
for(int i=0;i< [data length];i++)
{
NSString* op = [NSString stringWithFormat:#"%d:%X",i,bytes[i],nil];
NSLog(#"%#", op);
}
}
NsLog Output
0:24
1:0
2:4
3:0
4:0
5:0
Your data instance is empty.
It wouldn't only display the address otherwise. -[NSData description] includes a printout of the contents of the data. The bytes are grouped in fours and printed in hex with a leading 0 placeholder:
char arr[] = {0x1, 0x2, 0xA, 0x4, 0xF};
NSData * dat = [NSData dataWithBytes:arr length:5];
NSLog(#"%#", dat);
2012-07-17 22:24:48.973 PrintDat[61264:403] <01020a04 0f>
Using po dat at the debugger's command line will give you the same results, including the address:
(NSData *) $1 = 0x00007f98da500180 <01020a04 0f>
The contextual menu route that Anshu suggested also uses the description method.
I think I have it now.
Right click on NSData in the list displayed there, and click 'Show Memory Of "x"'.
I posted this as an answer to this relevant question:
Once you place a breakpoint, run, and the program stops at the breakpoint, hover your cursor over the variable/value you want to see like this:
You could also place an NSLog(#"%#", yourLabel.text); to view the contents of that label/other object type.
One other option is to run GDB in the console like this:
gdb
attach <your process name>
And then use the po (print-object) command to view the value of a variable like this:
po variableName
To view the value of primitive types (int, float, long, double, char, etc.), you can just use the print command while running GDB in the console like this:
print yourPrimitiveVariable
Hope this helps!
EDIT:
With the po command, you can print out the value of an object using both the property name (self.myProperty) or the ivar name (possibly _myProperty). I demonstrate this here:
Xcode 11.4 (and probably earlier) supports examining the raw bytes of (NS)Data in the visual debugger. Set a breakpoint after the Data has been assigned, hover over the symbol until the popup appears, and click on the eye or info icon. Roll for dexterity to prevent the popup from closing on you by moving outside of the tiny target.
Tested with Swift but presumably works with C family languages, too.
(Note: the eye icon produces the output below which is nicely formatted but, uh... seems to be missing the final column of bytes?)
The easiest way for me (during local development only!) is to convert to unused NSString instances. Then the values show right up in the debugger. Once I'm finished, I nuke those lines of code.
From this old thread
NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
For Swift code I'm doing the following:
When my program is stopped in a breakpoint I use the "Add expression" option and enter [UInt8](data) where data is my Data instance:
After that I can see the data contents:
I have three strings (a NSString, a NSMutableString, and another NSString) which I need to concatenate into a mutable string, in that order, to display as the source for a UIWebView. Comming from a PHP/JavaScript/HTML background, my knowledge of concatenation is pretty much this:
var concatenatedString = string1 + string2 + string3;
I presume that sort of thing won't work in Objective-C, so I'm wondering how to go about pulling them all together properly.
To give a bit of setting for this, the first string (NSString) is the header and canvas element of a web page, the second string (NSMutableString) is javascript from a text field that the user can define to manipulate the canvas element, and the third string (NSString) is the end tags of the web page.
Also, rather than initially creating the NSMutableString, should I just referance the UITextView.text to the get the user's text when concatenating the whole thing, or should I pull the text from the UITextView first?
NSMutableString *concatenatedString = [[NSString stringWithFormat:#"%#%#%#", string1, string2, string3] mutableCopy];
The other two answers are correct in that they answer the question as you asked it. But by your description of what you want to do there is a much easier way. Use a format.
Assuming string1 and string3 will always be the same and only string2 will change,which is what it sounds like you are doing you can write something like this.
static NSString *formatString = #"String1Text%#String3Text";
NSString *completeString = [NSString stringWithFormat:formatString,self.myTextFieldName.text];
NSLog(#"%#",completeString);
The %# in the format says to insert the description of the object following the format.(The description of an NSString is the stringValue.)
Assuming you have a UITextField named myTextFieldName, that currently contains the text 'String2Text' Then this will be the output:
'String1TextString2TextString3Text'
In this way you only create 1 instance of an NSString format for the whole class no matter how many times you call this code.
To me it sounds like you don't need a mutable string at all. Feel free to leave a comment if I misunderstood anything.
Response to comment:
I'm not sure how you are implementing 'moves to test it out again' but, let's say you have a button named 'testJavaScript'. The IBAction method connected to that button would have the first two lines in it. So each time you pushed the button it would make a new formatted NSString filled with the current contents of the textfield. Once this string was formed it could not be changed. But it won't matter since next time it will make another.
NSString *concatenatedString = [string1 stringByAppendingFormat:#"%#%#", string2, string3];
You can make the resulting string mutable (if you really need to) by adding mutableCopy as shown in the answer by #Vinnie.
Probably some easy answer out there, but I wasn't able to find it. I am using RegexKitLite to manipulate some NSStrings in my iPhone app. I want to get the set of links from an entire HTML source from a webpage. I want it to return the array of links, not the rest.
My code:
NSString *regex = #"[0-9]{1,}.htm";
for (NSString *match in [sourcePage componentsSeperatedByRegex: regex]{
NSLog (#"%#", match); // Just to debug, will use data later.
}
The problem here is that the enire page is returned in small pieces, but exactly without the strings I want.
Any help is appreciated!
Use -componentsMatchedByRegex: instead.
I have a Mac application that keeps it's own log file. It appends info to the file using NSString's writeToFile method. One of the things that it logs are URL's of web services that it is interacting with. To encode the URL, I'm doing this:
searchString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)searchString, NULL, (CFStringRef)#"!*'();:#&=+$,/?%#[]", kCFStringEncodingUTF8 );
The app then appends searchString to the rest of the URL and writes it to the log file. Now the problem is that after adding that URL encoding line, nothing seems to be getting written to the file. The program functions as expected otherwise however. Removing the line of code above results in all of the correct information being logged to the file (removing that line is not an option because searchString must be URL encoded).
Oh and I am using NSUTF8StringEncoding when writing the NSString to the file.
Thanks for any help.
EDIT: I know there's also a similar function to CFURLCreateStringByAddingPercentEscapes in NSString, but I've read that it doesn't always work. Can anyone shed some light on this if my original question cannot be answered? Thanks! (EDIT: same problem occurs when using stringByAddingPercentEscapesUsingEncoding:)
EDIT 2: Here's the code that I'm using to append messages to the log file.
+(void)logText:(NSString *)theString{
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,NSUserDomainMask,YES) objectAtIndex:0];
NSString *path = [docsDirectory stringByAppendingPathComponent:#"Folder/File.log"];
NSString *fileContents = [[[NSString alloc] initWithContentsOfFile:path] autorelease];
if([fileContents lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= 204800){
fileContents = #"";
}
NSString *timeStamp = [[NSDate date] description];
timeStamp = [timeStamp stringByAppendingString:#": "];
timeStamp = [timeStamp stringByAppendingString:theString];
fileContents = [fileContents stringByAppendingString:timeStamp];
fileContents = [fileContents stringByAppendingString:#"\n"];
[fileContents writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}
Because after almost a whole day no one else has offered any answers, I'm going to post a wild guess here: you're not accidentally using the string you want to output (with percent characters in it) as a format string are you?
That is, making the mistake of doing:
NSLog(#"In format strings you can use %# as a placeholder for an object, and %i for a plain C integer.")
Instead of:
NSLog(#"%#", #"In format strings you can use %# as a placeholder for an object, and %i for a plain C integer.");
But I'm going to be surprised if this turns out to be the cause of your problem, as it usually causes random-looking output, rather than absolutely no output. And in some cases, Xcode also gives compiler warnings about it (when I tried NSLog(myString), I got "warning: format not a string literal and no format arguments").
So don't shoot me down if this answer doesn't help. It would be easier to answer your question if you could show us more of your logging code. As for the one line you provided, I can't detect anything wrong with it.
Edit: Oops, I kind of missed that you mentioned you're using writeToFile:atomically:encoding:error: to write the string to the file, so it's even more unlikely you're accidentally treating it as a format string somewhere. But I'm going to leave this answer up for now. Again, you should really show us more of your code though ...
Edit: Regarding your question on a method in NSString that has similar percent encoding functionality, that would be stringByAddingPercentEscapesUsingEncoding:. I'm not sure what kind of problems you're thinking of when you say you've heard it doesn't always work. But one thing is that CFURLCreateStringByAddingPercentEscapes allows you to specify extra characters that don't normally have to be escaped but which you still want to be escaped, while the method of NSString doesn't allow you to specify this.