個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Microsoft MVP for Developer Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

3月23日(土)に、Windowsアプリを開発している皆さん、C#でスマホアプリ開発を試してみませんか?ハンズオン を開催いたしました

こんにちは、@hiro128_777です。

3月23日(土)に、Windowsアプリを開発している皆さん、C#スマホアプリ開発を試してみませんか?ハンズオン を開催いたしました!

jxug.connpass.com

今回は22名の方々にご参加いただきました。

@nakasho_dev さんにはメンターとしてご協力頂き非常に助かりました。この場をお借りして御礼申し上げます。本当にありがとうございました。

今回は iOS Android 両方のアプリを作成するハンズオンでしたが、特にAndroidエミュレータに関する問題に苦戦しました。

なお、毎度のことですが、コーディングではあまり躓きは少なかった印象です。

アンケート結果

ハンズオンを最後まで完了できたか

f:id:hiro128:20190328181026p:plain


みなさん最後まで進めることはできましたが、エミュレータのトラブル、残念ながら環境のトラブルでデプロイができなかった方がいらっしゃいました。



難易度

f:id:hiro128:20190328181059p:plain


難易度についてですが、84%の方が「簡単」「ちょうどいい」とご回答され、16%の方が「難しい」とご回答されました。


時間

f:id:hiro128:20190328181118p:plain


時間ですが、78%の方が「ちょうどいい」または「短い」とご回答いただいております。


ハンズオン自体は、休憩などを省くと正味3時間程度でした。集中力的にも3時間程度がちょうどいい長さだと感じました。


役に立ったか

f:id:hiro128:20190328181143p:plain


なんとみなさま全員に「役に立った」とご回答を頂けました!
主催者としては非常にうれしい結果となりました!



その他のご感想

その他のご感想としては、以下をいただきました。

  • 対象OSがあれば事前調査していただきたかった。(Windows7で動作確認まで行えなかったため)。作りの大枠が理解できてよかった。
  • androidエミュレータに苦戦しました
  • 自由に質問が出来る時間が欲しかったです
  • 時間が短いこともあり、駆け足感は仕方がないかと思いますが、コードの説明がもう少しお願いしたかったと感じました。しかし、このような機会はあまりないのでとても参考になりました。ありがとうございました。
  • 実際に手を動かして開発したのは初めてだったので、経験できたのは良かった。
  • ケーブルを忘れたため、実機ではテストできませんでしたが、シュミレーターで確認出来たので良かったです。
  • 非常にわかりやすかったです。ありがとうございました。
  • MacがなくてもiOSのネイティブアプリを開発できる日を心待ちしています。
  • 以前からXamarinに興味はあったものの、どう作ればよいのかがわからないままでした。今回参加して、いろいろお話を聞けてとても勉強になりました!
  • 自主勉強でXCode上でコーディングを行ったことがありましたが、Swiftとストーリーボードとの格闘に四苦八苦し、開発を諦めてしまったことがありました。私は今C#のWebアプリ開発に携わっているため、C#の知識を流用できるならと思い、Xamarinのことを勉強したいと考えていました。改めて、Xamarinのメリットを学んだ上でハンズオンを体験したことで、スマホアプリ開発の興味が再び湧いてきました。本日はありがとうございました!
  • ご丁寧にありがとうございました。
  • モバイルアプリ初めてでしたが実機確認までできました! モバイルアプリエンジニア転職に向けて勉強がんばります。Xamarinを知るためにSwift, Android開発にも手を出してみようと思います。


また、今後開催してほしいハンズオンとしては、以下をいただきました。

  • 今回のようなハンズオンをお願いします
  • アプリストアへの申請なども含め、難易度を上げたハンズオン。
  • AIと組み合わせたアプリ開発のハンズオンがしてみたいです!
  • 質問・相談会などがあれば。。。
  • いまいまは思いつかないです。
  • c#visual studio) を使ったWEBアプリの作り方(SQL DBのCRUDMVCの使い方、スマホWeBブラウザでも見やすくする工夫 など) を教えていただきたいです
  • Prismを用いての設計方法・Xamarinでのテストの書き方・自動テスト実行環境
  • さきほどのWeBアプリのハンズオンについての追加希望です。環境は、Azure の WEB APP、SQL DB を使ったやり方を教えていただきたいです


皆様のご意見を参考に今後も有意義なハンズオンを開催できるように精進いたします。

最後にお忙しい中休日にお時間を作ってご参加頂いた皆様、本当にありがとうございました!

また、JXUGのイベントでお会いできるのを楽しみにしております!

Visual Studio for Mac 2019 Preview 4がリリースされました。

Visual Studio 2019 for Mac version 8.0 Preview 4 がリリースされました。

visualstudio.microsoft.com



今回のリリースは、基本的にはバグフィックスで、新たな機能の追加はないようです。その中でも、インストーラーにはかなり修正が入りました。


