iOS static library, cannot access some class methods - ios

I'm building a static library in iOS. after importing that library in my project, I added -ObjC in Other linker flags. But when I call the class methods(currently 3 available), 2 of them are being called and executed properly, but the last one is getting this error: "+[RankConferenceLib joinConferenceWithName:]: unrecognized selector sent to class 0x5044dc".
This is my Header file of library
#interface RankConferenceLib : NSObject
+(void)initEnvironment;
+(void)orientationChange;
+(void)joinConferenceWithName:(NSString *)name;
#end
in .m file of library
+ (void)joinConferenceWithName:(NSString *)name
{
//....codes
}
and in my project I'm calling them
- (IBAction)join:(UIButton *)sender {
[RankConferenceLib joinConferenceWithName:#"User"];
}
Please tell me what I'm missing here. This is my first static library. I've searched but could not find any help which is similar as my situation here. Please mention what else you need to know.
Thank you.

I have checked this and for me it's working fine without any linker flags added.
The only one error possibility is something happened inside the + (void)joinConferenceWithName:(NSString *)name
Write a log inside the joinConferenceWithName to printout the parameter name and make sure this is calling and the problem is occurring inside that method.
+ (void)joinConferenceWithName:(NSString *)name
{
NSLog(#"the name is: %#", name);
}
Finally, make sure that you added the latest modified static library into your project.
You can download the working sample from here

Try Running using the -all_load linker flag
Apple Documentation
Stack Overflow Answer

Related

Receiver '**' for class message is a forward declaration Error. Swift Static Library use in Objective-C

I am trying to make a Swift Static library and apply it to Swift and Objective Project.
import Foundation
#objc open class Library001_Test: NSObject {
public override init(){}
#objc public func testPrint() {
print("My Name is Andi")
}
#objc public func getUUID(userName: String) -> String {
let uuid = UUID().uuidString
return "\(userName)'s UUID : \(uuid)"
}
}
I wrote the code like this using Swift.
And in the Edit Scheme menu, I changed the Build Configuration to Release and proceeded with Run. As a result, the 'libLibrary001.a' file and the 'Library001.swiftmodule' folder were created.
These two artifacts work well when pasted into a Swift project and imported.
But the problem is an Objective-C project.
I put both artifacts into my project and checked:
[General - Frameworks, Libraries. and Embedded Content] whether the library is recognized
Whether the library is recognized in [Build Phases - Link Binary With Libraries]
Check [Build Settings - Library Search Paths] address
Defines Module - Yes
And I put '#class Library001_Test;' in ViewController.h
#import <UIKit/UIKit.h>
#class Library001_Test;
#interface ViewController : UIViewController
#end
And in ViewController.m, '#import "ProductName-Swift.h" and the created Class were loaded.
#import "ViewController.h"
#import "SwiftInObjectiveC-Swift.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
Library001_Test *test = [[Library001_Test alloc] init];
}
#end
error : Receiver 'Library001_Test' for class message is a forward declaration
error : Receiver type 'Library001_Test' for instance message is a forward declaration
An error occurred while doing this. I've tried all the methods I've found on the internet and I'm wondering where the problem is.
Is the code the problem? Did I not set it up well??
The Swift file created in the project is import well in Objective-C... Why the hell is the .a file not working like this?
My problem was with '(ProductName)-Swift.h'
If you look at how Swift Code is used in Objective-C, many articles say to import (ProductName)-Swift.h. So I only added the project header that I want to apply, but I also need to add the product header made from the library.
My problem was simple, but it took me a long time to figure it out. The error was not found 'Class' and 'func' in Swift static library. My workaround was resolved using the (LibraryProductName)-Swift.h of the library I created, rather than the (ProductName)-Swift.h of the project you are working on.
If you refer to the address below, you can prevent the error that occurred in advance.
https://medium.com/#mail2ashislaha/swift-objective-c-interoperability-static-libraries-modulemap-etc-39caa77ce1fc

How to call UnitySendMessage method in swift?

