Xamarin Forms - use iOS native library - xamarin

I have mobile applicaction using Xamarin Forms. I have also library something.framework written in Objective-C and sample project in XCode.
I need to use this library in cross-platform application. I have added native reference to this library at Xamarin.iOS project. I use dependency interface to manage button's action from Xamarin Forms into Xamarin-iOS. The thing is that Visual Studio is not connecting native reference to library with my code in class. Using directive is not accessing native library so I have many errors when I try to use methods form library. I have already read Microsoft's instructions about binding native libraries but not answers came.
How to solve this?
Here are logs from terminal when I have used Objective Sharpie:
Johns-Mac-mini:~ johnmiller$ sharpie bind
-output=InfColorPickerCustom -namespace=InfColorPickerCustom ~/Desktop/InfColorPicker/InfColorPicker/*.h -sdk=iphoneos12.1 Parsing 8 header files... In file included from /var/folders/_g/mb3qv73j16d_mdwzb8bf5hww0000gn/T/tmp765fc04f.h:2: /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorIndicatorView.h:19:1: warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute] #property (nonatomic) UIColor* color; ^ /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorIndicatorView.h:19:1: warning: default property attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute] In file included from /var/folders/_g/mb3qv73j16d_mdwzb8bf5hww0000gn/T/tmp765fc04f.h:3: In file included from /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorPicker.h:60: /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute] #property (nonatomic) UIColor* sourceColor; ^ /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: default property attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute] /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute] #property (nonatomic) UIColor* resultColor; ^ /Users/johnmiller/Desktop/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: default property attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
Binding... [write] ApiDefinitions.cs [write] StructsAndEnums.cs
Binding Analysis: Automated binding is complete, but there are a few APIs which have been flagged with [Verify] attributes. While the entire binding should be audited for best API design practices, look more closely at APIs with the following Verify attribute hints:
ConstantsInterfaceAssociation (200 instances):
There's no foolproof way to determine with which Objective-C interface an extern variable declaration may be associated. Instances of these are bound as [Field] properties in a partial interface into a nearby concrete interface to produce a more intuitive API,
possibly eliminating the 'Constants' interface altogether.
MethodToProperty (193 instances):
An Objective-C method was bound as a C# property due to convention such as taking no parameters and returning a value (non-void return). Often methods like these should be bound as properties to surface a nicer API, but sometimes false-positives can occur and
the binding should actually be a method.
StronglyTypedNSArray (42 instances):
A native NSArray* was bound as NSObject[]. It might be possible to more strongly type the array in the binding based on expectations set through API documentation (e.g. comments in the header file) or by examining the array contents through testing. For example,
an NSArray* containing only NSNumber* instances can be bound as NSNumber[] instead of NSObject[].
PlatformInvoke (3256 instances):
In general P/Invoke bindings are not as correct or complete as Objective-C bindings (at least currently). You may need to fix up the library name (it defaults to '__Internal') and return/parameter types manually to conform to C calling conventionsfor the target
platform. You may find you don't even want to expose the C API in your binding, but if you do, you'll probably also want to relocate the definition to a more appropriate class and expose a stronger type-safe wrapper. For P/Invoke guidance, see http://www.mono-
project.com/docs/advanced/pinvoke/.
InferredFromMemberPrefix (29 instances):
The name of this originally anonymous declaration was taken from a common prefix of its members.
Once you have verified a Verify attribute, you should remove it from the binding source code. The presence of Verify attributes intentionally cause build failures.
For more information about the Verify attribute hints above, consult the Objective Sharpie documentation by running 'sharpie docs' or visiting the following URL:
http://xmn.io/sharpie-docs 6 warnings generated.
Done. Johns-Mac-mini:~ johnmiller$

I have solved it. There was a need to use scope when using Objective Sharpie. Simple add "-scope ~/Desktop/InfColorPicker/InfColorPicker". Then Sharpie is generating small files.

Related

Sharpie binding objective-c #protocols issue

I'm using sharpie bind command to get API interfaces for my iOS library for xamarin
sharpie bind --namespace=XXX --sdk=iphoneos9.2 Headers/*.h
Have issues with #protocol bindings:
The type or namespace name `IProfileDelegate' could not be found. Are you missing an assembly reference?
This is how it's generated:
interface XLibrary : IProfileDelegate
{
[Wrap ("WeakProfileDelegate")]
[NullAllowed]
MB_ProfileDelegate ProfileDelegate { get; set; }
I understand that it creates empty ProfileDelegate then compiler or something fills it with methods BUT my issue is that IProfileDelegate not found.
#protocol ProfileDelegate <NSObject>
#required
- (void)GetProfileFinished:(NSString*)_data;
- (void)SetProfileFinished:(NSString*)_data;
#end
Difference here in I symbol (which is reserved for #protocols I guess).
How to make sharpie generate proper api definitions?
I'm able to remove all I prefixes and it compiles successfully but I'd rather fix it not to repeat this every time I need to update source library.
Thanks
Remember that all the obj-c protocol act as a interface or abstract class i recommend to put "protocol, model and set base type as nsobject, another thing all the methods or properties maked as a "required" you need to specify it as Abstract
[Protocol, Model]
[BaseType (typeof(NSObject))]
interface myAwesomeDelegate
{
[Abstract]
[Export(...)]
void myRequiredMethod(uint param1)
[Export(...)]
void anotherMethod()
}
hope this will help you to fix your issue
According to the Objective Sharpie documentation:
In some cases these generated files might be all you need, however more often the developer will need to manually modify these generated files to fix any issues that could not be automatically handled by the tool (such as those flagged with a Verify attribute).
This means you will sometimes have to adjust the two generated files, ApiDefinitions.cs and StructsAndEnums.cs to fix issues, such as the one in this case.
You can read more about how bindings work for Objective-C protocols, which are similar to C# Interfaces, but not quite in the binding documentation.

What features does mogenerator provide?

I've been using mogenerator for a while now, and while there is a reasonable Getting Started Guide and a Stack Exchange article on the command line options, I haven't found a good guide for all of the functionality it provides.
In short: what, above and beyond the classes that Core Data provides for you, what does mogenerator actually generate?
(Frankly, I kept finding little pleasant surprises in the headers/implementations that I didn't realize were in there and I decided to step through the mogenerator templates and code and document what I found in a Stack Exchange Q&A. I'd love to see additional answers and edits, however. )
In addition to its core feature of a two class system, mogenerator helps you by automatically implementing a number of best practices regarding Core Data in your machine header and implementation files.
Property Accessors
Methods to access the attributes of your Entities are the core of what mogenerator generates. But there are some nice features implemented in the accessors above and beyond what the out of the box Xcode class generator provides to you.
Scalar Accessors
Xcode's built in generator gives you the option of "use scalar properties for primitive data types". This option gives you choice of having Xcode create properties with NSTimeIntervals instead of NSDates for date types, BOOLs instead of NSNumbers for boolean types, and int16_t (or similar) rather than NSNumbers.
I find this infuriating because most of the time I prefer the primitive types, but not for NSDates which are much more useful than a NSTimeInterval. So Core Data is giving me the choice of objects, in which case I will be constantly unboxing stuff and making stupid mistakes like if(myBooleanAttribute) (which is always YES because myBooleanAttribute is a NSNumber, not a BOOL). Or I can have scalars, but in that case, I get NSTimeIntervals that I'll always have to convert to NSDates. Or I can hand edit all of the generated files by hand to give me my desired mix of NSDates and BOOLs.
On the other hand, mogenerator provides you with both options. For example, you will get both a myBooleanAttribute getter that gives you an NSNumber (for easy storage in an NSArray) and a myBooleanAttributeValue getter that gives you an actual BOOL. Same with integers and floats. (Mogenerator does not generate NSTimeInterval accessors: only NSDates.)
Typed Transformable Properties
If you have a transformable property, you can set a specific UserInfo key ( attributeValueClassName ) in the attribute that will specify the class that your property will return/accept. (And it will properly forward declare the class etc.) The only place I found this documented was on Verious.
In contrast, the Xcode code generator will only type these transformable attributes as id types.
Validation Declaration
While mogenerator does not automatically generate any validation methods, it does include the proper signature as a comment in the machine h file. The seems to largely be for historical reasons, but it does mean that it is easy to copy and paste the signature if you decide to implement it in your human file implementation. (I wouldn't actually uncomment the declaration as you aren't supposed to call validation directly.)
Primitive Accessors
Core Data already provides you these accessors to the primitive values, but for some reason doesn't include them in its Xcode generated headers. Having mogenerator include them in its header files makes it much easier to access a primitive value.
Fetched Properties
mogenerator will generate accessors for fetched properties. As far as I can tell there is no way to have the Xcode generator do this.
Helper methods
Automatic NSFetchedResultsController generation
If you have a to many relationship in your Entity and you pass --template-var frc=true into mogenerator, mogenerator will automatically generate a method to create a fetch request for the child objects associated with a parent object. It even automatically generates a unique cache name, and isolates everything inside an #if TARGET_OS_IPHONE preprocessor macro.
Even if this doesn't fit your particular needs, it is a great example of how the templates can be extended.
+fetchMyFetchRequest:moc_
If you like defining your fetch requests in the model, this is a lot better way to retrieve them than hardcoded strings.
-MyEntitySet
Mogenerator uses the magic of KVC to give you a NSMutableSet proxy into your relationships.
+entityName
Need to provide a entity name to a NSFetchRequest or other Core Data method? It's easy to avoid hard coded strings by using this simple method that returns the name of the entity as an NSString.
+insertInManagedObjectContext: and entityInManagedObjectContext:
Another way to avoid hardcoding entity names is to use these helper methods.
Typed object ids
Each of your headers and implementations also includes a MyEntityID class. They are empty interfaces and implementations that merely subclass the NSManagedObjectID class. Also, each model class has a helper method called objectID that overrides the standard objectID method in NSManagedObject. The helper method does nothing but cast the superclass's return value to the MyEntityID type.
The net result: the compiler can catch your mistakes if you ever accidentally interchange your object ids from different entities.
Miscellaneous
Subclassing a Custom Superclass
One of the command line options is --base-class: which allows you to specify a base class that all of your generated classes will inherit from. This is very useful, either so that you can have a base class where you define convenience methods (which, given Core Data, you probably should) or so you can use an off the shelf Core Data toolkit like SSDataKit (or both).
includem
A simple little thing, but if you specify a --includem argument, mogenerator will generate a header file that includes all of your model header files. Convenient if you want to include all of your headers in a PCH, or something some other standard header you include.
Const Definitions of All Attributes, Relationships, Fetched Properties
An extern declaration of a struct is included in the header that has an NSString defined for every attribute and relationship defined in your Entity. This allows you to define predicates and other parameters, without baking the names of your entities into your strings. For example,
req.predicate = [NSPredicate predicateWithFormat:
#"(%K == YES) AND (%K <= %#)",MyObject.favorite, MyObject.availableDate, [NSDate date]];
(This type of struct used for "namespaced" constants is described My Mike Ash on his blog
const Definitions of User Info Keys/Values
Similarly an extern declaration of a struct is defined in the header that includes the keys as members of the struct, and the values as a values. i.e.
NSLog(#"User info for key my key is %#",MyObjectInfo.mykey) //will log "myvalue"
Alternate Templates
One of the interesting things about mogenerator is that in building mogenerator its author (Wolf Rentzsch) has basically built a generic parser and templating engine for the xcdatamodel files produced by Xcode. So you don't need to use the mogenerator templates. You can provide your own with a simple command line argument. There are lots of user contributed templates on the GitHub site.
In fact, you don't even have to use Core Data. Many of the contributed templates allow you to generate a series of ordinary NSObject model classes based on the data model. (So called PONSOs: "plain old nsobjects"). Want to use the data modeler in Xcode, but some other persistence mechanism? mogenerator can help you there.
You don't even need to generate objects at all: another interesting submitted template just provides a diff of two different model versions.

GetExportedTypes() on an assembly throws NotSupportedException

I'm having some serious troubles getting a Windows Phone 7.5 class library to load into the WP Unit Test Framework. It internally calls GetExportedTypes() on my assembly which throws a ReflectionTypeLoadException that doesn't contain any details. Its message is "ReflectionTypeLoadException" and its LoaderExceptions is null ("Could not evaluate expression"). The assembly is not using any 3rd party assemblies. If I create a separate WP7 app and do the same thing, I get the same results. I'm a very experienced Reflection user, but the lack of any detailed errors has brought my research to a complete halt. Just for completeness, it's the Windows Phone version of Fluent Assertions.
What about the Types array on the exception? Does it contain values? If so, does it also contain nulls? If so, you can find out which classes failed to load: You know all classes in the assembly and you know which classes loaded correctly. Those that are missing are the classes that couldn't be loaded. Maybe this info gives some clues.
This answer is based on the documentation, especially these bits:
From the Remarks of the LoaderExceptions property:
The LoaderExceptions property retrieves an array of type Exception that is parallel to the Types array. This array will contain null values whenever reflection cannot load a class.
And from the documentation of the Types property:
An array of type Type containing the classes that were defined in the module and loaded. This array can contain some null values.
I've found it! #GeertvanHorrik pointed me at a blog post he recently wrote. I was using an covariant interface (using the out parameter) which the runtime (!) doesn't support. Why the compiler does not protect me from that is a big mystery (and a huge disappointment) to me

Using a system supplied NSValueTransformer on a transformable Core Data attribute

When trying to use a system supplied NSValueTransformer in Core Data I get the following warning:
Warning: no NSValueTransformer with class name 'NSKeyedUnarchiveFromDataTransformerName' was found for attribute 'someAttribute' on entity 'SomeEntity'
How come the NSKeyedUnarchiveFromDataTransformer is not recognized?
Turns out that the actual string that the NSKeyedUnarchiveFromDataTransformer points too for this transformer is NSKeyedUnarchiveFromData. But even more importantly: if you specify this, the transformer will be used in the wrong direction. Leave the transformer name field empty to use NSKeyedUnarchiveFromDataTransformer correctly.

Scalar type in Managed Object only works for IPhone 5

Property 'Latitude' is a scalar type on class 'LatitudeLongitude'. Cannot generate a setter method for it.
When I generated codes for my managed object, I got a message whether I want scalar properties for primitive data type. should I use it? I want to make this application compatible with iPhone 3 - 5
is there any issues with this problem?
When you use scalar properties you have to provide implementations of getters and setters for those properties by yourself, as described in documentation:
"You can declare properties as scalar values, but for scalar values Core Data cannot dynamically generate accessor methods—you must provide your own implementations (see “Managed Object Accessor Methods”). Core Data automatically synthesizes the primitive accessor methods (primitiveLength and setPrimitiveLength:), but you need to declare them to suppress compiler warnings."
Documentation
At this place I would recommend you to check this post core-data-scalars.
I hope I have helped.
This is not true, scalars have been supported in Core Data out of the box for a long time. You do not have to implement custom accessors as many blog posts out there indicate.

Resources