prefix header import cancels out library's implementation of same method - ios

I have a category on UIView that implements - (void)setWidth:(CGFLoat)newWidth, that sets the width by changing the frame of the view and a static library that has the same method.
I am using the category throughout the whole project by adding it to the .pch (prefix header) file.
When I try to use the library method, my category overrides the setWidth: method and the library is never called. I don't really want to remove the category from the prefix header as that would cause serious issues with the rest of the project.
Any ideas how to resolve this issue?
Thank you!
~LSonic

Unfortunately, Objective-C methods (including those from categories) exist in the same namespace. If there are two method implementations with the same name, it is not defined which is called at runtime.
This is discussed in Avoid Category Method Name Clashes in Appleā€™s Programming with Objective-C.
There is no better way than prefixing the names of methods in your categories. For example:
- (void)ls_setWidth:(CGFLoat)newWidth;
Also see this question for more.

Related

"Cannot define category for undefined class" error in Xcode 11.3, no access to source file

I'm trying to make a category for a class that gets defined in a source file I don't have access to, namely RunnerViewController.
The two important files here are iPad_RunnerAppDelegate.h and FilesBrowser.mm. I do not have access to the header file's corresponding source file.
iPad_RunnerAppDelegate.h contains a forward declaration to the RunnerViewController class, and can reference that class with no difficulties.
However, if I try to #include "iPad_RunnerAppDelegate.h" in FilesBrowser.mm and then try to create a category in the same file, it doesn't recognise the class name.
Despite this error appearing, I can still use the RunnerViewController class inside FilesBrowser.mm, I just can't make categories for it.
What's happening here, and how would I fix it?
I've had to do this same thing but it was a long time ago. The problem is that without some indication of where to apply the category, your code cannot work alone. What you need is info to the compiler to let it know where it's going to insert the category.
In FilesBrowser.mm, you will tell it by adding this BEFORE "iPad_RunnerAppDelegate.h":
#interface RunnerViewController: UIViewController // or whatever it actually subclasses
#end
Now the compiler knows that its going to insert the category against an Objective C class named RunnerViewController.
But - you're not completely done. Now you need to insure that the runtime / loader do the class loading and category insertions at the proper time. This is where my knowledge gets a bit fuzzy, so it may not turn out to be a problem at all.
What I believe needs to occur is for the RunnerViewController class to get loaded first, then later at some point the category you wrote applied to it (but this may not be necessary). So if RunnerViewController is statically linked into your app (using a .a archive), then you're good for sure. But if that class is in a dylib loaded dynamically, and your category is statically linked - well that might be a problem. I just don't know how long Apple waits to try and deal with the categories (which by the way the -ObjC link flag is for.
In any case try the code above first and just see what happens. If RunnerViewController is dynamically loaded, and you get some hard runtime error, there is a workaround where you would make your category go into a module/framework that is also dynamically linked, but gets linked after RunnerViewController.
In the end I believe you have a good chance of making this happen.

Is it safe to extend an Objective-C class in Swift with non-prefixed methods?

In Objective-C, one should always prefix category methods, e.g. if extending UIView with the method descendants, you'd add zzz_ and make it zzz_descendants to avoid naming conflicts. Is that necessary for a function in extension UIView { ... } in Swift?
It's not necessary in order to compile. However, it's a good idea to prefix extension methods to avoid possible conflicts later on, in case Apple should introduce a method by the same name. An even more important reason, in my opinion, is to make clear that the extension method is custom code and not part of the standard API.

I only have header file from framework in iOS, but need to change property

Here is the things.
I use a framework which contains only header files.
The framework use SOMEWebView which is a subclass of UIWebView.
I need to set this SOMEWebViews property "allowsInlineMediaPlayback" to "YES".
That webView is used by SOMEViewController's UIWebViewDelegate.
How can I make this?
Thanks in advance.
Create a category on SOMEWebView that has the following method declaration:
+ (BOOL)allowsInlineMediaPlayback
{
return YES;
}
EDIT:
N.B. Only do this when you control the code you're overriding. Doing this without knowing what you're doing can cause undesirable behaviour (especially when overriding Apple framework classes using this method). Since you're not in control of the code, I'd suggest you also check out "method swizzling" or see if you can simply subclass the SOMEWebView in question.

Using Categories in Objective C

I have a file called ViewMessages.m which is becoming quite verbose. I'd like to refactor and put part of my methods into a separate file. It seems that Categories are the right way to go, so I've created a Category on ViewMessages called DataEngineViewMessages
It created 2 files, DataEngineViewMessages.h and DataEngineViewMessages.m
My Question: Do I need to #import "DataEngineViewMessage.h" in my original ViewMessage.h or .m in order to access my new methods?
Not into the .h file. The category header should import ViewMessages.h, and if required the category header should be imported into ViewMessages.m. This prevents any kind of circularity.
Usually you want to differentiate between category methods that should be public (defined in a header perhaps like ViewMessages+DataEngine.h) and category methods that are for internal use (defined in a header perhaps like ViewMessages+Private.h). The former shouldn't be included by ViewMessages and the latter should (again, in the .m file).
Any code that calls the methods will raise a compiler warning if the compiler can't see the method definition. They may also raise an error if the compiler can't figure out exactly what to do about the return type and you're expecting it to be an atomic C type.
In terms of keeping the external interface untouched, you can probably just add a #import for your category methods at the bottom of the main class's header file.

How to create a class which is sub class of two classes

I have class called ViewController. How to make this class is a sub-class of "metaiosdkViewController" and "JWslideViewController". Help me with syntax.
i have written like this
#interface ViewController : MetaioSDKViewController,JWslideViewController
but this giving me error
objective-c doesn't support multiple inheritance,but if you want to add some extra behaviour you can achieve it through delegates..
yes objective-c doesnt support multiple inheritance but you can give one parent so
#interface ViewController : MetaioSDKViewController
and
#interface MetaioSDKViewController : JWslideViewController
this is just an idea I know you can implement well as per your need
What is it that you want to achieve with multiple inheritance?
Do you want to override methods from each of these super classes?
Note that objective c provides 2 mechanisms for extensibility:
1) Implementing a Protocol and make your object the delegate:
#interface ViewController : <MetaioSDKViewController,JWslideViewController>
This enforces ViewController to implement certain methods as defined in contract by 2 delegates, and at some point in processing, they get called. If you don't implement them, they may simply not be called but you may not get desired functionality.
Example: UITableViewDataSource protocol that defines many methods that UITableViewController subclass implements. cellForRowAtindexPath is very famous example of a delegate method that your own table view subclass must implement to draw your own custom cells.
Note that this is not the type of extensibility that subclasses provide in general sense. Your class does not extend any functionality here. Rather it becomes what it says - a delegate - someone who is assigned to do some task. Like you do:
yourTableView.delegate = self; //tell self to be the delegate of yourTableview
Library code does it's stuff and in some point in processing it calls [delegate someMethod]. If your own class implements it, it calls it, otherwise delegate will be nil, and it may just be NO-OP and you don't get desired functionality. Again, this is implementation-dependent. Maybe the protocol defines that the method is compulsory, in which case your class MUST implement this method in order to compile.
2) Implement a category:
This is sort of a shortcut way to extend library classes. They act like an extra stub which, when your code runs, attaches itself to the already existing memory layout of the library objects and provides extra functionality.
You can define a category on any of the in-built classes as well. In fact that is the primary objective it is used for. For example, here is an NSString category which provides HTML conversion. There are hundreds of categories implemented as open source and they provide enormous benefits where library code falls short. Discussing their suitability in entirety is however out of scope for this discussion.
One thing to note however is: You do not override anything using a category. Rather you are supplying something in extra. For example if you want some custom drawing across all your app views, you can define a category on UIView in your project and then all your views could simply include the category header file. You don't even have to inherit from this category, you simply inherit from the base type.
e.g. in the NSString category example above, you do not have to define your NSString to be of type NSString+HTML. Instead you just include the responsible NSString+HTML.h file wherever you want those extra methods like stringByConvertingHTMLToPlainText and so on. The changes remain limited to your project - to the files where you include this category.
Categories do not provide for extra data members - and that is something that only inheritance can provide. Yet, multiple inheritance among viewcontrollers is something you should definitely reconsider hundred times - you will see that what you are looking for is not multiple inheritance.

Resources