TinyIoC, Xamarin.iOS, linker settings - ios

I'm trying to get TinyIoC working on Xamarin.iOS, but I'm not having a lot of luck. My project linker settings are set to "Link SDK assemblies only".
I'm literally doing something this simple:
public interface IPerson { int age { get; } }
public class Person : IPerson { public int age { get { return 99; } } }
Then my registration code looks like this (I've just placed it in my AppDelegate in a toy app):
TinyIoCContainer.Current.Register<IPerson,Person>.AsMultiInstance();
When I attempt to grab an IPerson, I get a runtime exception saying that IPerson cannot be resolved (this code is found immediately after the registration code in the AppDelegate of the toy app):
IPerson person = TinyIoCContainer.Current.Resolve<IPerson>();
Here's the error:
Unable to resolve type: TinyTest.IPerson
If, however, I change the linker settings to "Don't link", everything works fine. This is obviously untenable, though, because the binary becomes enormous.
I've tried placing [Preserve] attributes on the IPerson interface and the Person class, but no dice. I also tried just manually declaring a variable of type IPerson and instantiating it with a new Person() and then grabbing the age property, just to make sure the type was included in the build, but no luck there either.
Feel like I'm missing something here - can someone point me in the right direction?
Thank you!

This is a bug because reflection is used to call an internal Expression<TDelegate> constructor.
The linker cannot analyze reflection usage (it's beyond static analysis) so it must be aware of those special cases.
This is obviously untenable, though, because the binary becomes enormous.
Keep using the default Link SDK option but add the --linkskip=System.Core to your Additional mtouch arguments, inside your Project Options, iOS Build.
That way only System.Core (from the SDK) will not be linked and the increase in size will be much smaller. Of course this is only a workaround until a new version fix the issue properly.

Related

singleton in framework with error: initializer is inaccessible due to 'private' protection level

So, I made a framework in swift and at first I wanted to use a singleton class. I built it and put the .Framework file into a new project to test it. Than I got this error:
'getInstance' is inaccessible due to 'internal' protection level
. I tried looking for anyone with the same problem, but nothing I found worked. It might be because its a framework. After hours of meaningless searching, I gave up on the singleton and I got almost the same error with a normal class.
'mySDK' initializer is inaccessible due to 'private' protection level
I tried making the class public, the initializer public, but nothing seems to change. Anyone experienced any problem like this? I never worked on frameworks before, so maybe its the obj-c header that have to be modified. If you need any more information, please just ask.
Thank you all, in advance.
Edit:
This is the getInstance func. I wrote it only, because the mySDK.myInstance seemed to give the same error.
static let myInstance = mySDK()
public static func getInstance() -> mySDK {
return myInstance
}
I don't know what caused the error, but I managed to fix it by creating a new project, than copy pasting the code from the old to the new.
I found the source of the problem. If I turned off the build active architecture only option in the build settings of the framework, It gave me this error.
You can create a singleton class in a framework like this. Please make the public Class and public static getInstance function.
public class ClassName {
// Singleton instance
private static var instance : ClassName?
/********************* Singleton Instance ************************************/
public static func getInstance() -> ClassName {
if (instance != nil) {
return instance!
}
// Initialize instance.
instance = ClassName()
return instance!
}
}

Method ViewModel.Init receives null as parameters when linker "Link All" enabled in MvvmCross at iOS

I am facing such problem: In MvvmCross 4.4.0 on iOS project when I have changed linker mode from "Link Only SDKs" to "Link All", in the Init method of ViewModel I started to get null as a parameter of Init Method. Example below. (All other Init methods have same problem).
On PreviousViewModel:
public void RedirectToCountry()
{
/*_countryId != null */
ShowViewModel<NextViewModel>(new {countryId = _countryId});
}
On NextViewModel:
public void Init(string countryId)
{
/* countryId == null */
_countryId = countryId;
}
So, now I am looking what Method/Class/File/Namespace/Assembly do I need to save from Linker. Which component should I include?
P.S.: If someone now khow to save Prepare method from new versions of MvvmCross please answer too.
P.P.S.: I have researched that MvvmCross uses JsonSerializer for transferring data between ViewModels, tried to include assembly with serializer files (MvvmCross.Core.ViewModels) but it did not helped.
These are the assemblies I normally avoid from linking on iOS:
--linkskip=MvvmCross.Binding --linkskip=MvvmCross.Binding.iOS --linkskip=MvvmCross.Localization --linkskip=MvvmCross.Platform --linkskip=MvvmCross.Platform.iOS --linkskip=Newtonsoft.Json
You shouldn't have any MvvmCross issues when linking all assemblies after that.
So, including my iOS project helped to pass data between ViewModels.
For example:
--linkskip=GuestGuide.iOS
Also I did not included all MvvmCross assemblies excluding MvvmCross.Binding.
However it all is not understandable by me at all.

"NSClassFromString" is invalid in c99

My app worked well yesterday but always failed to build in the new day!I did nothing for code as well as Xcode settings and didn't update anything!But the error "implicit declaration of function 'NSClassFromString' is invalid in c99"displayed when built project.I have checked for some simulate issues in stack overflow but nothing works for me.If someone can help me ?
My code is as following:
- (UIView*)indexView {
Class indexViewClass = NSClassFromString(#"UITableViewIndex");
NSEnumerator* e = [self.subviews reverseObjectEnumerator];
for (UIView* child; child = [e nextObject]; ) {
if ([child isKindOfClass:indexViewClass]) {
return child;
}
}
return nil;
}
"Implicit declaration invalid" means the compiler doesn't see a prototype for this function. Double-click on the function name and "Show Definition", then make sure you include the right header file.
Much better to use [UITableViewIndex class].
BTW. If you say it compiled yesterday, you haven't changed anything, and it doesn't compile today, then someone else has made a change. Use your source code control system or your Time Machine backup to get a copy of yesterdays state and compare them. Diff tools for that are available for free.
Class indexViewClass, you have to confirm which type of class you want to assign to indexViewClass , must use a pointer variable.
for example : UIView *view = NSClassFromString(#"LoginView");
Object view is an instance of a LoginView class.

swift failed with exit code 1 while compiling in Xcode - possibly related to Bridging-Headers

I have an Obj-C Project I'm trying to migrate to Swift. I did succeed with various classes but recently ran into an issue I can't seem to make sense of. When I try to compile my current code base I get the following (SUPER UNHELPFUL ERROR MESSAGE)
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
My only assumption is its somehow related to my bridging-headers but Xcode isn't giving me enough information to figure out if this is actually true.
I'm using Cocoapods to add the CorePlot to my project. I'm trying to migrate the following class to Swift:
Obj-C Class (ScatterPlotContainer.h)
#import <Foundation/Foundation.h>
#class CPTScatterPlot;
#interface ScatterPlotContainer : NSObject
#property (nonatomic, strong) CPTScatterPlot *ahrsAlt;
#property (nonatomic, strong) CPTScatterPlot *calibration;
#property (nonatomic, strong) CPTScatterPlot *coreAlt;
#property (nonatomic, strong) CPTScatterPlot *pitch;
#property (nonatomic, strong) CPTScatterPlot *roll;
#property (nonatomic, strong) CPTScatterPlot *slip;
#end
Obj-c Class (ScatterPlotContainer.m)
#import <CorePlot/CPTScatterPlot.h>
#import "ScatterPlotContainer.h"
#implementation ScatterPlotContainer {
}
#end
Swift Conversion
import Foundation
class ScatterPlotContainer : NSObject {
public var ahrsAlt : CPTScatterPlot;
public var calibration : CPTScatterPlot;
public var coreAlt : CPTScatterPlot;
public var pitch : CPTScatterPlot;
public var roll : CPTScatterPlot;
public var slip : CPTScatterPlot;
}
My bridging headers file
#import <CorePlot/CPTScatterPlot.h>
What I've tried thus far
When I comment out the #import <CorePlot/CPTScatterPlot.h> from the Bridging headers file - I get an error in swift because it doesn't know what CPTScatterPlot is
I've also tried #import <CPTScatterPlot.h> which didn't work either.
Thoughts
So the only thing I can think of is perhaps because I'm using a cocoa pod there is some sort of module name I need to add. The error message really isn't that useful. Does anybody have a suggestion about some blaring error I've made or how to get a more descriptive error message to figure out what is going on?
I did the same all answer says but mine issue was not resolved. I did figured out that issue was related to broken function call.
A function syntax was not wrong but its calling mechanism was wrong.
To check the exact error for this issue check following:
Select issue navigator > Click on error will show logs for error > In that select All Messages tab.
This will show all detail logs for this error.
Scroll down and You got logs like, in my case
So, by reading this I figure out that something wrong with function calling. I browse my code and resolved it, Below was correct and wrong code.
Wrong Way:
var region = MKCoordinateRegionMake(self.mapView.userLocation.coordinate, span)
// It will not shown error here but when you build project compiler shows error.
Right Way:
let region = MKCoordinateRegion(center: self.mapView.userLocation.coordinate, span: span)
I run into this last night and nothing above was solving my problem.
I was about to do something very bad at my laptop when I saw, all by pure luck, that ONE (1) file was is text encoding set to UTF-16 ?!?! WTF??
This was the last file I was working on, and probably, one bad cut/paste "import" a strange character into the arena. I did a cut/paste of my code in this file to a bare bone text editor. I deleted the file, recreate it and paste back my code... and voilĂ ! it work.
So do the above, but also check your file encoding! :-)
I had the same error message.
What helped, was to set the optimization level in the swift compiler settings to None.
This is not really a solution for me and I think that's one of the many bugs in the swift compiler.
Another solution for this issues is to check that you don't have 2 or more files with the same file names. It solved the problem for me.
Thank you #Kampai for the advice on going through the error log message. I read through, and some files were missing:
<unknown>:0: error: no such file or directory:
Somehow, some files were removed during a pull from GitHub. The files are in the directory, but not in the Xcode project.
Right click on a folder and click 'Add files to ...' to manually add missing files to Xcode. That fixed the problem for me.
This happened to me several times already, but now I know how to fix it \o/
I was getting the same error for including this code in a didSet block:
didSet {
// Test whether this view is currently visible to the user.
if super.isViewLoaded() && (super.view.window != nil) {
// (build fails even if this block is empty)
}
}
It took a lot of trial/error to hunt this down. Removing super. allowed the build to proceed.
had a horrible time with this bug for over 3 hours by meticulously going from file to file and reverting the changes and seeing if that file had the issue in it. I tried the first answer but didn't give me any answers. Found the issue and it was because I had a non computed property named the same as a computed property of a subclass. I really hope the debugger becomes more robust with handling these sorts of cases in future updates :(
Simply deleting derived data and cleaning helped me
1) Identify the file there the problem is. You can copy and paste the compilation instruction to the console and the last screen will contain the error description. Note the pid number there the problem was identified. Then scroll up and find the pid and related instruction - there will be one file per pid, so you will find the file you have problem it.
2) Look through the file and check all you last changes. If you have git initialized you can use
git diff <file name>
As for #Kampal, I'm still struggling to figure out how much to specify in a function call. For instance, creating a UIColor object sometimes requires that UIColor be specified, and sometimes doesn't.
These both work:
playButton.backgroundColor = .darkGrayColor()
playButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
This yields the exit code 1 error on compilation, without any debugger warning. #time-sucking debug vortex
playButton.setTitleColor(.whiteColor(), forState: UIControlState.Normal)
So I have a new rule: when using a function that takes more than one parameter, be explicit.
Now back to playing swift: AVOID THE VORTEX
Since everyone else has been showing theirs, I'll show mine:
class Foo : UIView {
var pathPosition:Double = 0.0 { didSet {
pathPosition = min(max(0.0, pathPosition), 1.0) // crashes if this line is present
self.pathPosition = min(max(0.0, pathPosition), 1.0) // but not here
}}
}
Incredibly, this does not come up in Playground, but does fail when placed in code in a framework. Although it is legal syntax (used to work, still works in playground), the Swift compiler seems to want pathPosition to be qualified with self.. Note that is (relatively) old code and used to compile, maybe something broke in 6.1.
Edit:
I feel like I am going insane, but it feels like there is a greater complexity problem going on here, where surrounding code can impact this problem. I saw things compile last night, changed some code and settings again today, and it failed on me again. Today, I had to hack in a bunch of really stupid code to get it to work:
var pathPosition:Double = 0.0 { didSet {
// bug: insane!! - have to clobber the value before resetting!
let bugOldValue = pathPosition
self.pathPosition = 1.0 // fails without this nonsensical line!
self.pathPosition = min(max(0.0, bugOldValue), 1.0)
}}
For what it's worth, the actual error message I got, per the helpful instructions above, was:
PHI node has multiple entries for the same basic block with different incoming values!
%14 = phi double [ 1.000000e+00, %10 ], [ %11, %10 ], [ 1.000000e+00, %9 ], [ 0.000000e+00, %9 ], !dbg !4818
label %10
double 1.000000e+00
%11 = phi double [ %7, %entry ], !dbg !4815
LLVM ERROR: Broken function found, compilation aborted!
I'm scared for tomorrow.
I just had this same error, the problem was that I had overridden a method with a non-optional parameter and had made the parameter optional in the override. (the method parameter below)
func logNetworkCallDurationForMethod(method:String, path:String, milliseconds: UInt) {
}
override func logNetworkCallDurationForMethod(method:String?, path:String, milliseconds: UInt) {
}
Ran into this issue today actually. Was the result of a recent pull from git on a project where a file had been deleted, but it didn't update in my local project.
Clicking on the error brought up the location of the "missing" file, went and deleted it's reference in the Project Navigator. Fixed the error, did a clean, and compiled successfully.
This happened to me when trying to reference a method from an inmutable protocol argument(by mistake, I thought the member was a property):
Having an interface as follows:
public protocol NSValidatedUserInterfaceItem {
func tag() -> Int
}
Compilation crash
func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
print(anItem.tag) // oopsie, tag is a function
return false
}
Compilation success
func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
print(anItem.tag()) // this is cool for swift
return false
}
This happened to me and after reading the log in issue navigator I found out that I have two swift files with same name. This was creating the issue and I was getting build failed.
I got this error due to a missing file in my project. Added this file again and voila everything worked.
In my case it was wrong method overriding. Base class:
open func send(_ onSuccess: #escaping ((SomeType) -> Void)) -> SomeType { }
Subclass:
open override func send(_ onSuccess: ((SomeType) -> Void)) -> SomeType { }
As you see #escaping is missing. Swift3 converter in XCode8 doesn't consider inheritance relations, moreover, that type mistakes aren't marked as errors.
In My Case it was Simulator bug just uninstall app from simulator and clean project then run project.
I had accidentally dragged symlinks (aliases) to source files into the project instead of the actual files.
I had CoreData generated files twice (and added myself). Check the files are not duplicate.
Unfortunately this error is often caused by a glitch inside Swift's compiler. It is not always easy to find the reason. If cleaning doesn't work, my suggestion is to try to comment the last code you wrote (even the whole file if necessary). Usually commenting the last code you entered would restore the compilation and you'll get more meaningful errors. From there on you have to try to uncomment the code piece by piece until you get to the instruction which caused this error. The Swift compiler is still pretty young and from time to time it reports weird errors. These kind of errors are completely useless, because instead of helping the developers they only confuse them even more. I would suggest Apple to change the compiler to give more detailed information and avoid this annoying error from appearing anymore.
NSString const *kGreenColor = #"#00C34E";
I had above line in my Constant.h file. which was meant for preprocessors only.
Removing that line worked for me.
moving the Bridge file to project level resolve my problem.
In my case I had renamed a file. After committing I found that the file name still hasn't changed in the Xcode project (not sure why), the file was greyed out. Changing the name and committing again did the trick.
So we have to keep an eye out for this error, when making changes to files using source control.
In my case deleted a couple of files directly from SourceTree but their reference was still there in Xcode. Logs show their names. Removed them and error went away.

System.ExecutionEngineException: Attempting to JIT compile method only in Debug Mode on device (MonoTouch)

I have the following method:
ApiResponse<T> PostMultipart<T>(string uploadUrl, NameValueCollection formParamters, params UploadFile[] uploadFiles);
UploadFile is just a Poco:
public class UploadFile
{
public string FilePath { get; set; }
public string ContentType { get; set; }
public string ParameterName { get; set; }
}
By calling that method, everyhing works fine on the simulator with "Debug|iPhoneSimulator" and on my iPod Touch with iOS 5.1.1 with "Release|iPhone".
But when I am starting to debug the app on the device ("Debug|iPhone"), I get the following exception:
System.ExecutionEngineException: Attempting to JIT compile method 'Xyz.Api.ApiClient:PostMultipart (string,System.Collections.Specialized.NameValueCollection,Xyz.Api.UploadFile[])' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.
I can't see any relevant information on the linked page. And I can't really understand why that behaviour only occurs when debugging on the phone.
Is someone else able to understand what is going on here? :)
Your code sample is not complete enough (to duplicate) but this is most likely because your <T> is a value-type (e.g. int, enum...).
The AOT compiler has difficulties generating code for value-types where code cannot be shared (like it can for any reference type). Workaround includes:
hinting the AOT compiler of what you need (ensuring <T> is known and code is generated for the value types you're using);
using a reference type (e.g. a string) instead of a value type (e.g. an int)
And I can't really understand why that behaviour only occurs when debugging on the phone.
iOS devices do not allow JITting code (Apple's restriction) so AOT is used. The iOS simulator does not have this restriction, so the JIT is used (because it's a lot faster than AOTing code).

Resources