インストーラー修正内容は以下の通りです。

  • Visual Studio for Mac (10.12) に必要な最小バージョンの macOS のサポートを追加しました。 macOS のバージョンが 10.12 以上でない場合に、インストーラーが更新を求めるようになりました。
  • 既定のインストーラーが、より小型でスマートなインストールを行うように変更しました。 既定ですべてを選択されるのではなく、すべてのユーザーには IDE .NET Core を選択し、お使いのマシンにいずれかのバージョンの Xcode または Android SDK が検出された場合には追加で iOS または Android が選択されます。
  • Xamarin.iOS または Xamarin.Mac アプリを開発している場合には、最も推奨されるバージョンの Xcode に更新するように求めます (まだインストールされていない場合)。
  • Android SDK のダウンロードから、NDK を削除しました。
  • Android のアクセス許可のダイアログに対し、UI の改善、ユーザーによる Xamarin.Android の選択解除の許可、ボイスオーバーの問題の修正など、多くの改善を行いました。
  • Android のアクセス許可によってアプリケーションがハングしていた問題を修正しました。
  • 個々のコンポーネントのエラー報告を改善し、すぐにはエラー ページが表示されなくなりました。


また、 Android Emulator に関する問題も修正されています。


その他、細かい修正内容につきましては公式サイトをご覧ください。

docs.microsoft.com



私も早速アップデートし、色々確認しています。


正式版のリリースが待ち遠しいですね!

Visual Studio 2019 for Mac version 8.0 Preview 3 がリリースされました。

Visual Studio for Mac をご愛用の皆さまお待たせしました!


Windows では、 Visual Studio 2019 RC がリリースされましたが、Mac でも Visual Studio 2019 for Mac version 8.0 Preview 3 がリリースされました。

visualstudio.microsoft.com



目玉機能は以下の通りです。

  • Windowsソースコードエディターとコードを共有した新しいエディターがプレビューとして使えるようになりました。
  • Getting started が新しくなりました。
  • Visual Studio for Mac の複数インスタンスの立ち上げがサポートされました。
  • .NET Core 3.0 がサポートされました。
  • 複数プロジェクトの同時実行、デバッグがサポートされました。
  • Azure Functions template のアップデートを検出できるようになりました。
  • Unity デバッガーのコードが Windows と共有になりました。
  • Visual Studio for Mac 2017 とのサイドバイサイドがサポートされました。ただし、Mono と Xamarin SDK は共有となります。


私も早速インストールし、色々機能を試しています。


今後、Visual Studio for MacWindows 版と機能差が少なくなっていくといいですね!

Xamarin.iOS Wrapper Types と User Types の補足

はじめに


前回の記事で、Wrapper Types と User Types について説明しましたが、言葉だけだとわかりにくいので、図を交えて補足したいと思います。


hiro128.hatenablog.jp

Wrapper Types と User Types


Wrapper types とは

Wrapper types は、UIView や UIButton のような Objective-C の組み込み型をラップしたもので、マネージドの世界では、ネイティブオブジェクトのインスタンスへのハンドルだけを持っています。

Wrapper types のインスタンス作成
var view = new UIView();


Wrapper types のイメージ

f:id:hiro128:20190207195119p:plain



User types とは


User types は、UIView や UIButton のような Wrapper types を継承し派生した型で、Objective-C に対応する型が無いものを指し、ネイティブオブジェクトのインスタンスへのハンドルの他に、マネージドな世界だけで管理されている、フィールド、プロパティやメソッドを持っています。

User Types のインスタンス作成

public class MyView : UIView
{
    string myField;

    public string MyProperty { get; set; }

    public MyView(string fieldValue)
    {
        myField = fieldValue;
    }
}

var view = new MyView("fieldValue")
{
    MyProperty = "propertyValue"
};


User Types のイメージ

f:id:hiro128:20190207195144p:plain





これで、Wrapper Types と User Types の違いがわかりやすくなりましたら幸いです。



今回は以上です。

Xamarin.iOS でメモリーリークをコントロールするために知っておきたいこと

はじめに


こんにちは、@hiro128_777です。


この記事は「Xamarin その1 Advent Calendar 2018」の21日目になります。


Xamarin.iOS は基本的には、Objective-C の薄い Wrapper であることは間違いありませんが、オブジェクトがマネージドの世界とネイティブの世界でそれぞれに存在し、互いに関係性を持ちながら、インスタンスが生成・破棄されているので、GC の挙動を正しく理解しておかないとメモリリークをコントロールするのが難しくなる弱点があります。今回はそこについてのお話です。


この記事の内容については Xamarin.iOS のソースコードhttps://github.com/xamarin/xamarin-macios/blob/master/runtime/runtime.mに記載されています。


これは、Xamarin.iOS の GC の挙動について調べるために、Xamarin.iOS のソースコード を読んでいるときに偶然発見しました。これを読むと Xamarin.iOS の GC の挙動のクセがわかると思います。


このような超重要な事が、そんなところに書いてあってもなかなか皆さんが目にする機会はないと思い、今回日本語に翻訳し説明を追加しました。
※わかりやすくするために色々補完して翻訳していますので、原文に忠実な翻訳ではありません。



GC の挙動にかかわる iOS アプリののアーキテクチャーについてはこちらの公式ドキュメントもご参照いただくとより理解が深まります。
docs.microsoft.com



