Xamarin iOS binding, symbol not found in library - xamarin

I needed a sketch/painting control for my Xamarin.iOS project, and while I couldn't seem to find one compatible with C# I did find a good component available written in Objective C. https://github.com/acerbetti/ACEDrawingView
I've done Xamarin bindings before, so I had hoped that the process would be fairly simple, but unfortunately I've hit a few roadblocks along the way.
I started off creating my static library and used an ant build script to make a FAT binary to cover devices and the simulator:
snippet of my ant script
AceDrawingViewSDK.a: libAceDrawingView-i386.a libAceDrawingView-armv7.a libAceDrawingView-armv7s.a libAceDrawingView-arm64.a xcrun -sdk iphoneos lipo -create -output $# $^
Next, I ran
sharpie bind --sdk=iphoneos10.1 *.h
on the header files to get my ApiDefinitions and Structs and Enum files.
I checked and removed a the Verify attributes. (They all looked fine.) But this is where some of my other issues started.
The type ACEDrawingLabelViewTransform' already contains a definition forTransform' (CS0102) (AceDrawingViewBinding).
For the sake of just trying to move on and get something working, I just commented out this reference.
I then got multiple problems similar to this:
The type or namespace name `IACEDrawingTool' could not be found. Are you missing an assembly reference? (CS0246) (AceDrawingViewBinding)
I figured it related to this:
// #interface ACEDrawingPenTool : UIBezierPath
[BaseType(typeof(UIBezierPath))]
interface ACEDrawingPenTool : IACEDrawingTool
and this:
// #protocol ACEDrawingTool
[Protocol, Model]
[BaseType(typeof(NSObject))]
interface ACEDrawingTool
I tried to fix this my making the interface name consistent (I tried both IACEDrawingTool and ACEDrawingTool.) Doing this got past this error and allowed me to compile
One of my enums came out as
[Native]
public enum ACEDrawingMode : nuint
{
Scale,
OriginalSize
}
I couldn't find how to handle [Native] in this case (so once again, for testing sake I removed it.) I tried using removing the nuint from the enum and using uint. Either approach seemed to fix the error.
So with those errors fixed I was able to generate the .dll from my binding project and add it to my main project.
Now, I am getting 2 more issues.
If I build and deploy to the simulator I am able to run my app up until the point that I try to create a new instance of the ACEDrawingView from the binding. I get:
Could not create an native instance of the type 'ACEDrawingView': the native class hasn't been loaded.
It is possible to ignore this condition by setting ObjCRuntime.Class.ThrowOnInitFailure to false.
If I try to build and deploy to my phone I get different errors in the build phase which prevents it from launching on the device at all:
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingArrowTool. The symbol 'OBJC_CLASS$ACEDrawingArrowTool' could not be found in any of the libraries or frameworks linked with your application.
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingDraggableTextTool. The symbol '_OBJC_CLASS$ACEDrawingDraggableTextTool' could not be found in any of the libraries or frameworks linked with your application.
MTOUCH: error MT5211: Native linking failed, undefined Objective-C class: ACEDrawingEllipseTool. The symbol '_OBJC_CLASS$_ACEDrawingEllipseTool' could not be found in any of the libraries or frameworks linked with your application.
...and so on.
I've tried going back, rereading and redoing steps and have tried to reuse some of the scripts and settings from my previous successful bindings with no luck.
Does anyone have suggestions for what might fix these issues?

The type or namespace name `IACEDrawingTool' could not be found.
Add a new interface, like this interface IACEDrawingTool{ }
public enum ACEDrawingMode : nuint
Change the nuint to ulong

Related

iOS project doesn't reference a static library from Binding project when in Release mode

