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.
Most workout trackers are demanding. They require you to enter a lot of information just to track your progress and many shame you if you do not work out regularly. Simplest Workout Tracker has another philosophy: If you’ve exercised, that’s great! If not, there’s always another day.
Book Scanner version 1.7.2 is finally completed and it’s the most awesome version of Book Scanner yet!
Book Scanner now works and looks good on all supported iOS devices and plays nicely with iOS 12.
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.
Thus, I’ve been pondering the difference between groups (folders) and tags, and when either should be used. Arno had an interesting take:
Think of the group structure in a DevonThink database as a catalog rather than as the place where your documents are stored
Use DevonThink’s groups to tag your documents by topic
Use DevonThink’s tags to flag documents for special purposes
Using groups to store documents by topic and tags to actualize them while working on projects is something I’ll try from now on.
A new year has dawned, bringing with it the possibility of being even more efficient. One of the things I did a lot last year, was entering books in Goodreads found in links from Amazon. I did this manually (ouch), searching for the book’s name in the Goodreads website or app.
Inspired by this thread, I created an iOS workflow which takes an Amazon URL from any source, extracts the Amazon ID and searches for the corresponding book on the Goodreads website or app (if installed).
Import this workflow into the Workflow app and use
Run Workflow from any app with an Amazon URL, Safari for example.
So you know that all software sucks, right? iOS 11 is the best mobile operating system in the world, but it too has bugs. Funny bugs. Like this:
Another day, another radar.
Apple did good and delivered my iPhone X on Friday November 3. and I’ve had an entire weekend to enjoy this technological marvel.
This is my trip report.
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.
macOS has an awesome firewall, however the default setting is very harsh for us iOS developers.
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.
Workday Countdown is a countdown panel for Panic's Status Board 2 application for iOS. Different from the stock Countdown panel, Workday Countdown filters out weekends and public holidays. This provides a more realistic countdown in a work setting where people are not expected to come in on weekends.
View the source on GitHub.
I'm writing my next game, Icarus - Escape from Crete, using Xamarin iOS together with SpriteKit. The combination works great and SpriteKit turns out to be a well thought out API. My only gripe so far is that I haven't found an existing way for tiling a sprite texture, that is fill the entire sprite using a smaller texture.
The grass below is just a small image, repeated to fill the entire green meadow.
The grass is created from this simple tile
using an extension method on
Using CoreGraphics, an image of the proper size is created and the texture is tiled. Next the image is rendered and a
SKTexture is created from the result.
Here's the example from Icarus:
This method has two disadvantages though.
- It's slow. Create the needed nodes during game loading, not during gameplay.
- The resulting image is flipped. Remedy this by either using a flipped image as the tile, or flip the Y-axis on the
SKSpriteNodeafter the texture is applied:
grass.YScale = -1f;I use the former.
Even with the disadvantages, the method was useful in Icarus. Maybe it's useful for you too 😃
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.
If the iOS Simulator scaling is set to 75% or 100% on a non-retina display, scale it to 50% before moving it to a retina display.
One of the biggest advantages of a Retina MacBook Pro is that the iOS Simulator can run at 100% resolution and you get a good feel for what your app will look like on the real device. Running the simulator on an external display, you often need to scale down the window to 75% or 50% in order to view the whole thing.
If the simulator scaling is set to 100% or 75% on a non-retina display, it will retain its seemingly large size when moved to the retina display.
Before moving the simulator to a retina display, set the scaling to 50%. The simulator will detect the retina display and set its scaling to 100%.
Exactly as we want.
The iOS Simulator only seems to auto scale if its scaling is set to 50% on a non-retina display.