This question already has answers here:
"Thread 1: stopped at breakpoint" error when initializing an NSURL object
(3 answers)
Closed 7 years ago.
I am trying to run the following in Xcode:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
// NSLog(#"Hello, my name is Travis");
// NSString *firstName = #"Variable";
// NSLog(#"Hello, my name is %#", firstName);
// NSString *lastName = #"Last Name";
// NSLog((#"First name: %#, Last name: %#", firstName, lastName));
// NSNumber *age = #26;
// NSLog(#"%# age is %#", firstName, age);
// NSArray *items = #[#"item1", #"item2", #"item3"];
// NSLog(#"%#",items[1]);
// NSLog(#"%#", [items description]);
// NSString *result = [items description];
// NSLog(result);
NSString *city = #"San Francisco";
NSUInteger cityLength = [city length];
NSLog(#"%lu", cityLength);
// NSMutableArray *mystr = [NSMutableArray arrayWithObjects:#"hello",#"world", nil];
// NSLog(#"%#", mystr[0]);
// NSString *me = #"FROM ME!";
// [mystr addObject: me];
// NSLog(#"%#", mystr[2]);
// NSDictionary *appRatings = #{#"item1": #4, #"item2": #3};
// NSLog(#"%#", [appRatings allKeys]);
// NSLog(#"%#", [appRatings objectForKey:#"item1"]);
// NSLog(#"%#", [appRatings allValues]);
// NSLog(#"%#", [appRatings valueForKey:#4]);
}
}
I'm simply trying to run the code thats uncommented. Seems simple, should just count the number of characters within my string variable. When I run this, the build succeeds but nothing is put into the console. The only thing that appears is: (lldb)
The lldb means the code is paused somewhere at a breakpoint, and is waiting for a lldb command. Either disable breakpoints or find and remove them, and try again.
Related
This code had been working fine until just recently. I hadn't' changed anything nor upgraded my system and I'm completely flummoxed.
I've been using it for 6 years and now it dies on me.
Is there an easier or better way of running an applescript from within a cocoa application? At this point I'm happy to pay to fix this problem!
utils.h
#import <Foundation/Foundation.h>
#interface Utils : NSObject
// Runs an applescript with a given map of variables (name/value)
+ (NSArray *)runApplescript:(NSString *)source withVariables:(NSDictionary *)variables;
// Runs an applescript from a file pathwith a given map of variables
// (name/value)
+ (NSArray *)runApplescriptFromFile:(NSString *)scriptName withVariables:(NSDictionary *)variables;
+ (NSArray *)arrayFromDescriptor:(NSAppleEventDescriptor *)descriptor;
// String is empty or only has white characters (space, tab...)
+ (BOOL)stringIsEmptyOrWhite:(NSString *)string;
#end
Utils.M
#import "Utils.h"
#implementation Utils
+ (NSArray *)arrayFromDescriptor:(NSAppleEventDescriptor *)descriptor {
// Enumerate the apple descriptors (lists) returned by the applescript and
// make them into arrays
NSMutableArray *returnArray = [NSMutableArray array];
NSInteger counter, count = [descriptor numberOfItems];
for (counter = 1; counter <= count; counter++) {
NSAppleEventDescriptor *desc = [descriptor descriptorAtIndex:counter];
if (nil != [desc descriptorAtIndex:1]) {
[returnArray addObject:[Utils arrayFromDescriptor:desc]];
} else {
NSString *stringValue = [[descriptor descriptorAtIndex:counter] stringValue];
if (nil != stringValue) {
[returnArray addObject:stringValue];
} else {
[returnArray addObject:#""];
}
}
}
return returnArray;
}
+ (NSString *)escapeCharacters:(NSString *)string {
return [string stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""];
}
+ (NSArray *)runApplescript:(NSString *)source withVariables:(NSDictionary *)variables {
NSString *input = #"";
NSArray *variableNames = [variables allKeys];
// Transform the dictionary of names/values to set sentences of applescript
for (NSString *variableName in variableNames) {
NSObject *variableValue = [variables objectForKey:variableName];
if ([variableValue isKindOfClass:[NSString class]]) {
input =
[input stringByAppendingString:[NSString stringWithFormat:#"set %# to (\"%#\" as text)\n", variableName,
[Utils escapeCharacters:variableValue], nil]];
} else if ([variableValue isKindOfClass:[NSNumber class]]) {
input = [input stringByAppendingString:[NSString stringWithFormat:#"set %# to (%# as integer)\n",
variableName, variableValue, nil]];
} else if ([variableValue isKindOfClass:[NSArray class]]) {
// Initialize a list
NSString *entry;
NSArray *values = (NSArray *)variableValue;
input = [input stringByAppendingString:[NSString stringWithFormat:#"set %# to {", variableName]];
BOOL first = TRUE;
for (entry in values) {
if (!first) {
input = [input stringByAppendingString:#", "];
}
input = [input
stringByAppendingString:[NSString stringWithFormat:#"\"%#\"", [Utils escapeCharacters:entry], nil]];
first = FALSE;
}
input = [input stringByAppendingString:#"}\n"];
}
}
NSString *finalScript = [input stringByAppendingString:[NSString stringWithFormat:#"\n\n%#", source]];
NSLog(#"Final script: %#", finalScript);
NSAppleScript *script = [[NSAppleScript alloc] initWithSource:finalScript];
NSDictionary *error;
NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&error];
NSLog(#"applescript error: %#", [error description]);
// Transform the return value of applescript to nested nsarrays
return [Utils arrayFromDescriptor:descriptor];
}
+ (NSArray *)runApplescriptFromFile:(NSString *)scriptName withVariables:(NSDictionary *)variables {
NSString *scriptPath = [[NSBundle mainBundle] pathForResource:scriptName ofType:#"applescript"];
NSString *scriptSource =
[[NSString alloc] initWithContentsOfFile:scriptPath encoding:NSASCIIStringEncoding error:nil];
return [Utils runApplescript:scriptSource withVariables:variables];
}
+ (BOOL)stringIsEmptyOrWhite:(NSString *)string {
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
return [string isEqualToString:#""];
}
#end
Easier, yes, although whether that’s your actual problem is another question.
http://appscript.sourceforge.net/asoc.html
I assume you’ve already got other details, including sandboxing and hardening settings and plist entries, taken care of. (Recent Xcode upgrades also had a habit of breaking it when auto-upgrading your project files, by turning on hardening for you so Apple events can’t get out.)
I have two (2) classes defined in one .m file:
#interface vendorData : NSObject { // < first class
#public
NSString *vendor;
NSString *price;
NSString *condition;
}
#end
#implementation vendorData
#end
#interface DetailViewController () < UIAlertViewDelegate>
#end
#implementation DetailViewController // <-- second (main) class
// code for the main class follows
I initialize both the class and NSMutableArray like this:
NSMutableArray *arrayOfPrices = [[NSMutableArray alloc]initWithCapacity:100];
vendorData *data = [[vendorData alloc] init];
I fill the class data using NSScanner, then put the vendorData object into a NSMutableArray; this is how I'm populating the data object:
NSData *siteHTMLData = [NSData dataWithContentsOfURL: siteUrl];
siteHTMLData = [NSData dataWithContentsOfURL: siteUrl]; // get past first page ("searching")
NSString *htmlString = [[NSString alloc] initWithData:siteHTMLData encoding:NSUTF8StringEncoding];
// start the search
NSScanner *scanner = [[NSScanner alloc] initWithString:htmlString];
NSString *priceString, *vendorString, *conditionString;
vendorData *data = [[vendorData alloc]init];
do {
#try {
// find vendor
[scanner scanUpToString:#"<tr id=\"" intoString:nil];
scanner.scanLocation += 9;
[scanner scanUpToString: #"\r\n" intoString: &vendorString]; // find end of vendor
data->vendor = vendorString;
// find price
scanner.scanLocation += 2;
[scanner scanUpToString:#"<span >$" intoString:nil]; // find beginning of price
scanner.scanLocation += 8;
[scanner scanUpToString: #"</span>" intoString: &priceString]; // find end of price
data->price = priceString;
scanner.scanLocation += 7;
}
#catch (NSException *exception) {
if([[exception reason] isEqualToString: NSRangeException])
break;
}
// see if vendor/price is already in array; if so ignore it
NSLog(#"\ndata->vendor: %#,\n->price: %#", data->vendor, data->price); // <---------
[arrayOfPrices addObject:data]; // add struct to array
} while (([scanner isAtEnd] == NO) || (scanner.scanLocation > htmlString.length));
This is a portion of the log:
2014-08-24 11:53:03.154 BookInventoryManager[3741:60b]
data->vendor: Thriftbooks.comUsed",
->price: 1.00
2014-08-24 11:53:03.155 BookInventoryManager[3741:60b]
data->vendor: ValoreBooksUsed",
->price: 0.01
2014-08-24 11:53:03.155 BookInventoryManager[3741:60b]
and this is what the debugger shows in the arrayOfPrices array:
Amazon.ca.Marketplace should be the last entry added to arrayOfPrices, but for some reason it appears in each and every element of the mutable array. Why?
Every time you want to append a element you should create a new instance of the object.
You can create your own custom init to make it easier. Here is an example:
#interface vendorData : NSObject {
#public
NSString *vendor;
NSString *price;
NSString *condition;
}
-(id) initWithVendor:(NSString) vendor price:(NSString *)price condition:(NSString *) condition;
#end
#implementation vendorData
-(id) initWithVendor:(NSString) vendor price:(NSString *)price condition:(NSString *) condition{
self = [super init];
if(self) {
self.vendor = vendor;
self.price = price;
self.condition = condition;
}
return(self);
}
#end
And here is how you would fill your mutable array:
NSMutableArray *arrayOfPrices = [[NSMutableArray alloc]initWithCapacity:100];
vendorData *data1 = [[vendorData alloc] initWithVendor:#"Amazon" price:#"31.75" condition: nil];
[arrayOfPrices addObject:data1];
vendorData *data2 = [[vendorData alloc] initWithVendor:#"Ebay" price:#"20.00" condition: #"new"];
[arrayOfPrices addObject:data2];
EDIT: thank you for updating your post, all you need to do is move the object declaration inside of the do-while loop:
do {
vendorData *data = [[vendorData alloc]init];
#try {
...
or if you want to use the custom init in my example, use it at like this:
do {
#try {
// find vendor
[scanner scanUpToString:#"<tr id=\"" intoString:nil];
scanner.scanLocation += 9;
[scanner scanUpToString: #"\r\n" intoString: &vendorString]; // find end of vendor
// find price
scanner.scanLocation += 2;
[scanner scanUpToString:#"<span >$" intoString:nil]; // find beginning of price
scanner.scanLocation += 8;
[scanner scanUpToString: #"</span>" intoString: &priceString]; // find end of price
scanner.scanLocation += 7;
}
#catch (NSException *exception) {
if([[exception reason] isEqualToString: NSRangeException])
break;
}
// see if vendor/price is already in array; if so ignore it
vendorData *data = [[vendorData alloc] initWithVendor:vendorString price:priceString condition: nil];
NSLog(#"\ndata->vendor: %#,\n->price: %#", data->vendor, data->price);
[arrayOfPrices addObject:data]; // add struct to array
} while (([scanner isAtEnd] == NO) || (scanner.scanLocation > htmlString.length));
As with most problems, odds are that this is a bug in your code. That's what always should be your first thought, especially when you are doing something that thousands of people have done before: It's a bug in your code.
We don't have all the code. We have one line where you create a vendorData object. We don't see where you set the vendor and price. We have one line where you add a vendorData object to a mutable array, and we see that the mutable array contains the same object twice.
The most obvious explanation would be that you create a vendorData object once, then set vendor and price to different values, and always add the same vendorData object to the mutable array. Adding an object to a mutable array adds that object, not a copy of it.
When I try to initialize any variable, my app crashes
NSString *str = #"Some String";
It crashes with the error message - "EXC_BAD_ACCESS"
This stmt is inside a function. Everywhere else in the program the initialization is working but when i call this function, my app crashes giving the error message
Here is my function
+ (NSString *) recvToFile:(NSString *)_fileName {
#try {
int _sz = [self recvNumber:4];
uint8_t t[_sz];
NSMutableData *data = nil;//[[NSMutableData alloc] init];
NSMutableData *fileData = [[NSMutableData alloc] init];
NSString *str = #"Some String";
long _pos = 0;
NSString *_fullPath = _fileName;
while (_sz > _pos) {
long _c = [m_sin read:t maxLength:_sz];
_pos += _c;
data = [NSData dataWithBytes:t length:_c];
if([Misc checkTempFileExists:_fileName]==nil)
[[NSFileManager defaultManager] createFileAtPath:_fullPath contents:nil attributes:nil];
[fileData appendData:data];
}
[fileData writeToFile:_fullPath atomically:YES];
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:_fullPath error:nil];
long long length = [[attr valueForKey:#"NSFileSize"] intValue];
if (length >= _sz)
return (_fullPath);
}
#catch (NSException * e) {
}
return (nil);
}
Everywhere else initializing is working but not for this function
In your code you are using class method and in that method you are initializing nonstatic string, i think tats the problem.Instead of that Can you please check it with static NSString=#"Some String"; after the import files in .m file.The same way you can create fullpath string also.Then u can assign like fullpath=_fileName;#aswinikumar..sorry for my english
I'm not sure if this is possible, but I've seen people do crazy things with regex and other tools.
I want to convert this plist to an Objective-C literals:
<dict>
<key>ar</key>
<array>
<string>+54## #### ####</string>
<string>## #### ####</string>
</array>
<key>at</key>
<array>
<string>+43 1 ########</string>
<string>+43 ############</string>
</dict>
converted to:
NSDictionary *dic = #{
#"ar" : #[#"+54## #### ####", #"## #### ####"],
#"at" : #[#"+43 1 ########",#"+43 ############"]
};
Is it possible to automate such conversion? This guy did something similiar: he parsed a PHP list into an NSDictionary using VIM.
Plist don't have a separate 'format' for use in code (this question doesn't quite make sense as-is). You either want to 1. generate Objective-C code which initializes the dictionary with these values, or 2. initialize the dictionary using the file, for which you can write
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:#"UIPhoneFormats.plist"];
Edit: so you want to generate Objective-C code that in turn will reproduce the same dictionary. For this, you need to re-print the contents of the dictionary in a formatted way. You can write a program like this:
#import <stdio.h>
#import <Foundation/Foundation.h>
NSString *recursiveDump(id object)
{
if ([object isKindOfClass:[NSString class]]) {
return [NSString stringWithFormat:#"#\"%#\"", object];
} else if ([object isKindOfClass:[NSNumber class]]) {
return [NSString stringWithFormat:#"#%#", object];
} else if ([object isKindOfClass:[NSArray class]]) {
NSMutableString *str = [NSMutableString stringWithString:#"#["];
NSInteger size = [object count];
NSInteger i;
for (i = 0; i < size; i++) {
if (i > 0) [str appendString:#", "];
[str appendString:recursiveDump([object objectAtIndex:i])];
}
[str appendString:#"]"];
return str;
} else if ([object isKindOfClass:[NSDictionary class]]) {
NSMutableString *str = [NSMutableString stringWithString:#"#{"];
NSString *key;
NSInteger size = [object count];
NSArray *keys = [object allKeys];
NSInteger i;
for (i = 0; i < size; i++) {
if (i > 0) [str appendString:#", "];
key = [keys objectAtIndex:i];
[str appendFormat:#"%#: %#", recursiveDump(key), recursiveDump([object objectForKey:key])];
}
[str appendString:#"}"];
return str;
} else {
// feel free to implement handling NSData and NSDate here,
// it's not that straighforward as it is for basic data types.
}
}
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:#"UIPhoneFormats.plist"];
NSMutableString *code = [NSMutableString stringWithString:#"NSDictionary *dict = "];
[code appendString:recursiveDump(dict)];
[code appendString:#";"];
printf("%s\n", [code UTF8String]);
[pool release];
return 0;
}
This program will generate (hopefully syntax error-free) Objective-C initialization code out of the provided property list which can be copy-pasted to a project and be used.
Edit: I just run the program on a stripped version of the plist file OP has provided (the original file was way too large, so I cut it a bit) and it generated the following code:
NSDictionary *dict = #{#"at": #[#"+43 1 ########", #"+43 ############", #"01 ########", #"00 $"], #"ar": #[#"+54## #### ####", #"## #### ####", #"00 $", #"18 ### $ "]};
To verify it was really valid, I pasted this into the middle of an int main() to a file called 'test.m', so I got this program:
#import <Foundation/Foundation.h>
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *dict = #{#"at": #[#"+43 1 ########", #"+43 ############", #"0$
NSLog(#"%#", dict);
[pool release];
return 0;
}
To verify, I run clang -o test test.m -lobjc -framework Foundation and surprise, surprise:
It worked.
Edit 2: I made this a command line utility, just to facilitate further work - who knows, this may be useful in the future. Plist2ObjC
Hope this helps.
What you need is Serializing a Property List
NSData* plistData = [source dataUsingEncoding:NSUTF8StringEncoding];
NSString *error;
NSPropertyListFormat format;
NSDictionary* plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
NSLog( #"plist is %#", plist );
if(!plist){
NSLog(#"Error: %#",error);
[error release];
}
If you want to get it as a string, use this,
NSString *aString = [NSString stringWithFormat:#"%#", plist];
or else you can call NSString *aString = [plist description] to get the same as a string.
Source
I have ubuntu machine and compiling objective-c using GNUStep. I wrote the following code:
#import <objc/objc.h>
#import <Foundation/Foundation.h>
#import <objc/NSArray.h>
int main ( int argc, char ** argv)
{
int ar[100] = {0};
int i;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *arr = [[NSArray alloc] initWithObjects:#"stackOverflow", #"1", #"2", nil];
NSLog (# "Counts in the array %i", [arr count]);
#try {
NSString *str;
str = [arr objectAtIndex:1];
NSLog (#" String value is %# ", str);
}
#catch (NSRangeException * excep)
{
NSLog (#"Reached Range caught for %#:%#" [excep name], [excep reason]);
}
[pool release];
}
But I get the following fatal error:
fatal error: objc/NSArray.h: No such file or directory
I tried <NSArray.h> also, but getting same error.
Which path I have to provide?
The file objc/NSArray.h does not exist, hence the fatal error.
Remove the #import <objc/NSArray.h> as NSArray should already be available via the Foundation import.
See https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html