Unrecognized selector calling category method in static iOS library - objective-c

I am using some third party software to aid in writing an iPad application using Xcode 4.3.2. The software is open source and is usually set up so its code will be compiled along with whatever code the developer writes for the application. Because I was using the software in numerous places, I decided to build it as a static library for the iOS simulator.
I was able to build the library, and convert one application to link to that library instead of compiling the original source code. However, when I go to run the application on the simulator, I get an error that says, unrecognized selector sent to instance.
I have verified that the program is successfully using portions of the static library. However, there is one piece of code that tries to call a method on an object, and that where the failure occurs. The method being called is not actually defined in the interface of that object. Rather it is provided in an additional module that defines a category for that object's class. The header file for that module is properly included and the compiler should have been able to find the category method and apply it to the object, yet at run time, the error mentioned above occurs.
I used the 'nm' command to verify that the category method exists in the static library. Here is an example of the output:
nm libStaticLibrary.a | grep categoryMethod
00000130 t -[SomeClass(Category) categoryMethod:]
0000354c s -[SomeClass(Category) categoryMethod:].eh
What ideas do people have about how this library can be made to work correctly with the desired application?

Your 3rd party framework is probable using a category on a existing (apple) class. But to load/find the category you need to add the -ObjC flag in the build settings under Other Linker Flags

Pfitz answer is great, but this will cause the compiler to load a bunch of unused binaries to your project which is not what you want. Please refer to this answer to know why https://stackoverflow.com/a/22264650/1363997
Here is the best solution:
1) select your project target from the left panel (the folders navigator)
2) select "Build Phases" tap
3) expand "Compile Sources" cell
4) hit the plus button at the bottom and then add your category's .m file
Done!
Note: you have to search for the file by navigating through the folder by your self, don't type the file's name in the search field

Related

Xcode 8 Beta #import unexpected behavior

So I'm just coming back to programming for macOS after a few years hiatus, and have discovered the #import syntax. I created a sample program to test it out, but it's not working as my googling seems to suggest that it should.
Test project setup:
Open Xcode
File>New>Project...
Select the Cocoa Application template for macOS. Click Next
Name the project "ModuleTest", add organization name and organization Identifier. Select Objective-C as the language, check Use Storyboards, make sure "Create Document-Based Application", "Use Core Data", "Include Unit Tests" and "Include UI Tests" are all unchecked. Click Next and choose a save location. Don't create Git repository, and don't add to any project or workspace. Click Create.
In the Navigator, click on Main.storyboard.
From the Object Library, drag an AVKit Player View object onto the View of the View Controller Scene in the Storyboard.
Now at this point, we can see the symptom, which is that if you build the project, a window will pop open, but the player is missing from it, and the xcode output window shows a message such as
2016-08-16 09:07:46.465 ModuleTest[19778:4097187] Failed to set
(contentViewController) user defined inspected property on (NSWindow):
*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (AVPlayerView) for key (NSDestination); the class may be defined
in source code or a library that is not linked
This error occurs regardless of whether I put an #import AVKit; statement into AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m, or main.m. However, simply linking the AVKit.framework in the "Link Binary With Libraries" section of the project's Build Phases, solves the issue, no #import needed anywhere.
So what's going on? I thought #import was supposed to eliminate the need to manually link frameworks? Am I going through the process incorrectly? Is this happening because I'm using storyboards? Any ideas?
The problem is that there is no actual code that references the AVPlayerView. Try adding a single line of code that uses AVPlayerView and you'll notice that the error is gone.

Xcode cannot find ProductModuleName-Swift.h