また、より詳しい記事を書き始めましたのでこちらもご覧ください。
hiro128.hatenablog.jp


参照カウンタについての注意点

Wrapper type と User type


Wrapper type は、UIViewUIButton のような Objective-C の組み込み型をラップしたもので、マネージドの世界では、ネイティブオブジェクトのインスタンスへのハンドルだけを持っています。


一方、User type は、UIViewUIButton のような Wrapper type を継承し派生した型で、Objective-C に対応する型が無いものを指し、ネイティブオブジェクトのインスタンスへのハンドルの他に、マネージドな世界だけで管理されている、フィールド、プロパティやメソッドを持っています。


Xamarin.iOS における GC の挙動を考える上で、この2つの型の区別はとても重要となります。


Wrapper type の寿命について


これはとても簡単です。


Wrapper type のインスタンスの寿命は、ネイティブオブジェクトの寿命とはリンクしてません。


Wrapper type のインスタンスは、マネージドな世界にネイティブオブジェクトへのハンドル以外には何も保持していませんので、GC の判断によっていつでも自由に解放できます。もし、後の段階で再びそのオブジェクトが必要になった場合には Wrapper type のインスタンスが再度作成されるだけです。


User type の寿命について


こちらは簡単ではありません。


User type のオブジェクトは マネージドな世界にユーザーが定義した状態を含む可能性があるため GC の判断によって自由に解放することはできません。
よって、User type のオブジェクトを必要な間はずっと生かし続けることを保証する必要があります(マネージオブジェクトは強力な GCHandle によって保持されます)。


この場合の問題は「どうやって不要になったタイミングを判断するのか」ということになります。
これには、歴史的に2つのケースが存在します。

ケース1


ユーザーが Dispose を呼び出すと、マネージオブジェクトの参照が解放され、ネイティブオブジェクトとマネージオブジェクトの間のリンクが切断され、GC がそのオブジェクトを解放できるようになります。(そのマネージオブジェクトを保持している他のオブジェクトが何もなければ)


ケース2


参照カウンタが1に達すると、マネージオブジェクトからの参照が唯一の参照であり、ネイティブコードは当該オブジェクトを再び使用しないと安全に仮定できます。よって、リンクを解除し、ネイティブオブジェクトを解放して、GC がマネージオブジェクトを解放できるようにします。


ケース1で、ユーザーが Dispose を呼び出した後、ネイティブコードが何らかの理由でそのオブジェクトを使用しようとすると、問題が発生します。 Xamarin.iOS は対応するマネージオブジェクトが存在しないことを検出し、それを(再)作成しようとします。ですが、これは失敗し、プロセスを終了させる例外がスローされます(この時、スタックにはマネージドフレーム/例外ハンドラが存在しない可能性があります)。


解決策としては、Disposeを呼び出すときに、次のことを行う必要があります。

  • マネージオブジェクトの参照を解放する。
  • ネイティブオブジェクトの参照カウンタが0に達するまで、ネイティブオブジェクトと管理オブジェクトの間のリンクを切断しない。


これにより、ネイティブオブジェクトが存続している限り、マネージオブジェクトを引き続き参照することができます。

User type の挙動についての注意点

User type のオブジェクトは、次のいずれかの条件が発生したときにネイティブオブジェクトへの参照を解放するようになっています。

  • Dispose がオブジェクトに対して(手動で)呼び出されたとき。
  • マネージオブジェクトの Handle プロパティが変更されたとき。
  • GC がオブジェクトを解放したとき。これは、参照カウンタが1でその参照がマネージオブジェクトによる参照である場合にのみ発生します。

(それ以外の時は、マネージオブジェクトに強力な GCHandle があるため、GC の解放処理はブロックされます。)


User type のオブジェクトは、次のいずれかの条件が発生すると、ネイティブ <-> マネージオブジェクトのディクショナリーからオブジェクトが削除されます。

  • ネイティブオブジェクトが dealloc されたとき(参照カウンタは0になります)。
  • マネージオブジェクトの Handle プロパティが変更されたとき(変更前の Handle 値とマネージオブジェクトの間のリンクがディクショナリーから削除されます)。

 

User type のオブジェクトは、ネイティブの世界の2つの情報を追跡し続けています。

  • マネージオブジェクトへの GCHandle。
  • マネージオブジェクトのインスタンスが存在するかどうか。


User type のオブジェクトはすでに GCHandle を保存する Objective-C インスタンス変数を持っているので、別のインスタンス変数を作成しません。
User type のオブジェクトはマネージオブジェクトへの参照(MANAGED_REF_BIT)があるかどうかを GCHandle の1ビットで保存します。



まとめ


Wrapper type は単に、ラッパーですので難しいことは何もありません。
問題は、User type です。こちらは、マネージドな世界とネイティブの世界にそれぞれ状態を持つことになるので、GC の挙動が複雑になっています。


オブジェクトの解放がうまく行われない時には、今回の内容を確認してたいただくとヒントになると思います。実際私もこれを理解してからは、解放できなくて困ったり、強引な Dispose で Exception に悩まされることが無くなりました。


以上です。