Call non-exported method from static library - objective-c

I am using a static library built by someone else in my Objective-C project. There is a C method in the library that I want to call, but it is not exported. How can a call this method from Objective-C code?

First of all: Why do you need that? Obviously the author of that framework did not see any need for this and things can break, if a method is executed directly.
However: Write a category on the receiver with that method and just do it. Objective-C binds dynamically, so this works.
#interface FrameworkClass(InternalMethodAddition)
- (void)internalMethod;
#end
// Do not implement this category.
…
FrameworkClass *object = …
[object internalMethod];

Related

Objective-C Passing Method Reference As Parameter

I've seen a lot of discussions NEAR this subject, but none that actually work in Xcode 5.x, especially using ARC. I have a simple problem:
I need to pass a method reference to a CreateButton method so that when the button is called it calls my custom function, and not some generic one.
I've tried using (SEL) type, but that doesn't work with ARC. I've tried using the &func method, but that claims I haven't declared the function yet.
So my need is:
Class A calls Class B and sends over the info to make a UIButton. Within that call, I want to send over the action:method in a reference. I'm sure this is done routinely, but I can't seem to find an iOS 7 / Xcode 5.x method of doing it. I've also reviewed the O'Reilly iOS 7 fundamentals and cookbook code and couldn't find this discussed anywhere.
Thanks for you help.
When I have to pass selectors around, I convert them to strings with NSStringFromSelector() and back to selectors with NSSelectorFromString().
Passing the strings around is a lot easier. You can store them in collections (arrays, dictionaries), serialize and unserialize them, and they will work naturally with ARC.
Example:
In your class A where you gather the information to create a button:
NSString *selectorString = NSStringFromSelector(#selector(yourActionMethodNameHere:));
// Gather more information needed by Class B here, then package
// it all up into a dictionary, for example
NSDictionary *buttonInfo = #{#"selectorString": selectorString, /* more stuff here */};
At this point, you can call your button-constructing method in Class B, passing along buttonInfo, which contains all the information that that helper method needs, including the selector. The method can convert the string back to a selector and use it like this:
SEL actionSelector = NSSelectorFromString(buttonInfo[#"selectorString"]);
// configure your button to use actionSelector here
You should be able to use SEL parameters? I know I have done before.
ARC might complain and give you a warning, but it won't fail to compile. It's simply a warning because it can't quite figure out what to do memory wise.
If you really can't get that to work though, another alternative would be to use a block, so you might call your method like
[objectA performMethodWithParam:paramA paramb:paramB completion:^{ ... do somethhing ... }];
Then in that method you can just call
completion();
Instead of actually calling a method.
Another alternative would be to use the delegate pattern. Create a #protocol defining a method such as classADidFinish then make class B implement that method. Then set the instance of classB as the delegate for your classA instance, and have it call that method when it's done.
Both of these approaches will stop ARC moaning at you.
But as I said, using SEL params should work fine. There is a way you can even get the compiler to stop showing you the warnings but it's a little ugly.

Pure C function calling Objective-C method?

Okay, I've read half a dozen threads on this subject, but none of the solutions appear to address exact needs.
Question:
How does a Pure C (.c) function call a method inside a Pure Objective-C (.m) class?
Every example / answer is using C inside an Objective-C (.m) method. I have a Pure C library that I have to create a simulator for, so I need to keep my Kernel in pure C and call out to my higher level emulation methods in Objective-C.
Any attempt I make to create a reference and call a method fails. Square bracket notation fails as well. Creating a global var in Obj-C and trying to use that in Pure-C doesn't work, as if the namespace is segregated.
Anyone done this?
Here's a diagram of the flow:
Obj-C UIButton CLICKED->Calls Obj-C method->Calls C function->Call Obj-C method
After much experimenting, I found that the most elegant way of solving my problem was to turn my core C library into an NSObject using the .m suffix. The method of calling back and forth resolved instantly. This change DOES alter my original library, but by so little, it's manageable. So to review:
My original C file was renamed to use the .m suffix. Then I added
#interface myCLibrary : NSObject
#end
to my .h file, and added to my formerly .c file, now renamed .m.
#implementation myCLibrary
#end
Just remember that C functions aren't to be pasted between these interface / implementation declarations, below them. Only Objective-C is to go inside these statements. Once I did that, calling the C functions, and calling BACK to other C functions worked great.
Thanks for all the help regardless.
Objective C can compile c method without any modification. To call c method from objective-c class you have to whatever you do in c, just include the header file then call method directly. Suppose you have a C header named test.h and in that you have a method sum(int i, int j); then first include test.h and then call test(1, 2);
If you want to call C++ method, use Objective-C++ (.mm extension) in the same manner as explained above.
I hope i understand you correctly!
You can do this via callback-function.
In you C file use this:
Define the callback-type
eventcallback g_callback;
Implement callback-class (executed by objective-c code)
void comm_set_callback(eventcallback callback){
g_callback = callback;
}
in objective-c:
Set the callback (i.e.: in viewDidLoad())
comm_set_callback(&testfkt);
C-Method called from extern C-function
void testfkt(){
[refToSelf testmethod];
}
Objective-C Method called from C-Method testfkt
-(void)testmethod{
...
}

Easy way to tell if a method is overriding another method?

I'm just beginning with ObjC. I'm wondering how to find out when looking at code, written by me or from a template that comes when you use the wizard to create a new class, how you can tell if a method is overriding something.
In Java, you can mark a method with #Override, and then it's very easy to see if it's overriding something. That's not foolproof, because #Override is optional, but if I'm still unsure I can just type that in and see if it generates an error.
Is the only way to look up the source of the superclass, or in the case of a framework to read the documentation?
I don't know a way to see this immediately, but you could check if super responds
to the same selector. Example:
- (void)myMethod
{
// Temporarily add this line. If the compiler does NOT complain,
// "myMethod" overrides a method from some superclass.
[super myMethod];
// ...
}
You can use instancesRespondToSelector to see if your instance has an implementation of the method in its object hierarchy.
[MyClass instancesRespondToSelector:#selector(myMethod)];
or depending on what type of checking you need to do
[MyClassSuperClass instancesRespondToSelector:#selector(myMethod)];

Restrict usage/generate a compile error when someone uses a particular method in an Objective-C class/object

Suppose I have an AwesomeClass but I cannot change it's implementation (ie it is from a static library or framework). I like everything about AwesomeClass except for - (void)thatOneBadMethod. I can subclass AwesomeClass to be MyAwesomeClass and override that method with an empty implementation (not calling super) but the problem is that if my fellow developer is using MyAwesomeClass and is unaware of my actions he may try to use thatOneBadMethod thinking that it is doing something it is not.
Is there some preprocessor directive that I can put in the override for thatOneBadMethod so that he gets a compiler error or warning when he tries to use it?
You can deprecate the method in the header file:
-(void)thatOneBadMethod __attribute__ ((deprecated("Unsupported, please call 'thatOneGoodMethod' instead!")));
But I'd also suggest generating an error when people try to call it:
-(void)thatOneBadMethod {
NSAssert(NO, #"Unsupported, please call 'thatOneGoodMethod' instead!");
}

NSClassFromString returns nil

Why does NSClassFromString return nil ? As per the definition it has to return class name.
How should I take care to rectify this problem? I need to instantiate a class from string and call the method, which is in the class, using the instance created.
This is how my code looks like:
id myclass = [[NSClassFromString(#"Class_from_String") alloc] init];
[myclass method_from_class];
But the method_from_class function is not being called, control is not going into it. And my code is error free. Any idea how to solve this in Objective-C?
If you are trying to instantiate a class from a static library, you must add the "-ObjC" flag to the "Other Linker Flags" build setting.
The Documentation for the function says:
Return Value
The class object named by
aClassName, or nil if no class by that
name is currently loaded. If
aClassName is nil, returns nil.
An example of how this should be properly used is as follows:
Class dictionaryClass = NSClassFromString(#"NSMutableDictionary");
id object = [[dictionaryClass alloc] init];
[object setObject:#"Foo" forKey:#"Bar"];
It is possible that your class is not getting linked if this is the only reference to it.
I had a factory method to instantiate various types of subclass. The factory had a switch statement that went to the appropriate subclass and alloc'd and init'ed it. I noticed that all of the alloc/init statements were exactly the same, except for the name of the class. So I was able to eliminate the entire switch block using the NSClassFromString() function.
I ran into the same problem - the return was nil. This was because the class was not used elsewhere in the program, so it wasn't getting linked, so it could not be found at runtime.
You can solve this by including the following statement:
[MyClass class];
That defeats the whole purpose of what I was trying to accomplish, but it might be all you need.
This happened to me when I add an external file to the Xcode project. Adding the .m file to Build Phases > Compile Sources solve the problem.
You also need to make sure the class you are trying to instantiate is included in the project. If you added it later, you made need to click the checkbox next to the Target you are building.
Why not decomposing all these calls ? This way, you can check the values between the calls:
Class myclass = NSClassFromString(#"Class_from_String");
id obj = [[myclass alloc] init];
[obj method_from_class];
By the way, is method_from_class an instance method or a class method ? If it is the later, then you can directly call method_from_class on the myclass value:
[myclass method_from_class];
I also saw an oddity where adding the standard singleton code espoused by apple prevented the class from being loaded. The code was working as expected, then I added the singleton, and suddenly the NSClassFromString started returning nil. Commenting out the singleton code resulted in the NSClassFromString resolving the class correctly. I don't understand the interaction, but I think the singleton static var was somehow getting mangled to hide the class name...?