Obj C - Is there a way to make a method return the method in which it is called? - objective-c

I want to know whether there is the way to achieve the following requirement:
First, there is a methodA, which takes an input objA and check whether objA is valid for the method. If it's valid, then it returns an object objB. However, if objA is not valid, it just returns objA itself. Note that even if objA is valid, the returned objB may still be the same with objB.
Then, there is a methodB and in the method, methodA is called. If the input of methodA is valid, the program go on without error. However, if methodA is called with invalid input, then methodB should terminate (a.k.a return with a certain string signaling an error) to prevent future crash.
The current solution that I could think of is to create a (BOOL)methodAInputIsValid:(obj)input and in methodB there is:
if(methodAInputIsValid:input) {
obj objReturn = methodA:input;
}else{
//show error warning
return;
}
//continue doing something with objReturn and finally return some valid thing
A problem of the code is that (BOOL)methodAInputIsValid:(obj)input and methodA:(obj)input share a lot of code in common because there is a validity-test in methodA. So I want to use the validity-test more efficiently so that it will work for methodB and drop the (BOOL)methodAInputIsValid.
Here is one possible application that I could think of:
In a program the user is asked to enter a string that will direct the action of the program. However, the input string may need to be standardized such as converting all letters to lower-case and converting all single quotation to double quotation and auto-complete any missing right parenthesis or quotation marks. However, if the user is just entering nonsense that cannot be standardized, then the program should terminate and warn the user of the problem. The two methods are (BOOL)isStandardizeable:(NSString *)input and (NSString *)standardize:(NSString *)input. Because (NSString *)standardize already returns an NSString *, I can't make it to return another BOOL, right? So the following code is not achievable:
if(standardize:input){
NSString *result = standardize:input;
} else {
NSLog(#"unrecognizable input!");
return;
}
//continue...
Can anyone think of a way to do this?

Realistically, I'd just have methodA return nil if the input is not valid. This is a fairly common method to signal failure to a caller. If you really need the "identity" part of the method, just have callers do
id res = [... methodA:input];
if(res == nil)
res = input;

Related

Instance variable initialized without using "init" method?

Iam in the first phase of Objective-C learning curve, so please bear with me :).
Iam reading Apple documentation and doing exercises there also. Ive come to a problem with initialization of particular object, because I get unexpected (In my opinion) behavior in my Xcode.
To the point (lets make it simple):
STEP 1:
I have declared simple variable from a my custom class named XYZPerson. It looks like this:
XYZPerson *randomPerson;
"If" check for initialized object returned out "Not Initialized" (as expected).
if(randomPerson == nil) {
NSLog(#"Random person is not initialized");
} else {
NSLog(#"Random person is initialized");
}
STEP 2:
I have allocated the memory for this object using "alloc" word on this variable. As I understand in this phase, memory for this variable gets allocated. It also returns the pointer?
Line of code looks like this:
XYZPerson *randomPerson = [XYZPerson alloc];
Checking for "nil" surprised me: (It executes "else" statement).
if(randomPerson == nil) {
NSLog(#"Random person is not initialized");
} else {
NSLog(#"Random person is initialized");
}
I can also send messages to this object and they are executed just fine, without calling "init" method.
How can this be? Am I missing something? How can "randomPerson" variable be initialized before calling "init" method on this instance? Why is "init" there in the first place then?
Furthermore, the accepted answer here Difference between ! and nil check on Objective-C object , says that ALL object are set to nil in the alloc method!
Iam coming from Java and there is one way of declaring an object using "new" keyword. Without using "new" the instance of object will be always "null", and calling methods on that instance will result "NULLPOINTEREXPECTION Error".
P.S Is "nil" in objective C, same as "NULL" in Java?
Whole project looks like this:
main method:
XYZPerson *randomPerson = [XYZPerson alloc];
if(randomPerson == nil) {
NSLog(#"Random person is not initialized");
} else {
NSLog(#"Random person is initialized");
}
**XYZ Person Class:**
#import "XYZPerson.h"
#implementation XYZPerson
-(void)sayHello {
//[self saySomething];
}
-(void)saySomething:(NSString *) greeting {
NSLog(#"%#", greeting);
}
#end
I post an answer additional to that one linked in the comment for two reasons:
A. Your Q is slightly different.
B. I do not confirm with the linked answer in details.
First of all to your additional Qs: Yes, nil is Objectice-C's NULL. But there are some differences:
A. In most cases (using ARC) a reference to a pointer (not the object itself) is initialized with nil.
XYZPerson *person; // Usually automatically set to nil.
B. A message to nil is allowed in Objective-C, does not throw an exception and returns NO, 0, 0.0, nil, or whatever the representation of null resp. zero (if it does not have a null representation like integers) is for that type. Sometimes this is done intentionally and you can rely on that.
Two your main Q:
After creating an instance object with +alloc all instance variable (ivars) are set to NO, 0, 0.0, nil, or whatever the representation of null resp. zero is for that type. You should not set such ivars explicitly to that value.
For example, if the instances of the class XYZPerson has an ivar for the name typed NSString*, the ivar will be nil. So, one might think that an naked -init does not have any meaning, because it does not take parameters and therefore does nothing. But you simply do not know: Maybe something else is done in -init. And, that's probably a surprise for a Java developer, -init returns an object reference, so you cannot know, whether -init replaces the instance object, for example for twin toning. So even you do not see any meaning in it, the first message to an instance object has to be init. (Yes, in many case you would not see any difference, but you do not know, whether there is one or not or will be in future. It is a part of the API contract, so do it.)
In disagree with the linked answer in one point:
Sending +new… instead of +alloc -init is the better way to do it.
A. If you use a simple +new it is correct that it sends +alloc -init in many cases. Therefore it is obvious that this is not better or worse than sending +alloc -init. It is what it does. You always have to have a look at the documentation, whether a naked initialization, using +new or +alloc -init is allowed. But in such a case you likely do not want to do a naked initialization, because it is meaningless.
B. Sometimes it is for the implementor of a class easier to receive a new message to the class object.

id object in theos mobilesubstrate tweak , i can't disable this -(id)

-(id)initWithUserSettings:(id)userSettings mqttSender:(id)sender;
NSDictionary *settings3=[[NSDictionary alloc] initWithContentsOfFile:#"/var/mobile/Library/Preferences/myfilehere.plist"];
if ([[settings3 objectForKey:#"invisiblechat"] boolValue]){
return NULL;
}
else{%orig;}
[settings3 release];
}
I don't know if this code is the right one, I am searching 2 days without an answer. On -(void) this code works really good and it keeps the -(void) disabled until the objecForKey is disabled. What I want is to keep the (id)mqttSender disabled/enabled with the toggle, I can't do it though. Any help please?
Im not quite sure what you are trying to achieve from your explanation but if your going to init a class that is a subclass of NSObject you need to be at least call [super init] and return self, if you dont whatever is calling the init method will fail to get a reference to that object.
Setting a return value of 'void' means that the method shouldn't return anything, if you set 'id', then 'id' is a representative of a value that you haven't defined so it can be nearly anything.
With your method you are setting a return value of 'id' which means you should be returning something from that method. At the moment you have a single return inside of your 'if' statement, but after that your method is open ended and doesn't return anything. Xcode will throw up a compile error in this case because you are failing to return anything and it's expecting at least something to come out of the method, even if it's nil.
One other thing: you only end a method deceleration with a semi-colon when defining a method/function, when you implement the method/function you don't need a semi-colon as you are following it with curly braces which contain your code for that method/function.

How can I check whether parameter of function is nil or not?

I made Sender class and sender object:
Sender *sender = [[Sender alloc] init];
Then, I wrote test:
// should success
[sender upload:[UIImage imageNamed:#"test2.jpg"] withName:#"test2.jpg"];
// should fail
[sender upload:nil withName:#"test2.jpg"];
Then, I wrote nil check code:
- (void)upload:(UIImage *)image withName:(NSString *)name
{
if ([image isEqual:nil]) {
...
}
...
}
But nil check is ignored.
How can I check whether the image parameter is nil or not?
Thank you for your kindness.
Try
if(!image)
or
if(image == nil)
Short answer, replace [image isEqual:nil] with image == nil.
Long answer, when you write:
[image isEqual:nil]
you are asking for the message isEqual: to be sent to the object whose reference is stored in the variable image.
However you don't wish to send a message to an object, you wish to determine whether the variable image contains a reference to an object or not. To do this you need to compare the value of your reference with the "no reference" value - which is written nil. The value comparison operator in Objective-C (and C et al) is == so you need to test:
image == nil
Now you might ask why did the code you have execute without error, just not producing the result you expected, given that there is no object to send a message to? Objective-C supports sending messages to "no object", aka nil, and returns the "zero" value for the result type, i.e. 0, nil etc. When converted to a boolean value, as in your if statement, a "zero" value produces NO.
HTH
#yeesterbunny's answer is on point as to what you should do in this situation, but it's also good to know why.
Remember that every objc method call is a message. When you call
[objA isEqual:objB]
you're sending a message to objA asking whether it considers itself "equal" to objB.
If the "image" parameter to your method is nil, there's nothing there to send a message to. By definition, any message to nil returns nil. (And "nil" is the same as zero in an if statement.)
Moral of the story: test pointer equality with == (or !=, or implicitly as in "if (!image)") if you're looking for nil. Use isEqual: only when you want to test whether two objects (known to exist and of similar type) are semantically equal (e.g. when you want to know if two instances of NSString contain the same text).

How to determine whether a #selector wants a parameter?

The scenario presents itself where I have an object that stores an outside #selector for later use. By design, I would like to be able to add two kinds of selectors. The simple one, without parameters, like [object add:#selector(doSomething)], and the more complex one, with one parameter, like [object add:#selector(doSomething:)] (mind the colon). Let's say the selector is stored in a variable SEL mySelector.
In the execution, I need to decide between [anotherObject performSelector:mySelector] or [anotherObject performSelector:mySelector withObject:userInfo]].
The way I implemented this decision, is by providing a BOOL flag that redundantly stores whether the performance should be with or without the extra parameter. Yet although I can't find this in the docs, I have the feeling that I should also be able to ask the selector something like -(BOOL)needsParameter. I know, for example, that UIGestureRecognizer's addTarget:action: somehow makes this distinction automatically.
Could someone point me in the right direction?
You can use the NSMethodSignature class for that. For instance,
SEL mySelector = …;
NSMethodSignature *msig = [anotherObject methodSignatureForSelector:mySelector];
if (msig != nil) {
NSUInteger nargs = [msig numberOfArguments];
if (nargs == 2) { // 0 non-hidden arguments
}
else if (nargs == 3) { // 1 non-hidden argument
}
else {
}
}
Alternatively, you could use NSStringFromSelector() to get the string representation of mySelector and count the number of occurrences of the colon character.

What does it mean to return an object in a method?

I still cannot understand what does it mean to return an object in a method. What would its value mean?
If I have something like this:
-(ClassName *) methodName: (int) arg {
return arg;
}
I can't understand how an object can be returned through a method as the above. If someone can help me understand.
Thanks.
You would return an object by returning an object. For example, you could ignore the argument:
- (ClassName *)methodName:(int)arg {
return [[[ClassName alloc] init] autorelease];
}
You could turn the int into an object:
- (NSNumber *)methodName:(int)arg {
return [NSNumber numberWithInt:arg];
}
You could use the argument in some calculation to determine some property of the object returned. You could process the argument and return an object indicating the status of the calculation. And so on and so on. There's a practically unlimited range of ways you could return an object from a method. All it requires is that some object be created or accessed and then returned.
The above method returns a pointer to arg which is of type ClassName*.
I assume explaining the question would assume basic knowledge of how functions are called, how passed values are pushed on stack before function call and how return values is returned from a function.
In this specific case your arg variable is part of a class, meaning that it is stored in memory that is part of the object. When you return pointer to it you are pointing to a specific area of memory within the object.
Another option is to return copy of the value. It would mean make a copy and return it.
The difference is that if you return pointer to objects internal variable that object state could be modified from outside.
If you return copy that copy can be modified and the original object will not change.
Not sure if that helps, but you are asking about very basic software development topic which assumes some background knowledge.
Maybe specify what exactly you are looking for?
Think of methods like they are functions in math. In math, sin(180) is equal to 0. sin is the method, 180 is the argument and 0 is the return value of the method. An example of sin in objective-c might go like this:
-(double) sin:(double)angleInDegrees;
{
double sinValue;
//calculate the return value here and store it in sinValue.
//for example, if angleInDegrees is 180, then set sinValue to 0
return sinValue;
}
Returning objects is exactly the same. Look at this example:
-(NSString*) sayHelloTo:(NSString*)name;
{
return [NSString stringWithFormat:#"Hello %#!", name];
}
If I were to write it like a math function, then sayHelloTo(#"Tom") is equal to #"Hello Tom!". The only difference is that #"Hello Tom!" is an NSString object, not a double.