IOS Method Calling - ios

I have a method which i need to call within another method. in a UIViewController
//This is how i call methoed
tmpUITextView.text= [self ssidValue:1 arrayOf:ssidArray];
//my Method
+ (NSString *)ssidValue:(NSInteger)selectedValue arrayOf:(NSMutableArray *)tmpArray {
NSString *result=[tmpArray objectAtIndex:selectedValue];
NSLog(#"%#",result);
return result;
}
but i am getting waring ( warning: 'UIViewController' may not respond to '-ssidValue:arrayOf:')and crash it.
Please tell me what i am doing wrong here.
Thanks in Advance

You are declaring the method as a class method (note the "+") but you are calling it as an instance method.
To solve this, either declare it as an instance method (replace "+" with "-") or call it as a class method:
[[self class] ssidValue:1 arrayOf:ssidArray];

use the instance method type declaration i.e.,. use "-" instead of "+" for method declaration
and you can call it using the class name
tmpUITextView.text= [class_Name ssidValue:1 arrayOf:ssidArray];
class_name is the name of the class Wherethe method initialized

You are declaring the method as a class method (note the "+") but you are calling it as an instance method.
To solve this, either declare it as an instance method (replace "+" with "-") or call it as a class method:
[[self class] ssidValue:1 arrayOf:ssidArray];

Related

Call a static var in another class , in objective c

I try to get a static variable from a class so I do this
in file Login.h
+ (instancetype)setToken:(NSString *)aToken;
In file Login.m I do this
static NSString* token;
.......
+(instancetype)setToken:(NSString *)aToken
{
token = [aToken copy];
return aToken;
}
so I can get value
[Login setToken:token]
But I don't know how to get this value in another class
You have to provide a class getter method as well:
+ (void)setToken:(NSString *)token;
+ (NSString *)token;
However using a singleton is the preferred way of doing this, allowing you to use a #property.
Create a getter method for that. This method will return that static variable value.
Add signature of that method to Login.h file.
+ (NSString *) getUniqueToken;
Relevant method in Login.m class.
+ (NSString *) getUniqueToken {
return token;
}
As it is a class method you can direclty access with out creating object of login class.
Call above method in other controller class, It will return token string.
[Login getToken];

Call method hierarchy in Objective-C

I declare a class method:
+(int)widthScaled:(UIImage *)image maximumHeight:(int)max{
int width = 0;
width = (image.size.width - (((image.size.height - max)*100)/image.size.height)*image.size.width)/100;
return width;
}
In the same class, I declare an instance method like these:
- (void)generarVistas{
if(...){
...
}else{
for(...){
...
//I need to put the class method here but if I call the class method like this, don't recognize
int variable = [[self class] widthScaled:image maximumHeight:max];
...
}
}
I try to put the class method in instance method but doesn't work.
What context should I indicate to recognize the class method?
The problem you are facing is that [self class] is a runtime call who's return result is not known until runtime. The compiler doesn't know what class it is. The code you're writing must always be invoked from a fixed class, so don't do that. If the class is FooClass, then use this form:
int variable = [FooClass widthScaled:image maximumHeight:max];
(replace [self class] with your class name, e.g. FooClass.)

Use an NSString to programatically access or create a method in Objective-C

I am trying to use an array of strings dynamically access methods at runtime within my class. For now the methods are already there, eventually I want to create them.
Is this possible?
For example:
bool nextLevel=NO;
for(NSString * match in gameLevels)
{
if([match isEqualToString:self.level])
{
nextLevel=YES;
}
else if(nextLevel==YES)
{
self.level=match;
nextLevel=NO;
}
}
//access method named self.level
Thank you in advance!
I use:
NSSelectorFromString(selectorString)
In your case, the selectorString would be:
NSString * selectorString = #"setLevel:";
This is 'setLevel' instead of 'level' because the Objective-C runtime will automatically expand dot properties to these selector names when assignment occurs.
To access a method based on a string, check the other answer.
To add a method in the runtime you need to create a IMP function or block.
If using a function, could be something like:
void myMethodIMP(id self, SEL _cmd)
{
// implementation ....
}
You could also use a block like this:
IMP blockImplementation=imp_implementationWithBlock(^(id _self, ...){
//Your Code here
}
Then you need to add the method, like this:
class_addMethod(yourClass, #selector(selectorName), (IMP) blockImplementation, encoding);
The encoding part is a special runtime encoding to describe the type of parameters your method receives. You can find that on the Objective-C runtime reference.
If you receive dynamic arguments on your generated methods, you need to use the va_list to read the values.

iOS jailbreak get object based on class name

I have a dylib which has a object of class "mConWifi". I have the main app which loads this dylib and executes following code
Class klass = objc_getClass("mConWifi");
SEL sel = sel_getUid("ListAllWifi:");
if ( [klass respondsToSelector:sel] )
objc_msgSend(klass, sel);
When above code is called, object of class mConWifi is already created in Memory.
My objective is to get object based on class name and then invoke a method. With above code I am not able to as respondsToSelector fails. I have already tried "ListAllWifi" and "ListAllWifi:"
Any ideas how to get object of a class based on class name?
Thanks in advance.
I think your problem is that you are trying to test a method of class (which are declared with +), but in fact you have an instance method, declared with -.
Try this:
Class klass = objc_getClass("mConWifi");
SEL sel = sel_getUid("ListAllWifi:");
if ( [klass instancesRespondToSelector:sel] ) {
id object = [[klass alloc] init];
objc_msgSend(object, sel);
}

Can OCMock run a block parameter?

Assume a method signature such as the following:
- (void)theMethod:(void(^)(BOOL completed))completionBlock;
I would like to mock this method signature to ensure the method is called, and just call the completion block. I see from other posts like this one that I can mock the method call and accept any block, but not run the block. I also know there is a andDo method that I might be able to use, but I can't figure out how to pass a block in and run it.
Any ideas?
Thanks.
You can use [[mock stub] andDo:] like this to pass another block that gets called when your mocked method is called:
void (^proxyBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
void (^passedBlock)( BOOL );
[invocation getArgument: &passedBlock atIndex: 2];
};
[[[mock stub] andDo: proxyBlock] theMethod:[OCMArg any]];
The block gets a NSInvocation instance from which you can query all the used arguments. Note that the first argument is at index 2 since you have self and _cmd at the indices 0 and 1.
EDIT 2:
Use https://stackoverflow.com/a/32945785/637641 instead.
Using andDo: is perfectly fine, but personally I prefer [OCMArg checkWithBlock:].
[[mock expect] theMethod:[OCMArg checkWithBlock:^BOOL(id param)
{
void (^passedBlock)( BOOL ) = param;
// Normally I set some expectations here and then call the block.
return YES;
}]];
// Code to test
[mock verify];
You can use also [mock stub] but I prefer to verify that theMethod is called.
EDIT 1
OCMock 3 version:
OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
{
// call the block...
return YES;
}]]);
// Code to test
OCMVerify(mock);
This is now supported in OCMock 3.2. You can use [OCMArg invokeBlock] and [OCMArg invokeBlockWithArgs:...] to invoke the block passed as an argument to a stubbed method.
Using andDo: blocks is sometimes required but for most cases you can use [OCMArg invokeBlock] or [OCMArg invokeBlockWithArgs:].
In your example you can do the following
If you don't care about the arguments:
// Call block with default arguments.
OCMStub([mock theMethod:[OCMArg invokeBlock]];
If you want to send specific arguments:
// Call block with YES.
OCMStub([mock theMethod:([OCMArg invokeBlockWithArgs:#YES, nil])];
Note the nil termination since you can pass multiple arguments to this method.
In addition the entire expression must be wrapped in parentheses.
You can read more about it in the OCMock documentation.
This is Sven's answer updated for OCMock 3.
OCMStub([myMock myMethodWithMyBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
void (^passedBlock)(BOOL myFirstArgument, NSError *mySecondArgument);
[invocation getArgument: &passedBlock atIndex: 2];
passedBlock(YES, nil);
});

Resources