I am trying to write an if statement that checks an array of objects to see if a certain object exists (in this case the word, "NBC" in my array, "channel"). I'm new to this and I'm not sure how to do it in objective c. Please take a look at my code below:
if ([[self.channel objectAtIndex:path.row] containsObject: #"NBC"])
{
//Arguments
}
After I run it with this, the simulator crashes and gives this error: 2013-01-02 17:11:44.778 Master Detail Practice App[50056:207] -[__NSCFConstantString containsObject:]: unrecognized selector sent to instance 0xc698
I know my syntax or logic is probably off. Any help will be appreciated. Thank You!
[self.channel objectAtIndex:path.row] is returning you an NSString object. You're then trying to send that NSString instance a containsObject: message, which it doesn't know what to do with. Maybe you meant:
[self.channel objectAtIndex:path.row] isEqualToString:#"NBC"]
or
[self.channel containsObject:#"NBC"]
But without more context, it's hard to say.
It appears you are pulling out the String from an array rather than checking the array for the String. Try rewriting your code like this:
if ([self.channel containsObject: #"NBC"]) {
//Arguments
}
Related
Let me start off by saying I am new to Objective C.
I am getting the error
atusMenuApp[24288:303] -[__NSCFConstantString createListItem]: unrecognized selector sent to instance 0x100002450
Here is my code:
selector = [NSMutableArray arrayWithObjects: #"nvda", #"aapl", #"goog", nil];
[selector makeObjectsPerformSelector:#selector(createListItem:) withObject:self];
- (void)createListItem:(NSString *)title {
//do some stuff
}
Now I have done plenty of looking around and it seems like the biggest reason for this issue is the addition of or lack of the :however I do believe I properly have that in place. Maybe I do not understand the use of makeObjectsPerformSelector very well as after look up the doc on it I found:
Sends to each object in the array the message identified by a given selector, starting with the first object and continuing through the array to the last object.
Any help would be great, Thanks!
[Only if you read the documentation (or thought a bit about why a method is named this way and not that), or even made the effort trying to understand the error message...]
The makeObjectsPerformSelector:withObject: method of NSArray does what it suggests it does: it makes the objects of the array perform the selector, that can have an optional argument. So
[selector makeObjectsPerformSelector:#selector(createListItem:) withObject:self];
will send the createListItem: message to every single NSString object in the selector array and pass in self as its argument. It won't perform the selector on self passing in the object. I. e., what you have is equivalent to
for (NSString *obj in selector) {
[obj createListItem:self];
}
Obviously, instead of this, you want the following:
for (NSString *obj in selector) {
[self createListItem:obj];
}
You don't even need that nasty method for this. A nice fast enumeration for loop will do it.
First you make an array of NSStrings. Then, you send them all the message createListItem. That's all fine and dandy, but NSString doesn't have any method called createListItem; just because you've defined an instance method called createListItem doesn't mean every instance of every class can use it. Only the class who's implementation file has the definition will be able to handle the message. For instance, I can't make a list of Car instances, then define the method fly in another class called Helicopter's implementation and expect to be able to call fly on an instance of Car; only Helicopter can use it. I recommend you read a good book on Objective-C and further familiarize yourself with classes, instances and instance methods.
You misunderstood the method.
It will call the method createListItem: with argument self over every object of the NSArray.
So the resulting call would be something like:
[#"nvda" createListItem:self];
...
Clearly that method doesn't exist for a NSString and there goes your exception.
If you need to apply a method of self to every object inside your array, simply loop through it.
Hi I am debugging and need to be able to check what the values of my properties within my objects are. They are strings... but I dont see the actual string itself.
I just get this here:
some advice would be nice...
thanks
Add below method to TrackVO class
- (NSString *)description{
return #"put together your instance property values and send out";
}
Note:
You are overriding the method that is inherited from NSObject.
%# and xCode-variable-view will implicitly call this description method.
The debugger sometimes messes up the contents of variables. Try logging your strings.
NSLog(#"String value: %#", myString);
(XCode 4.3)
Why does the following crash at the NSLog statement with EXC_BAD_ACCESS?
BOOL autoFlag
#property BOOL autoFlag
#synthesize autoFlag
[object setAutoFlag:YES]
NSLog(#"%#", [object autoFlag]); //crashes here in debugger with EXC_BAD_ACCESS
I managed to get around it with NSLog(#"%d"..., which prints 1, but why doesn't #"%#" work? I thought it just converts the value to a string?
%# is used to print the description of objects that are descendants of the NSObject class, this however can be overwritten to make your objects print whatever you want.
Unless autoFlag is an object it will crash your program. It is very common to get these type of errors in NSLog Statements since the compiler cant tell what kind of "thing" you want to print and most of the time it wont be able to know before hand (there are some exceptions in where it will tell you that you are using the wrong identifier).
If what you want to see is something like "True" or "YES" then you need something like
NSLog(#"Auto Flag: %#",object.autoFlag? #"True":#"False");
Take a look at: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
%d works because you are telling it to print your boolean value as an integer, so you will get back either 0 (false) or 1 (true) using this method. There is no specific formatter for a boolean.
You encountered a crash because the code is expecting a pointer to a memory address by using %#, and instead you gave it a primitive datatype, in this case a boolean. When the application tried to use this address and there was no object there, you got a EXEC_BAD_ACCESS.
I am working with sqlite database.
I retrieve text data from sqlite database into NSMutableArray named myArray.
In that myArray variable, there is a column named "info" with text data.
After i retrieve that data into NSMutableArray , i would like to convert all of text data from sqlite database into lowercase.
I wrote following code in searchBar's textDidChange Event like that.
NSInteger counter = 0;
for(NSString *nameMe in myArray)
{
NSRange r = [[nameMe lowercaseString] rangeOfString:[searchText lowercaseString]];
if(r.location != NSNotFound)
{
if(r.location== 0)
{
[tableData addObject:nameMe];
}
}
counter++;
}
However there is a error occurring in lowercaseString.
This error is
2012-03-31 16:28:18.217 SqliteTest[1812:f803] -[MyInfoClass lowercaseString]: unrecognized selector sent to instance 0x6da9210
2012-03-31 16:28:18.276 SqliteTest[1812:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyInfoClass lowercaseString]: unrecognized selector sent to instance 0x6da9210'
I think that compiler doesn't know how to convert object data into lowercase.
How can i solve that?
Can i convert object (NSString) data into lowercase.
If it can be,Please let me know how to do that.
Thanks you for your helping.
I think that compiler doesn't know how to convert object data into lowercase.
The problem is that objects of type MyInfoClass don't have a method -lowercaseString. You're iterating over the array assuming that every object in the array is a NSString, but that's apparently not true -- there's definitely at least one instance of MyInfoClass in myArray. So, one way to fix the problem is to make sure that you only add strings to the array.
Here's a shorter, safer way to do what you're doing above:
NSArray *lowercaseArray = [myArray valueForKey:#"lowercaseString"];
NSArray's -valueForKey: will send a -valueForKey: message with the key you provide to every object in the array, and collect the results in an array. Even better, if some object in the array returns nil, the resulting array will contain a NSNull object at that index. You'll want to check for those NSNull's when you use the array, but you won't get an exception like you do in your code.
Update: From the OP's comment, it seems that the reason for converting the array to lowercase is to make case insensitive searching possible. It's worth pointing out that there are better ways to accomplish that. Here are two:
Use NSString's -caseInsensitiveCompare: method to compare strings, if you're doing the comparison yourself.
If you're using a predicate to search for a match, use string comparison operators (LIKE, CONTAINS, etc.) with the case-insensitive option: #"SELF like[c] %#". You may also want the diacritic-insensitive option: #"SELF like[cd] %#".
I know how to create a SEL at compile time using #selector(MyMethodName:) but what I want to do is create a selector dynamically from an NSString. Is this even possible?
What I can do:
SEL selector = #selector(doWork:);
[myobj respondsToSelector:selector];
What I want to do: (pseudo code, this obviously doesn't work)
SEL selector = selectorFromString(#"doWork");
[myobj respondsToSelector:selector];
I've been searching the Apple API docs, but haven't found a way that doesn't rely on the compile-time #selector(myTarget:) syntax.
I'm not an Objective-C programmer, merely a sympathizer, but maybe NSSelectorFromString is what you need. It's mentioned explicity in the Runtime Reference that you can use it to convert a string to a selector.
According to the XCode documentation, your psuedocode basically gets it right.
It’s most efficient to assign values to SEL variables at compile time with the #selector() directive. However, in some cases, a program may need to convert a character string to a selector at runtime. This can be done with the NSSelectorFromString function:
setWidthHeight = NSSelectorFromString(aBuffer);
Edit: Bummer, too slow. :P
I'd have to say that it's a little more complicated than the previous respondents' answers might suggest... if you indeed really want to create a selector... not just "call one" that you "have laying around"...
You need to create a function pointer that will be called by your "new" method.. so for a method like [self theMethod:(id)methodArg];, you'd write...
void (^impBlock)(id,id) = ^(id _self, id methodArg) {
[_self doSomethingWith:methodArg];
};
and then you need to generate the IMP block dynamically, this time, passing, "self", the SEL, and any arguments...
void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);
and add it to your class, along with an accurate method signature for the whole sucker (in this case "v#:#", void return, object caller, object argument)
class_addMethod(self.class, #selector(theMethod:), (IMP)impFunct, "v#:#");
You can see some good examples of this kind of runtime shenanigans, in one of my repos, here.
I know this has been answered for long ago, but still I wanna share. This can be done using sel_registerName too.
The example code in the question can be rewritten like this:
SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];