I tried calling UnitySendMessage method in my iOS Framework project using swift language but it is showing this error-
Use of unresolved identifier 'UnitySendMessage'
Here is the code snippet for my swift file-
import Foundation
#objc public class Example : NSObject{
#objc open static let shared = Example()
#objc open func printMsg(){
print("\(#function) is called with message:");
UnitySendMessage("CallbackTarget", "OnCallFromSwift", "Hello, Unity!");
}
}
Getting stuck here, can you please tell me what am I missing?
check Answer here.
UnitySendMessage is in libiPhone-lib.a, and as far as I can tell, the
Unity folks don't include any header that declares it.
I just added the following to my code
extern void UnitySendMessage(const char *, const char *, const char
*);
If you look at the generated AppController.mm, they basically do the
same thing for the various UnitySendXXX functions, rather than
including a header.
Having said that, while you will be able to build a library that calls
UnitySendMessage, that library probably won't work unless it's linked
into a Unity project, since UnitySendMessage is going to require more
than just libiPhone-lib.a to actually work.
Just add this code to your Bridging-Header.h file:
#import "UnityInterface.h"
Make sure that your files are in the XCode project that was build from Unity, so the actual UnityInterface file that is created by unity is present.
Worked for me :)

Duplicate symbol error with GoogleCast.framework

