Im trying to clean up a json stream and get the error listed above
NSString *traveladvice = [json valueForKeyPath:#"travel_advice_article.travel_advice_sections.body.markup"];
which gets me a stream with lots of javascript regular expressions like \U00a0 which I want to remove. Im using to regexlite to remove.
NSString *regexString = #"U00a0";
NSString *replacementString = #"";
NSString *travelparse1 = nil;
travelparse1 = [travelAdvice stringByReplacingOccurrencesOfRegex:regexString
withString:replacementString];
I understand the error but whats confusing me is that traveladvice is an NSString not an NSArray.
json valueForPath might return an array, not a string.
stop in a debugger and do 'po traveladvice'
it will show you the actual data.
also, store the result type as 'id' and not NSString* to avoid confusion
Related
I am facing the following issue,
I have parsed data from a server and I need all keys to be put into the arrays.
(
"shopping|TD|Shopping|TD|customer/shopping_icon.png",
"salon_spa|TD|Salon & Spa|TD|customer/salon_icon.png",
)
These are the keys I'm getting from the server, now I want to put them into an Array.
I have tried using component separated by string but that always crashes the app.
NSMutableArray *allKeysArray =[[NSMutableArray alloc]init];
[allKeysArray addObject: [deals allKeys]];
NSLog(#" all keys --%#",allKeysArray);
NSMutableString *string=[[NSMutableString alloc]init];
string =[allKeysArray objectAtIndex:0];
NSLog(#"string--%#",string);
arr =[string componentsSeparatedByString:#","];
The app crashes saying component separated by string is Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[_]: unrecognized selector
sent to instance 0x75b8dd0'
Replace your code from ....
[allKeysArray addObject: [deals allKeys]];
as like this...
[allKeysArray addObjectsFromArray: [deals allKeys]];
This will solve your problem...
I have a simple NSValueTransformer that should convert a comma-separated string first, second, third into an array. So in my CoreData schema I have the attribute options which I set to Transformed and specify my Transformer.
This is my Transformer:
-(id)transformedValue:(id)value{
// convert it to an array
if(!value){
return nil;
} else{
NSString *languages = value;
NSArray *result = [languages componentsSeparatedByString: #", "];
// return result;
return #"test Result";
}
}
Now when I return the variable result I get the following error (length looks like it's expecting an NSString):
... 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x6cc59a0'
If I return the test string above instead I get this error (bytes looks like it's expecting an NSData object):
... 'NSInvalidArgumentException', reason: '-[__NSCFConstantString bytes]: unrecognized selector sent to instance 0xf0780'
It looks like there is a conceptual problem which I don't seem to grasp. Also curiously +(Class)transformedValueClass and +(BOOL)allowsReverseTransformation are never "touched" when using the Debugger.
There are no errors in code you provide. The problem lays in your CoreData approach.
When you use transformed property in CoreData, the value is storing in database as NSData object. And length in your errors is related to NSData length method.
Therefore you should provide NSValueTransformer with transformation from NSData to NSArray and reverse to put concatenated arrays to CoreData as NSData.
If you want to keep the possibility to store property as NSString, you can implement special accessor to NSString property of your managed object, which will transform the NSString to NSArray value or use your NSValueTransformer outside your CoreData model like this:
NSValueTransformer *transformer = [NSValueTransformer valueTransformerForName:#"StringToArrayValueTransformer"];
NSArray *array = [transformer transformedValue:yourEntityItem.yourStringProperty];
The value needs to be cast to a NSString try this
-(id)transformedValue:(id)value{
// convert it to an array
if(!value){
return nil;
} else{
NSString *languages = (NSString*)value;
NSArray *result = [languages componentsSeparatedByString: #", "];
return result;
}
}
//COPY THIS CODE IN A FRESH PROJECT!!!
//THIS 2 LINES ARE JUST EXAMPLES, OF VALUES PUSHES OUT A DATABASE
NSString *messagelevel1 = #"45";
NSString *currentlevel = #"1";
NSString *HuidigLevel = currentlevel;
NSDecimalNumber *huidigleveldec = [[NSDecimalNumber alloc] initWithString: HuidigLevel];
float HuidigLevelRek = [huidigleveldec floatValue];
//HERE IS THE PROBLEM
NSString* LevelTotaal=[[NSString alloc] initWithFormat:#"messagelevel%.f",HuidigLevelRek];
NSString*result = LevelTotaal;
NSLog(#"%#",result);
// THE ABOVE RESULT SHOULD RETURN THE SAME VALUE AS THE NEXT (messagelevel1) LINE BUT IT RETURNS ONLY "messagelevel1" AND NOT THE VALUE!
NSLog(#"%#",messagelevel1);
I want the *result string behaves like the *huidiglevel string and fetch some information, but because the LevelTotaal is a NSString, It doesn't fetch this information. I really got no idea where to google for this problem, searching the Developer docs didn't helped either . Maybe you guys can help me out?
Actually the second NSLog returns the value and to first NSLog just returns messagelevel1. To tell you in short ;)
I hope you guys get what I'm saying!
I think what you're trying to do is use variable variables, a system that does not exist in Objective-C. In PHP, you can use variable variables:
$hello = 'abcdef';
$varName = 'hello';
print $$varName; // prints the value of $hello, which is 'abcdef'
Like many things in PHP, this is not really a good way to design software. Instead, consider using something like a NSDictionary, this allows you to give specific data a key.
NSMutableDictionary *aDict = [NSMutableDictionary dictionary];
[aDict setObject:[NSNumber numberWithFloat:4.5] forKey:#"messageLevel1"];
NSString *result = [aDict objectForKey:#"messageLevel1"];
You can obtain the data dynamically, the key can be generated or obtained at runtime.
Edit:
Rather than having variables called messageLevel1, messageLevel2, messageLevel3 ... messageLeveln, just use an array.
NSMutableArray *messageLevels = [NSMutableArray array];
[messageLevels addObject:#"1"];
[messageLevels addObject:#"45"];
[messageLevels addObject:#"123"];
NSString *result = [messageLevels objectAtIndex:HuidigLevelRek];
I'm using this code to query core data and return the value of key, I store the value like this :
NSString *newName= #"test";
[newShot setValue:newName forKey:#"shotNumber"];
and I query like this :
NSManagedObject *mo = [items objectAtIndex:0]; // assuming that array is not empty
NSString *value = [[mo valueForKey:#"shotNumber"] stringValue];
NSLog(#"Value : %#",value);
I'm crashing with this message though :
[NSCFString stringValue]: unrecognized selector sent to instance,
does anyone know where that would be coming from ?
newName (#"test") is already an NSString. There is no need to call -stringValue to convert it to a string.
NSString *value = [mo valueForKey:#"shotNumber"];
I often times add a category for NSString to handle this:
#interface NSString(JB)
-(NSString *) stringValue;
#end
#implementation NSString(JB)
-(NSString *) stringValue {
return self;
}
#end
You can add a similar category to other classes that you want to respond this way.
[mo valueForKey: #"shotNumber"] is returning a string and NSString (of which NSCFString is an implementation detail) do not implement a stringValue method.
Given that NSNumber does implement stringValue, I'd bet you put an NSString into mo when you thought you were putting in an NSNumber.
The value for the key #"shotNumber" is probably of type NSString which is just a wrapper for NSCFString. What you need to do, is, instead of stringValue, use the description method.
Note that you could also get this problem if you are trying to access a string property on an object that you think is something else, but is actually a string.
In my case I thought my Hydration object was in fact a hydration, but checking its class via isKindOfClass I found that it was an NSString and realized that I had incorrectly cast it as a Hydration object and that my problem lied further up the chain.
NSDictionary *story = [stories objectAtIndex: indexPath.row];
cell.text=[NSString stringwithFormat:[story objectForKey#"message];
i dont knw what exaclty "message " contains (what is the meaning of objectForKey#"message")
EDIT CODE
NSString *key =[appDelegate.books objectAtIndex:indexPath.row];
//dict y=#"Name";
NSArray *nameSection = [dict objectForKey:key];
NSDictionary *story = [nameSection objectAtIndex: indexPath.row];
cell.text=[NSString stringwithFormat:[story objectForKey:key]];
NSLog(#"Value Of message: %#", [dict objectForKey:key]);
why my code crashes
If you are more familiar with Java or C# the code is equivalent to something like this:
// Assuming stories is declared as: List<Dictionary<string, string> stories;
Dictionary<string, string> story = stories[indexPath.row];
cell.Text = String.Format(story["message"]);
In Smalltalk-style (and therefore Objective-C too) Object Oriented programming, methods are more like messages to other objects. So a good Objective-C method name should read like an English sentence (Subject-Verb-Object). Because of this working with dictionaries (hash tables) looks like this:
[myDictionary setObject:#"Value" forKey:#"someKey"];
[myDictionary objectForKey:#"someKey"]; // == #"Value"
In Java it would be:
myDictionary.put("someKey", "Value");
myDictionary.get("someKey"); // == "Value"
Notice how the key ("someKey") was the first argument in the Java example. In Objective-C you name your arguments with the method name, hence setObject: forKey:. Also notice that in Objective-C strings start with an # symbol. That's because Objective-C strings are different from regular C strings. When using Objective-C you almost always use Objective-C's # strings.
In C# there is a special syntax for Dictionaries so it becomes:
myDictionary["someKey"] = "Value";
myDictionary["someKey"]; // == "Value"
One important problem that you might encounter if you're new is the problem of native types.
In Java to add an int to a Dictionary you used to have to do:
myDictionary.put("someKey", new Integer(10));
Because the primitive types (int, char/short, byte, boolean) aren't real Objects. Objective-C has this problem too. So if you want to put an int into a dictionary you must use NSNumber like so:
[myDictionary setObject:[NSNumber numberForInt:10]
forKey:#"someKey"];
And you pull out the integer like so:
NSNumber *number = [myDictionary objectForKey:#"someKey"];
[number intValue]; // == 10
EDIT:
Your code might be crashing if you have a '%' character in your string, since stringWithFormat is just like NSLog in that it takes many arguments. So if story["message"] is "Hello" then it'll work fine without extra arguments but if it's "Hello %#" you need to add one argument to stringWithFormat.
NSString *message = #"Hello %#";
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:message forKey:#"message"];
NSString *output = [NSString stringWithFormat:[dict objectForKey:#"message"], #"World!"];
// output is now #"Hello World!".
#"message" is a key for a value stored in the NSDictionary object. The first line declares an NSDictionary named story that appears to come from an array.
If you want to find what value is stored for the key:#"message", consider using:
NSLog(#"Value Of message: %#", cell.text);
Run and check the console to see the output. (SHIFT + COMMAND + Y) in XCode will bring up the console, if that's what you are using. If you are unfamiliar with NSArrays/NSDictionaries, give Apple's Documentation a look.
I'm just guessing at all of this since that is a very limited sample of code. Try submit more code when you ask a question so that the viewers can get a better idea of your questions.
That is an example of key-value coding, and a lot of information is available on the Apple dev site if you're interested:
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html