An important concept in app development is the D in SOLID, the Dependency inversion principle. While using this technique together with the Interface segregation principle you end up with a lot of interfaces. And with cross-platform Xamarin apps, you’ll sometimes have different implementations on iOS and Android with some fake service implementations for testing too.
When creating iOS apps using Xamarin, another good practice is to enable
linking. Enabling linking will remove unused code before compilation and decreases the size of your app manyfold. There’s a difference between 80 and 20 MB, even in 2019.
Xamarin Forms has a built-in DependencyService to help manage the interfaces and their implementations, but I prefer the always excellent LightInject. And after adding LigthInject to my latest Xamarin Forms app and enabling linking, this error message appeared on startup:
VTable setup of type LightInject.ServiceContainer failed
One of my favorite professional activities is educating students on technical topics they’ve not yet encountered at the university.
Yesterday I gave a talk on cross-platform mobile development using C# and Xamarin for a group of students from NORD University in Bodø, Norway. The goal of the talk was to show how easy it is to create a cross-platform app using modern tools and give them a baseline from which they can create their own app.
Book Scanner version 1.7.2 was coded to perfection and ready for shipping. Or so I thought:
ERROR ITMS-90362: “Invalid Info.plist value. The value for the key ‘CFBundleExecutable’ in bundle BookScanneriOS.app/PlugIns/BookScanneriOSLatestBookExtension.appex is invalid. CFBundleExecutable must match the name of the bundle directory minus its extension.”
I’ve used Xamarin.UITest for both verifying the UI of my apps and automate screenshot taking for the App Store. This has worked, but with every iOS release, I’ve to tweak my tests to get them to run again.
This is what I had to do to get the default UITest template to run with Golden Ratio Calculator for iOS 12.
My previously awesome Book Scanner app, written using Xamarin, currently has an embarrassing error on iOS 12: the app will not prompt the user for camera permissions, thus rendering the app useless.
Luckily, the fix is easy. Just add the following to the
info.plist file and the user is prompted for permission when the app is run for the first time.
<key>NSCameraUsageDescription</key> <string>Used to scan book barcodes</string>
So I made the change and thought it only reasonable to test it on my own device first. Unfortunately, the output from the
Deploying to Device tab in Visual Studio crushed my dreams:
VerifyingApplication - PercentComplete: 40%
ApplicationVerificationFailed: Failed to verify code signature of /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.TCrsU1/extracted/BookScanneriOS.app : 0xe8008016 (The executable was signed with invalid entitlements.)
error MT1006: Could not install the application ‘/Users/sankra/projects/BookScanner/BookScanner.iOS/bin/iPhone/Release/BookScanneriOS.app’ on the device ‘iPhone XS’: Your code signing/provisioning profiles are not correctly configured. Probably you have an entitlement not supported by your current provisioning profile, or your device is not part of the current provisioning profile. Please check the iOS Device Log for details (error: 0xe8008016).
Application could not be uploaded to the device.
The app could not be uploaded to the device because of invalid entitlements. Strange, as the app has only a few entitlements and none that should be affected by the aforementioned small change.
Screenshots are an important aspect of App Store marketing. Not only do they promote the functionality and design of your app, but they can also reveal your attention to detail. Or lack thereof.
Many developers do not care how the battery, time and signal strengths are displayed in their screenshots. But I do.
I’m updating my Golden Ratio Calculator app to be ready for iPhone X.
The app is built using Xamarin Forms. After updating the packages and building the solution, I tried running it on my iPhone 7 with iOS 11. This error was the result:
Xamarin.iOS: Fatal error: failed to load the class 'ObjCRuntime.Runtime'
After getting zero hits on Google, I deleted the
obj folders and rebuilt the app.
Success, as if by magic.
The old adage from the IT Crowd still holds true.
I’m creating a new Xamarin Forms app using a PCL-project for shared code and an iOS project for the iOS specific details. After a short hiatus, I upgraded to Visual Studio for Mac version 7.0.1 for a nice morning of coding. No such luck, the iOS project would not build.
I updated to Xamarin Studio 6 this morning. A beautiful update with dark mode, full Roslyn support and prettier icons. And it prevented my Xamarin.iOS app from starting in the simulator.
After releasing a new version of Golden Ratio Calculator, I decided to compile my XAML code to increase performance. I followed this guide from Xamarin and triggered compilation of all XAML in the assembly by adding the following to my
Xamarin is awesome! They bring my favorite language, C#, to my favorite device, my iPhone. I use Xamarin in all my mobile apps and could not be happier.
Their growth these last couple of years has been amazing and they were the highlight of last years Build. Microsoft has focused on other companies and technologies this year, but Xamarin is one of the most important and innovating companies in the .Net ecosystem. They bring more value to peoples lives than ObjectiveC on Windows Phone ever could.Miguel: “This is web scale”. Bingo!
Everything you can do with C#, you can also do with F#. F# did not get a lot of love during this Build.Showing the C# slide.
The demo app is a chat client. That sounds familiar. DIRC didn’t have encryption though and automatic parent forwarding. Nor an Apple Watch app.The DIRC icon is missing DIRC is my goto Xamarin teaching app, used in the Norwegian education system.
Silicon Valley 101: Find larger market. Find a differentiator. Find product/market fit. Grow your market.
Miguel: “Parenting is kind of like Ruby on Rails”. Gamify driven parenting. Badges!Snuggle! Love to see Apple Watch apps in Visual Studio.
Use Xamarin Inspector to debug your UI on all platforms. It already supports C# 6. It’s like Apples playground, visual debugger and C# interactive all in once. The inspector supports visualizer for common things like images. Enables truly rapid UI prototyping or view hierarchy debugging. Available as a nuget package.The inspector knows of images. Where have I seen this before...
Xamarin Test Cloud is useful for Android developers for running UI tests across a range of real devices. iOS devices are also supported. The tests are written using Xamarin.UITest, adopted fron NUnit. The tests can be built using a live interacting REPL.Unexpected red tests are the best red tests. Android in all its glory.
Xamarin Insights is the Xamarin analytics solution. It supports all the usual stuff, exception reporting (both managed and native), optional user tracking and event tracking.Insights has gotten more useful.
I needed a way to get a color between two colors given a ratio while working on the 1.1 version of Golden Ratio Calculator. I use it to show a color between blue and gold, then gold and silver, and lastly between silver and blue.
The start and end colors are represented as arrays of RGB ratios, but this is easy to work with.
Either get the RGB-ratios from a UIColor:
Or create the array directly:
Version 1.6 of Book Scanner now supports 64bit and has an iOS 8 today widget extension. While submitting this version to the App Store, I was presented with this dialog.
Invalid Code Signing Entitlements. Your application bundle's signature contains code signing entitlements that are not supported on iOS.
I'm using the Unified Xamarin API and I was certain that all the entitlements were correct.
After a round of Googling', I've found post on the Xamarin Forums. It mentions that this error will be fixed in a newer version of Xamarin iOS. I was using version 5.5.4 of Xamarin Studio and 18.104.22.168 of Xamarin iOS.
UIAlertView has been deprecated by Apple from iOS8. From now on, UIAlertController is the way to go.
UIAlertController is surely an improvement, but given the asynchronous nature of displaying alerts to the user, I wanted to use the API together with async and await.
Below is a screenshot of what I wanted to accomplish:
A simple menu with two options and a Cancel-button.
By using a TaskCompletionSource, I can accomplish this using async and await.
TaskCompletionSource can be used to map an external asynchronous operation onto a normal C# Task. We can then use this task as we would any other.
In this case, the result of this task is the Enum
CustomerFeeling with values corresponding to the users happiness. Thus,
ShowRatingDialogAsync can be used like this:
The choice of the user can be awaited and
UIAlertController now fits in perfectly with the rest of the C# code.
I just submitted version 1.5 of Book Scanner to the App Store, but this time I needed two tries.
Book Scanner now fully supports iOS8 and the larger iPhones, and I've also update the app's icons. I use asset catalogs and had dutifully added icons in all the slots. Then I started uploading the app using Application Loader. After a while, this error message appeared:
ERROR ITMS-9000: "Invalid Image Path - No image found at the path referenced under key 'CFBundleIcons': 'AppIcons120x120'"
After a little trial and error, it turns out that the CarPlay icon was the culprit. I removed the CarPlay icon from the asset catalog and the upload completed successfully.
And I will update Book Scanner to 64bit soon...
FermiContainer gains features, but while doing so becomes even more simple. How is this possible? Let me tell you:
Automatic resolving of constructor arguments
Through constructor injection, the dependencies known to the container are automatically resolved. No attributes or XML configuration are needed.
Default container instance
Easier to extend
The Services dictionary is now protected so FermiContainer is easily extendable.
C# expressions makes FermiContainer very performant.
Available as source through NuGet
PM> Install-Package FermiContainer.Sources
What the world needs most is more IoC containers in the .Net space.
So I created FermiContianer, the simples IoC container imaginable.
It supports registering implementations of interface using either a default constructor or a factory method.
Resolve gives you a new instance each time.
Singleton will return the same instance.
PM> Install-Package FermiContainer
If FermiContainer ever becomes too simple for your needs, I recommend LightInject.
As of iOS 8 you can now use storyboards instead of images for your app's launch image. This is convenient, as you only need to create one storyboard instead of multiple launch images (one for each device form factor). This post by Ole Begemann outlines the procedure for a regular iOS app, I'll now show you how it's done using Xarmarin.iOS.
- Create an empty storyboard in Xamarin Studio and name it LaunchScreen.storyboard.
- Open Options for your Xamarin.iOS project and set the newly created storyboard as the launch image.
- Edit your storyboard using Xamarin iOS Designer or Xcode Interface Builder. The iOS Human Interface Guidelines specifies that:
Design a launch image that is identical to the first screen of the app, except for:  Text. …  UI elements that might change.
After you're satisfied with your design, remember to tick the Is Initial View Controller checkbox. Without it, your View Controller will not be loaded and you're stuck with a black only launch image.
Note that storyboard launch images do not work in the iOS Simulator at the moment, so be sure to test it on a real device.
After replacing your launch images with a storyboard, your app will appear in full size on all devices. This includes the iPad, even if you've created an iPhone only app. If your app is unusable on the iPad in this state, I would hold off until / if this bug is fixed.
Book Scanner will use a storyboard launch images from version 1.5, which is under development.
My new app Personal Trainer Worksheet - Time Tracking for Professional PTs is written using Xamarin.Forms and is currently available on the App Store. It's been a pleasure developing it using the Xamarin tools and I decided to release a iOS version first. However the App Store did not quite agree this time...
While submitting the App using Application Loader, it complained that the API usage info to be sent to Apple was too big, and that the analysis would continue on Apples servers. Okay, I thought and submitted anyway.
Moments later, this mail arrived in my inbox:
We have discovered one or more issues with your recent delivery for "Personal Trainer Worksheet - Time Tracking for Professional PTs". To process your delivery, the following issues must be corrected:
Non-public API usage:
The app references non-public selectors in PersonalTraineriOS: artwork, command, finished, initWithSendPort:receivePort:components:, isContainer, isNegative, playbackProgress, playbackRate, rating, removeTarget:, setArtwork:, setContainer:, setLocalizedTitle:, setPlayable:, setPlaybackProgress:
That was quite a mouthful.
Enable linking for SDK assemblies
The app doesn't use many third party dependencies, so I was quite certain the error was on my part.
The Monotouch linker can remove unused classes from your Xamarin iOS App, thus decreasing its size. The "too big" error message in Application Loader was actually a good hint that the linker had not run.
Sure enough, my project settings were set to
Don't link. After changing it to
Link SDK assemblies only, the API usage analysis ran successfully and the app was approved.
I don't know why the non-linked binary was rejected, but this thread on the Xamarin Forums shows that I'm not alone.
I'm utilizing Xamarin.Forms in my next app to more easily support both iOS, Android and Windows Phone using the (mostly) same code base. It's relatively new however, and some use cases are not yet supported using Xamarin's supplied controls.
My problem today was showing a TimePicker using a 24 hour time format, regardless of the users selected locale. The TimePicker normally respects the users preference, but I'm using the control to select a range of time, not a point in time.
TimePicker's Format property only affects the string showing the selected time, not the selection itself.
Forcing 24 hours on iOS
Since my next app will first be released on iOS (naturally), I tackled the problem there first. My solution was to create a custom renderer which forces the underlying UIDatePicker to always use a local with a 24 hour time format. In this case I chose Norwegian, but any 24h locale will do.The picture illustrates what I wanted to accomplish.
Here are a couple of Xamarin quick tips i have found useful the last couple of days.
iOS simulator refuses to scroll
If your iOS simulator refuses to scroll your ListView or TableView, try restarting it. The simulator sometimes locks up and disables scrolling for some reason. This has only happened during my Xamarin.Forms development, but I have no clue as of the source.
Open another instance of Xamarin Studio
To open another instance of Xamarin Studio on OS X, use the following command in the Terminal.app:
open -n "/Applications/Xamarin Studio.app"
To open another instance of Xamarin Studio on OS X, use the following command in the Terminal.app:
open -n "/Applications/Xamarin Studio.app"
Given that Xamarin Studio is in its default location. Sometimes Unix can be useful, who knew? 😬
Scan a book
Buy it if you want
View all scanned books
My new app Book Scanner, also known as Book Barcode Scanner is now available worldwide on the App Store.
Book Scanner scans ISBN-barcodes and finds the books on iBooks. The app remembers your scanned books and you can buy them on iBooks at your convenience. Scanning book barcodes is faster than a manual search and the it's very useful in bookstores and other places with a lot of books.
Book Scanner is available free on the App Store and is of course written in C# using the Xamarin stack. I've learned a lot while writing this app, and I will share some of it here on this blog.