I'm attempting to import my "-Swift.h" file into one of my Objective-C .h files but xcode keeps telling me that the file doesn't exist
#import "Aesculus-Swift.h"
If I command click on the file name it will take me to the generated header file so I know it exists. Why is xcode not able to find it?
This seems like just another issue with Xcode and it's complex tool chain of static analysers and compilers.
Openradar lists radar://21362856 - Swift to Objective-C bridging is unreliable. I am sure there are more but I stopped looking after finding one for this example.
The author imarcelv notes in the description:
I asked a Swift engineer at WWDC in a lab and even he didn't know how to fix this issue.
Steps to Reproduce:
Add a ramdom Swift class to an Objective-C project
Add the #import "ModuleName-Swift.h" file that Xcode generates automatically
Try to use it or just try to compile the project
From time to time it simply doesn't work
It's probably best to file a radar on this issue as it seems that others are already calling it out.
One other thing you could try...
Historically, it was possible for Xcode to completely lose it's syntax highlighting and you could always find out what files the static analyser was giving up on by increasing log level of clang.
I'm not sure if it's still relevant but if I was in your position I'd be trying this command:
defaults write com.apple.dt.Xcode IDEIndexingClangInvocationLogLevel 3
This generates logs you can search with using Console.app for just xcode to highlight the messages. You'll want to trash the derived data of your project to force it to re-compile things.
Although not the same issue as what you're seeing, I have had this post on the syntax highlighting issue bookmarked for years for the above defaults write command to try in times like these.
I solved this recently by adding the following entry to my .xcconfig (you could add it in Xcode's Build Settings > User Header Search Paths if you prefer).
USER_HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/MyFramework.framework/Headers
This tells the compiler to search for headers in the build output directory, which is where Xcode puts the generated header (at least in the case of this framework).
In my case this is a directory like ~/Library/Developer/Xcode/DerivedData/MyProject-LongCode/Build/Products/Debug-iphonesimulator/MyFramework.framework/Headers/MyFramework. You might find your generated header in there too.
Xcode's header and dependency management is a hot mess, and it's not surprising that it doesn't work for you.
I had trouble with this stuff & found that your -Swift file is the Product name of your Target ( not just the name of your Target ) . I found the details here helpful: http://ericasadun.com/2014/08/21/swift-calling-swift-functions-from-objective-c/
When you encounter such situation, just find your kinda "ProductName-Swift.h" file by just cmnd+click on it (even if xcode shows warning about it is not found, the #import "Aesculus-Swift.h" string is still clickable) and then in opened code editor window choose context menu and "Show in Finder" item, then explicitly add it to your project.

Some Parse methods not working in iOS SDK

I added the Parse SDK today (1.2.15) to an existing project which targets iOS7 and is built in Xcode5. I followed the instructions on https://parse.com/apps/quickstart#ios/native/existing exactly. Some things work, like creating and saving a PFObject. Certain functions however cannot be found by the compiler. For instance [PFUser enableAutomaticUser]; generates the error
AppDelegate.m:21:13: No known class method for selector 'enableAutomaticUser'
and [PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions]; generates the error
AppDelegate.m:20:6: Use of undeclared identifier 'PFAnalytics'
Are the docs out of date and have these methods moved? I have tried restarting Xcode and cleaning my project. I can see the PFAnalytics.h file if I expand Parse.Framework in Xcode, and when I look at PFUser.h I can see a declaration of enableAutomaticUser;. Why can Xcode see some Parse classes and methods but not others?
My problem was that Framework Search Paths in Build Settings contained two directories, and one was invalid, resulting in this very strange behavior where some methods in Parse worked and others didn't.

Strange error when compiling iPad application(ld: duplicate symbol _OBJC_CLASS_$)

when i compile my project, i have this error :
ld: duplicate symbol _OBJC_CLASS_$_DNCloseButton in /Users/.../Library/Developer/Xcode/DerivedData/...Objects-normal/i386/DNCloseButton-7045D069F03DAA13.o for architecture i386
Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/clang++ failed with exit code 1
I know that the problem is about the class DNCloseButton but i don't how to solve it ? thanks for your answers.
Ensure you've only declared the interface once, in a header file (.h), and imported that header file with #import and not #include.
Sometimes XCode cocks up a little bit and links the same file twice at the linker stage. To fi this:
Remove the file from your project (select the 'remove references' option) and then add it again.
Clean with shift-cmd-k
Build
Hope this helps!
This will happen if a source file is include twice in your Compile Sources Build Phase.
To check this in Xcode 4:
Select your Project from the file list.
Select your target from the left column.
Click on the Build Phases tab on the top bar.
In the search field, type in the name of the class that is causing the linker error. In the case of the question above, it is DNCloseButton (ignore the preceding _).
If the source file for the class appears twice in the Compile Sources list, delete one of the entries.
You might also get this error if you by accident #import the .m file instead of the .h file.
This may happen in the following cases.
You have put the same class implementation into two different files;
You actually have just one implementation of this class, however you are also linking in your project a framework or library containing a class whose name is exactly the same of yours.
Try finding in the whole project your class and make sure only one copy is available within your project.

Objective-C category is not loaded - How to debug this

I have two projects which the RestKit framework.
One project works without problems but another project fails, as soon as the RestKit framework is used.
I found out that the failing code is this:
return [anNSString MD5];
The MD5 method is a category method and is imported like this:
#import "NSString+MD5.h"
However, in one project, I keep getting the following error:
-[__NSCFString MD5]: unrecognized selector sent to instance 0x88a3390
I understand the basics of categories, and that they can be loaded at runtime, but I don't see why the category does not get loaded in this case.
These are the files on github: NSString+MD5.m, NSString+MD5.h,
Make sure you have the -ObjC flag enabled. Or it will not link categories in a static library.
Objective-C categories in static library
It's not enough to just include the header file. You also need to compile and link the .m file in your project.