I've got a static library, which was used to generate the wrapping code by Sharpie. The library was Built after that (including, generated *.dll) successfully.
AppDefinition.cs contains the namespace and the mappings, like this:
namespace TheNamespace
{
// #interface TheParameters : NSObject
[BaseType(typeof(NSObject))]
interface TheParameters
{
The library itself built in Release mode with LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Arm64.
However, when referencing this binding project from my iOS project, it works only in Debug mode.
When I change it to Release, the namespace (and all the related clasees) not available. Also, when exploring the binding library reference in Object Browser, it doesn't display any elements: it's totally empty.
Just to point that: it gets available when changing it in the dropdown to Debug and disappears on Release, what's interesting, undependently on what actually project is selected in Current Project dropdown!
What might be the issue? Thanks!
I think the problem should come from when building static library .When generating static library , there is a build type of release/debug to select.
Above screenshot shows static library types after building , there are three types (Two is Debug and One is Release ). You can see that tt distinguishes between release and debug .
After some Googling I found the solution.
The issue happens because of Visual Studio bug, I guess. And also referred here. (And it's weird it's not mentioned in Xamarin docs on Microsoft website.
To resolve the issue the Binding Project(s) must not reside in the same solution with the main project. Just remove them and attach the library as regular reference.

No type or protocol named 'UIApplicationDelegate'

Just added a WatchKit target to an existing Xcode project. Boom! 13 errors without typing a single new line of code. The first error listed is "No type or protocol named 'UIApplicationDelegate'".
I was able to create a fresh project and add the WatchKit target without any problems. That makes me think I need to adjust my existing project in some way.
Xcode 8 Beta is fairly new obviously but has anyone had this issue and overcome it?
Tried a couple things like explicitly importing UIApplication and even adding "-fgnu-inline-asm" to the Other C Flags build setting.
If I remove just the one target that gets added (not the extension one) and leave the new classes that were produced, the errors go away.
For enquiring minds, the error I mentioned was in the AppDelegate. Almost all of the other errors were of the "Unknown type" variety. Seems like the compiler loses its mind about where some basic classes like UIView, UIWindow, etc., are.
I encountered this error as well after adding a shared class that was shared between the iOS target and the Watch Extension target. In the shared class I was importing the AppDelegate.h file, so the watch extension target was trying to compile it. Removing the import solved the issue for me.

unable to print object ('po') in xcode6 beta 6 osx swift project: (Error in auto-import: failed to get module '__ObjC' from AST context)

An attempt to print object (po command) in xcode 6 beta 6 OSX Swift project results in this error message:
(lldb) po managedObject
error: Error in auto-import:
failed to get module '__ObjC' from AST context
In this case the object in question is an instance of NSManagedObject.
Any advice on how to help auto-import in getting __ObjC module into LLVM Abstract Syntax Tree context?
As of Xcode 6.1 if you attempt the po command twice it will work on the second attempt. The first po command will always fail for each new debugging session but subsequent calls work.
Have same issue in xcode 7.3.1:
error: Error in auto-import:
failed to get module 'Touch' from AST context:
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/tree.h"
^
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/tree.h:17:10: error: 'libxml/xmlversion.h' file not found
#include <libxml/xmlversion.h>
^
could not build Objective-C module 'LibXML2'
But you can use fr v managedObject instead of po managedObject.
I'd recommend double-checking that you have the
-D DEBUG
flag set under 'Other Swift Flags' for the scheme that you're using to debug. I experienced similar issues when I'd accidentally deleted it.
A clean of my project and deleting DerivedData worked for me.
I discussed a similar error message with an Apple engineer at WWDC2017. It seems like this issue can have many causes, and I am aware that mine is slightly different than the one described above.
My team spent weeks trying to figure this out, and it ended up being a bug on Apple's compiler, which we could never have figured out by ourselves. Also, it has a VERY easy workaround.
So, this is just me posting the fix here, in order to maximize the probability that someone else does a search for this confusing error message, and finds this answer.
So, here it is. In our case, we had an Objective-C project using a mix of Swift and Objective-C frameworks. This fix might apply in slightly different contexts, just try it.
There happens to be a bug with the way the compiling flags get aggregated from the frameworks and the project, and the "pure Objective-C" project "activates" it.
Solution: add one single, empty Swift file ("Whatever.swift", or whatever) in your Objective-C project, making it not-pure-objective-c any more (new->file->Swift file, don't create the bridging header. The file will only contain the import of Foundation).

How to build an objective c framework with optional dependencies

I'm developing an iOS object serialization framework. The framework is capable of serializing objects of classes from various other frameworks (e.g. CLLocation from CoreLocation), so I've imported those frameworks in order to compile my code.
However, I don't want to require my clients to have to edit their XCode projects to "Link Binary With Libraries" for each of the frameworks that my framework serializes. Instead, I'd like the client to be able to exclude the frameworks he doesn't use (e.g. CoreLocation) from his project and still be able to build his project with my serialization framework.
I've configured the project for my framework such that CoreLocation is Optional, but the client still gets linker errors ("Undefined symbols for architecture i386:").
What am I missing? Are there alternative ways to achieve my desired behavior?
I'm still not sure why it wasn't working, but I found a workaround for the location errors, so I thought I'd share that.
The 2 errors were:
(null): "_CLLocationCoordinate2DMake", referenced from:
...
(null): "_OBJC_CLASS_$_CLLocation", referenced from:
...
(null): Symbol(s) not found for architecture i386
By selectively commenting out lines of code from my file, I found the 2 main causes were
Invocations of CLLocationCoordinate2DMake
Invocations of CLLocation class methods
To fix #1, I just built the struct manually.
To fix #2, I abstracted all CLLocation class methods to use NSClassFromString. For example:
[CLLocation class]
becomes
[NSClassFromString(#"CLLocation") class]
The fix for #2 seems hacky, but just wrapping the original code with a conditional did not seem to fix the issue. Interestingly, I can still reference the CLLocation type like so:
CLLocation *loc = ((CLLocation *)obj);
I just can't seem to invoke any class methods without first using NSClassFromString.
Any insight to why I'm seeing this behavior would be appreciated, but for now, I can move on.

category in static library confused

unrecognized selector when using category in static library.
I searched in google and found this?
http://www.dribin.org/dave/blog/archives/2006/03/13/static_objc_lib/
but I am still confused:
1、If I have object.h/.m and object+category.h/.m, and #import "object+category.h" in object.m, I add these to my project as source code, it works fine(no unrecognized selector error). But if I complie these to a static library and add to my project, crash with unrecognized selector.
So what's the different between these two ways? Why first way can find the selector and second way cannot?
2、The article says "As an optimization, the linker only chooses the object files that are required to resolve symbols." Same with static library and source code? Means If I have object.h/.m and object+category.h/.m as source code in my project and object+category.h/.m is never used. Will all those compiled .o files link to final .app?
3、How does the xcode linker know object+category.o is required and link it to .app if symbol is just created for each class, not each method? And when the link happen for object+category.o, compile time or runtime?

Resources