Xamarin.Forms で開発していたところ、iOS10 で色々と動かない不具合があることが分かってきました。
QRコードをスキャン・生成できるツールである ZXing でも iOS10 で動作させるとスキャン画面でクラッシュしました。エラー内容は SIGSEGV です。SIGSEGV とは不正なメモリへのアクセス違反という内容らしいですが、対応方法が分かりづらかったので、今回はその対応方法について、ご紹介致します。
修正方法は以下のように2行変更するだけです。
ですが、コンパイルが通るようにするのがかなり大変なので、解説していきます。

前提条件
・Windows10
・Visual Studio 2015 Community Update3
・Xamarin 4.2.0.703 (NuGet Xamarin.Forms 2.3.2.127)
・macOS Sierra 10.12 / Xcode8 / Xamarin.iOS 10.0.1.8
・Zxing NuGetパッケージ 2.1.47
手順1.ZXing の NuGet パッケージを削除します。
NuGet パッケージで取得している以下の2つのパッケージをアンインストールします。
ZXing.Mobile
ZXing.Net.Mobile.Forms
手順2.ZXing のソースコードを GitHub からダウンロードします。
以下のサイトから ZXing.Net.Mobile-master.zip をダウンロードします。
https://github.com/Redth/ZXing.Net.Mobile
ダウンロードしたファイルを解凍し、以下のフォルダーを開発しているアプリのソリューションにコピーします。
\Source\ZXing.Net\
\Source\ZXing.Net.Mobile.Android\
\Source\ZXing.Net.Mobile.Core\
\Source\ZXing.Net.Mobile.Forms\
\Source\ZXing.Net.Mobile.Forms.Android\
\Source\ZXing.Net.Mobile.Forms.iOS\
\Source\ZXing.Net.Mobile.iOS\
\Source\ZXing.Net.Mobile.Portable\
アプリのソリューションに既存のプロジェクトを追加します。
\アプリフォルダ\ZXing.Net\zxing.portable.csproj
\アプリフォルダ\ZXing.Net.Mobile.Android\ZXing.Net.Mobile.Android.csproj
\アプリフォルダ\ZXing.Net.Mobile.Core\ZXing.Net.Mobile.Core.csproj
\アプリフォルダ\ZXing.Net.Mobile.Forms\ZXing.Net.Mobile.Forms.csproj
\アプリフォルダ\ZXing.Net.Mobile.Forms.Android\ZXing.Net.Mobile.Forms.Android.csproj
\アプリフォルダ\ZXing.Net.Mobile.Forms.iOS\ZXing.Net.Mobile.Forms.iOS.csproj
\アプリフォルダ\ZXing.Net.Mobile.iOS\ZXing.Net.Mobile.iOS.csproj
\アプリフォルダ\ZXing.Net.Mobile.Portable\ZXing.Net.Mobile.Portable.csproj
あとはそれぞれのプロジェクトに関連するNuGetパッケージ(主にXamarin.Forms と Xamarin.Adnroid.Support関連)を更新します。
※ただ単に新しいバージョンをインストールしただけでは参照設定にエクスクラメーションマークがつきます。これはプロジェクトファイルの下部に記述があるパスの設定が異なっているからです。
プロジェクトファイルをテキストエディタで開き、
「..\..\packages\」のあたりを以下のように実際のディレクトリに合わせて変更してみてください。
<Error Condition="!Exists('..\..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets'))" />
</Target>
<Import Project="..\..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
</Project>
手順3.ZXing.Net.Mobile.iOS.ZXingScannerView.cs を修正します。
namespace ZXing.Mobile
{
・・・
bool SetupCaptureSession ()
{
try
{
var started = DateTime.UtcNow;
var availableResolutions = new List<CameraResolution> ();
var consideredResolutions = new Dictionary<NSString, CameraResolution> {
{ AVCaptureSession.Preset352x288, new CameraResolution { Width = 352, Height = 288 } },
{ AVCaptureSession.PresetMedium, new CameraResolution { Width = 480, Height = 360 } }, //480x360
{ AVCaptureSession.Preset640x480, new CameraResolution { Width = 640, Height = 480 } },
{ AVCaptureSession.PresetHigh, new CameraResolution { Width = 640, Height = 480 } }, // 元のPreset640x480と同じ大きさで追加します。
{ AVCaptureSession.Preset1280x720, new CameraResolution { Width = 1280, Height = 720 } },
{ AVCaptureSession.Preset1920x1080, new CameraResolution { Width = 1920, Height = 1080 } }
};
// configure the capture session for low resolution, change this if your code
// can cope with more data or volume
session = new AVCaptureSession () {
//SessionPreset = AVCaptureSession.Preset640x480,
SessionPreset = AVCaptureSession.PresetHigh, // ←Highにします。Preset640x480だとiOS10では動作しません。
};
・・・
あとは普通にビルドして、動作を確認してみてください。
コンパイルには時間がかかりますが、参照設定をリリースコンパイル済みのdllに変更する等すればよいと思います。
今回修正しましたソースは以下のURLにてダウンロード可能です。
http://file.blog.fc2.com/itblogdsi/download/zxing_source.zip
ビルド済みのDLLのみは以下のURLになります。
http://file.blog.fc2.com/itblogdsi/download/zxing_build.zip
ご参考になれば幸いです。
当ブログの内容をまとめた Xamarin逆引きメニュー は以下のURLからご覧になれます。
http://itblog.dynaspo.com/blog-entry-81.html
- 関連記事
-