I just started porting an Android app to iOS, and am hitting a major roadblock that I can't figure out despite scouring many similar questions.
I am attempting to follow the pattern implemented in the CastVideos sample where the GoogleCast API is encapsulated in a singleton class which I've called CastManager. To use my singleton class, I #import "CastManager.h" in AppDelegate.m. Then in CastManager.h, I #import <GoogleCast/GoogleCast.h> so that I can use classes and protocols from it as part of CastManager's public interface. However, because I'm importing CastManager.h in both CastManager.m and AppDelegate.m, the linker is finding duplicate symbols from the GoogleCast framework.
This is my CastManager.h:
#import <GoogleCast/GoogleCast.h>
#import <Foundation/Foundation.h>
#interface CastManager : NSObject
#property(nonatomic, strong) GCKDeviceScanner *deviceScanner;
+ (instancetype)sharedCastManager;
#end
And corresponding CastManager.m:
#import "CastManager.h"
#implementation CastManager
+ (instancetype)sharedCastManager {
NSLog(#"sharedCastManager");
static CastManager *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
- (instancetype)init {
NSLog(#"init()");
if (self = [super init]) {
self.deviceScanner = [[GCKDeviceScanner alloc] init];
}
return self;
}
#end
And this is the main part of my AppDelegate.m:
#import "AppDelegate.h"
#import "CastManager.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CastManager *castManager = [CastManager sharedCastManager];
return YES;
}
However, this results in the following error from the linker when attempting to build the project:
duplicate symbol _kGCKDeviceCapabilityVideoOut in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/CastManager.o
... many similar errors ommitted for brevity ...
duplicate symbol _kGCKDeviceCapabilityAudioIn in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Projects/MyCastApp/GoogleCast.framework/GoogleCast(GCKDevice.o)
ld: 8 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As far as I can tell, this exactly copies the pattern as defined in the CastVideos sample, but the sample compiles fine, and mine doesn't, and I've scoured through both projects trying to find what is different, but I just don't see it. Further, I don't see anything really wrong with doing this, and would expect it to work fine. I can't think of any other way to do it, really.
Here are the relevant files from the CastVideos sample for comparison:
ChromecastDeviceController.h
ChromecastDeviceController.m
AppDelegate.m
Other questions point to solutions that don't apply or don't fix it:
I'm not importing a .m file on accident.
I don't have duplicate references to any files in the project.
The "Compile Sources" section of the "Build Phases" project setting doesn't include any duplicates.
I've added the '-ObjC' linker flag as described by the GoogleCast API docs, though it has the same error with or without it.
I've tried deleting the delegate data and doing a clean before building.
This is with Xcode 6.3.1 running on OS X Yosemite 10.10.3 and the GoogleCastSDK-2.6.0 package from the SDK documentation page
I have checked in my sample project with the problem at https://github.com/nshafer/MyCastApp
Any help is greatly appreciated!
Edit: the duplicate is somewhat related, it's definitely about the same symbols, but the answers there didn't help, as I'm not using Object-C++, but rather just Objective-C. I don't have a .mm file, just a .m file.
For me it helped to switch the "No Common Blocks" compiler setting to NO:
It pretty much seems to make sense, the setting is explained here: What is GCC_NO_COMMON_BLOCKS used for?
The linker tells you that you have a variable named kGCKDeviceCapabilityVideoOut in two files, AppDelegate.m and CastManager.m. Since it's not in your source code, it's most likely in the GoogleCast code that you are including.
Either change the GoogleCast.h file, or make sure it is only included in one .m file. Including it from CastManager.h means it is indirectly included in every file that includes CastManager.h, so I would avoid that and only include it from CastManager.m. You'll probably have to add
#class GCKDeviceScanner;
in your CastManager.h file.
I found another fix, which is to edit GCKDevice.h in the GoogleCast.framework/Headers folder. Change the 4 constants from GCK_EXPORT to GCK_EXTERN near the top of the file.
/** Device capability flag for video out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoOut;
/** Device capability flag for video in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoIn;
/** Device capability flag for audio out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioOut;
/** Device capability flag for audio in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioIn;
I detailed this in a bug report I filed with Google's issue tracker, but it was marked as a duplicate of another somewhat related issue. Either way, it will perhaps get fixed in the next version. Until then, I would suggest going with changing the "No Common Blocks" setting as detailed in Joobik'com's answer, as that doesn't involve changing the 3rd party code.

Unit testing a static library with RestKit

I'm attempting to follow along with the RestKit unit test guide ( https://github.com/RestKit/RestKit/wiki/Unit-Testing-with-RestKit ) except that my project is a static library instead of an app.
Here is the test I've written:
- (void)testMappingOfDate
{
id parsedJSON = [RKTestFixture parsedObjectWithContentsOfFixture:#"plan.json"];
RKMappingTest *test = [RKMappingTest testForMapping:[self planMapping] object:parsedJSON];
[test expectMappingFromKeyPath:#"plan.date" toKeyPath:#"date"];
STAssertNoThrow([test verify], nil);
}
When I attempt to run the test I receive this error on the first line of the test:
error: testMappingOfDate (api_clientTests) failed: -[NSBundle parsedObjectWithContentsOfResource:withExtension:]: unrecognized selector sent to instance 0x1765c40
It seems like its not finding the NSBundle category defined by RestKit, but my test target header search path is set to "$(BUILT_PRODUCTS_DIR)/../../Headers" and I've verified this path includes NSBundle+RKAdditions.h which contains the supposed "unrecognized selector".
Is there something I'm missing here?
You are trying to include a category within your binary that comes from a library. To get that accomplished you will need to add the following to your (Unit-Test-Target's) build settings.
Other Linker Flags: -ObjC
From Apple's QA:
Objective-C does not define linker symbols for each function (or
method, in Objective-C) - instead, linker symbols are only generated
for each class. If you extend a pre-existing class with categories,
the linker does not know to associate the object code of the core
class implementation and the category implementation. This prevents
objects created in the resulting application from responding to a
selector that is defined in the category.
Solution:
To resolve this issue, the static library should pass the -ObjC option
to the linker. This flag causes the linker to load every object file
in the library that defines an Objective-C class or category. While
this option will typically result in a larger executable (due to
additional object code loaded into the application), it will allow the
successful creation of effective Objective-C static libraries that
contain categories on existing classes.
The error means that the "unrecognized selector" issue is at runtime. The compiler and NSBundle+RKAdditions.h do not give this error they would at compile timr.
The issue is that the code that has #implementation NSBundle(RKAdditions) is not linked into your app. So you need to add this to your build

XCode 4 : error at runtime "unrecognized selector sent to instance"

I develop a static library and build my lib.a.
When I use this library in a iOS project (iPhone app built with -ObjC and -all_load flags for linker), I get this error at runtime :
unrecognized selector sent to instance
This error occurs when I try to call a class method.
+ (MyObject *) GetSingleton;
For information, I don't get error when I call an instance method.
- (void) Log;
Have you got an idea of the problem ?
When you create your singleton, try this:
+ (MyObject *)GetSingleton {
static MyObject* singletonInstance;
#synchronized(self) {
if (!singletonInstance)
singletonInstance = [[MyObject alloc] init];
}
return singletonInstance;
}
Hope that helps.
Hum, I fixed the problem re-creating my project !
I don't know why, my project made bad linking for class method, and not for instance method.
Now, with new project and linkg to my static library, all is OK at runtime.
Maybe it was a problem because of multiples static libraries I built, with probably a bad cache or dependencies...
Thanks for your answers developers !

Resources