takataka430’s blog

.NET系を中心に勉強したことのまとめを書きます

【Xamarin.Forms】ページ遷移と同時に実行する非同期メソッドについて考えた話

Xamarin.Formsで開発する時に非同期処理を結構使うのですが、いつも悩むのが非同期処理のメソッドをページ遷移と同時に実行するにはどうすればいいのかということです。というわけで自分なりに色々考えてみました。

どんな方法がある?

パターンとしては以下の3通りがあると思います。
  
1. ViewまたはViewModelのコンストラクタ内で実行する
2. ViewのOnAppearingメソッドで実行する
3. ViewのAppearingイベントで実行する
  
1と2の方法は、コンストラクタ自体は非同期にできないので、呼び出す非同期メソッドをasync voidとすれば画面上の動きとしてはうまくいっているように見えます。しかし、非同期処理について調べると「async voidイベントハンドラ以外では使わない」というのが鉄則のようです。また、Visual Studioからも「非同期メソッドでvoidを返すべきではない」と注意されます。

イベントハンドラを使えばいい!

そこで3の方法です。イベントなのでasync voidでも問題ないはずです。具体例としてコードを書くと以下のようなります。ページ遷移直後は待機中と表示し、3秒後に待機完了という文字列に変更するものです。

View

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:XF_VmConstructor" 
             Appearing="MainPage_Appearing"
             x:Class="XF_VmConstructor.MainPage">
    <ContentPage.BindingContext>
        <local:MainPageViewModel x:Name="mainPageViewModel"/>
    </ContentPage.BindingContext>
    <StackLayout>
        <Label Text="{Binding Label}" 
               HorizontalOptions="Center" 
               VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

  
コードビハインド

using System;
using System.ComponentModel;
using Xamarin.Forms;

namespace XF_VmConstructor
{
    [DesignTimeVisible(true)]
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        async void MainPage_Appearing(object sender, EventArgs e)
        {
            await mainPageViewModel.AsyncMethod();
        }
    }
}

  
ViewModel

using System.ComponentModel;
using System.Threading.Tasks;

namespace XF_VmConstructor
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public async Task AsyncMethod()
        {
            Label = "待機中";
            await Task.Delay(3000);
            Label = "待機完了";
        }

        private string label;
        public string Label
        {
            get { return label; }
            set
            {
                if(label != value)
                {
                    label = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Label)));
                }
            }
        }
    }
}

ViewModelで非同期なメソッドを定義して、ViewのAppearingイベントで呼び出しています。 この方法ならVisual Studioにも怒られずに済みます。

気になっているのが、Xamarin.Formsのサンプルコードでasync voidを使っているメソッドをたまに見るんですよね(async void OnAppearingとか)。それでも問題ないんですかね??やはり非同期処理についてしっかり理解しなければダメだな・・・。

といったところで今回は失礼します。

Xamarinの実機デバッグまとめ

Xamarinでアプリの挙動を確認する時、実機で動かして確認したいですよね。そのためのまとめメモです。

開発PCと実機デバッグを行う端末の組み合わせ

それぞれの組み合わせで実機デバッグができるかどうかを表にしてみました。

f:id:takataka430:20190414014543p:plain:w400

よく「XamarinをやるならPCはMac」と言われますが、このようにMacだとAndroidiOSも実機デバッグできるからなんだと思います。なのでもし、例えばXamarin.Androidを使ってAndroidアプリのみを作るのであればWindowsでも問題ないと思います。
(・・・が、個人的にはAndroidに関してもMacの方がトラブルが少ないような気がするのでMacを使うことをオススメしたいです)

実機デバッグのための手順は?

以下の通りMicrosoftの公式ドキュメントに手順が記載されていました。

Xamarin.iOS(Xamarin.FormsでiOSを実機デバッグする場合含む)

docs.microsoft.com

Apple Developer Programに参加している場合は「自動プロビジョニング」「手動プロビジョニング」のどちらかを実行してください。推奨は自動プロビジョニングの方みたいです。
Apple Developer Programに参加していない場合は「無料プロビジョニング」の手順を実行します。なおApple IDが必要になります。

Xamarin.Android(Xamarin.FormsでAndroidを実機デバッグする場合含む)

docs.microsoft.com

AndroidiOSに比べると設定が簡単でいいですね。   
  


動きを確認するのはシミュレータでもできますが、やはり実機で動きを確認した方がいいと思います。実機デバッグの方がトラブルも少ないと思うので、ぜひ使ってみてください。

「Visual Studio 2019 を試してみる会」に参加しました

4月10日(水)に開催された「【Launch 記念】Visual Studio 2019 を試してみる会」に参加しました。

csugjp.connpass.com

Visual Studio2019のGitの使い方およびGithubとの連携、IntelliCodeの使い方、VS for Macなどの発表がありとても参考になりました。

発表資料はこちらにあるのでぜひ見てみてください。 csugjp.connpass.com

感想

・Gitは普段コマンドで使っているのですが、Visual Studioの機能を使えば手軽にコミットやプッシュなどができるのでこちらもいいと思いました。
・IntelliCodeは学習に時間がかかったり注意点もあるみたいですが、良さそうな機能ですね。チームで共有は便利そうだと思いました。
・VS for MacにもIntelliCodeとLive shareが追加されてほしいのでこれからもどんどんVS for Macを使います!みなさんも、是非VS for Macを使いましょう!!



ちなみに、Visual Studio 2019 for MacでXamarin.Formsを使ってみた感想を過去のブログで書いているのでよろしければ読んでください。 takataka430.hatenablog.com

Visual Studio 2019でXamarin.Formsを使ってみました

Visual Studio 2019がそろそろリリースされますね。それに先立ちプレビュー版をダウンロードできるようなので、使ってみました。
この記事ではVisual Studio 2019でXamarin.Formsを少し使ってみて気づいたことを書いてみようと思います。
Visual Studio 2017 for Macとの比較です)

プロジェクト作成後、XAMLプレビューがビルドする前から使える

2017だとビルドしてからでないとプレビューが表示されなかったと思うのですが、2019だとビルド前からプレビューに表示されるようです。ただ、自分の場合なぜかAndroidはエラーになります(ビルドすればちゃんと表示されます)。

XAMLプレビューで機種が選べる

下の画像のようにプレビュー画面の上に機種を選択するバーが設置されています。ここからスマートフォンタブレットの機種を選べます。何気に便利そうだと思いました。

f:id:takataka430:20190329220811p:plain:w300

XAMLの編集画面で縦線が表示される

下の画像のように要素の左端から細い点線が出ています。2017ではなかったですよね? 要素の縦の位置を揃えるのに便利だと思いました。

f:id:takataka430:20190329221421p:plain


まだ少し触っただけなので気づいたのはこのくらいです。ぜひみなさんも使ってみてください!

【Xamarin.Forms】ViewModelでContentViewとFrameを操作してDisplayAlertの代わりにできないか試してみた

ViewModelで悩むことの一つとして「DisplayAlertを呼び出せない」というのがあると思います。色々解決方法を考えていて、「もしかしてContentViewとFrameを使えばDisplayAlertの代わりになるのでは??」と思いついたのでやってみたメモです。
(ライブラリやフレームワークは使わずに素のXamarin.Formsでやってみました)

コード

次のように書いてみました。(コードビハインドはInitializeComponentのみなので省略します)

画面

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:AlertFromViewModel" 
             x:Class="AlertFromViewModel.MainPage">
    <ContentPage.BindingContext>
        <local:MainPageViewModel/>
    </ContentPage.BindingContext>
    <AbsoluteLayout>
        <Button Text="Alert" 
                AbsoluteLayout.LayoutFlags="PositionProportional"
                AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"
                HorizontalOptions="Center" 
                VerticalOptions="CenterAndExpand" 
                Command="{Binding OnAlert}"/>
        <ContentView AbsoluteLayout.LayoutFlags="All"
                     AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
                     Opacity="0.4"
                     BackgroundColor="Black"
                     IsVisible="{Binding IsVisible}"/>
        <Frame AbsoluteLayout.LayoutFlags="PositionProportional"
               AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"
               IsVisible="{Binding IsVisible}">
            <StackLayout>
                <Label Text="アラートです"
                       HorizontalTextAlignment="Center"/>
                <Button Text="OK"
                        Command="{Binding OnOK}"/>
            </StackLayout>
        </Frame>        
    </AbsoluteLayout>
</ContentPage>

  
ビューモデル

using System.ComponentModel;
using Xamarin.Forms;

namespace AlertFromViewModel
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public MainPageViewModel()
        {
            OnOK = new Command(() =>
            {
                IsVisible = false;
            });

            OnAlert = new Command(() =>
            {
                IsVisible = true;
            });
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private bool isVisible;
        public bool IsVisible
        {
            get { return isVisible; }
            set
            {
                if(isVisible != value)
                {
                    isVisible = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsVisible)));
                }
            }
        }

        public Command OnOK { get; }

        public Command OnAlert { get; }
    }
}

画面の「Alert」ボタンを押すとContentViewとFrameが表示されます。その後Frameの「OK」ボタンを押すとContentViewとFrameが非表示になり、元の画面に戻ります。

動きはこんな感じです!

f:id:takataka430:20190324230137g:plain:w200

アラートっぽくなりましたね!
  
・・・でも正直ちょっと面倒なので、素直にコードビハインドに書くかライブラリを使った方がいいのかなと思いました。

【Xamarin.Forms】QRコードの読み取りをする方法

Xamarin.FormsにはQRコードやバーコードを読み取るためのZXing.Net.Mobileというライブラリがあります。

GitHub - Redth/ZXing.Net.Mobile: Zxing Barcode Scanning Library for MonoTouch, Mono for Android, and Windows Phone

今回はこのライブラリを使用して、Xamarin.FormsでQRコードをスキャンして表示する簡単なアプリを作ってみました。

環境

Visual Studio Community 2017 for Mac
Xamarin.Forms (3.6.0.220655)
ZXing.Net.Mobile (2.4.1)
ZXing.Net.Mobile.Forms (2.4.1)

手順

準備

それぞれのプロジェクト(.Net Standard、iOSAndroid)に以下のNuGet Packageをインストールします。

  • ZXing.Net.Mobile
  • ZXing.Net.Mobile.Forms   
      

次にAndroidのMainActivity.csとiOSのAppDelegate.csにコードの追加を行います。   

MainActivity.cs

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        (省略)

        //追加
        ZXing.Net.Mobile.Forms.Android.Platform.Init();

        LoadApplication(new App());
    }

    //追加
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
       global::ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
       base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

  
AppDelegate.cs  

[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        global::Xamarin.Forms.Forms.Init();

        //追加
        ZXing.Net.Mobile.Forms.iOS.Platform.Init();

        LoadApplication(new App());
        return base.FinishedLaunching(app, options);
    }
}

次に端末でカメラを使用するための準備をします。
  
Android:AndroidManifest.xmlの「必要なアクセス許可」の「カメラ」にチェックを入れる

iOS:info.plistを開き、以下の項目を追加する
* プロパティ:プライバシー-カメラの利用状況の説明
* 値:"カメラを利用してスキャンします"

最後にナビゲーションページを使うためにApp.xaml.csに以下の変更を行います。

public App()
{
    InitializeComponent();
    
    //ここを変更
    MainPage = new NavigationPage(new MainPage());
}

  
準備はこれでOKです。それでは画面を作っていきましょう。


画面作成と処理の追加

それではアプリを作っていきましょう。ページは次の2つだけです。

  • MainPage:中央にボタンがあって、それを押すとスキャンするページ(QRScanPage)に移動
  • QRScanPage:読み取りを行うと画面中央に読み取った値をアラートに表示する  OKボタンを押すと読み取りを再開

  
最初にMainPageです。このページはボタンを押して次のページに行くだけです。
  
MainPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:QRCodeStudy" 
             x:Class="QRCodeStudy.MainPage">
    <StackLayout>
        <Button Text="QRコード読み取り" 
                Clicked="OnQR"
                HorizontalOptions="Center" 
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

  

MainPage.xaml.cs

using System;
using Xamarin.Forms;

namespace QRCodeStudy
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        void OnQR(object sender, EventArgs e)
        {
            Navigation.PushAsync(new QRScanPage());
        }
    }
}

次に読み取りページを作っていきます。   

QRScanPage.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="QRCodeStudy.QRScanPage"
             xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms">
    <ContentPage.Content>
        <Grid>
            <zxing:ZXingScannerView x:Name="zxing"
                                    OnScanResult="Handle_OnScanResult"/>
            <zxing:ZXingDefaultOverlay />
        </Grid>
    </ContentPage.Content>
</ContentPage>

ZXingScannerViewのOnScanResultイベントで読み取った値をアラートに表示するように設定します。   

QRScanPage.xaml.cs

using Xamarin.Forms;

namespace QRCodeStudy
{
    public partial class QRScanPage : ContentPage
    {
        public QRScanPage()
        {
            InitializeComponent();
        }

        void Handle_OnScanResult(ZXing.Result result)
        {
            Device.BeginInvokeOnMainThread(async () =>
            {
                zxing.IsAnalyzing = false;  //読み取り停止
                await DisplayAlert("通知","次の値を読み取りました:" + result.Text,"OK");
                zxing.IsAnalyzing = true;   //読み取り再開
            });
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            zxing.IsScanning = true;
        }

        protected override void OnDisappearing()
        {
            zxing.IsScanning = false;
            base.OnDisappearing();
        }
    }
}

動きは以下のような感じです。
(手元にQRコードがなかったのでバーコードを読み取っています。QRコードも同様に読み取る事ができます。)

f:id:takataka430:20190321140723g:plain:w200

ViewModelで処理を行う

上のコードは値を読み取った時の処理をコードビハインドに書いています。これをビューモデルに書いてみましょう。
QRScanPageを書き換えて、ビューモデルを追加します。コードは以下の通りです。
  
QRScanPage.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="QRCodeStudy.QRScanPage"
             xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
             xmlns:local="clr-namespace:QRCodeStudy">
    <ContentPage.BindingContext>
        <local:QRScanPageViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <AbsoluteLayout>
            <Grid AbsoluteLayout.LayoutFlags="All"
                  AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1">
                <zxing:ZXingScannerView x:Name="zxing"
                                        ScanResultCommand="{Binding OnScan}"
                                        IsAnalyzing="{Binding IsAnalyzing}"/>
                <zxing:ZXingDefaultOverlay />
            </Grid>
            <Frame AbsoluteLayout.LayoutFlags="PositionProportional"
                   AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"
                   IsVisible="{Binding FrameVisible}">
                <StackLayout>
                    <Label Text="読み取った値"
                           HorizontalTextAlignment="Center"/>
                    <Label Text="{Binding ScannedCode}"
                           HorizontalTextAlignment="Center"/>
                </StackLayout>
            </Frame>
        </AbsoluteLayout>
    </ContentPage.Content>
</ContentPage>

ZXingScannerViewはScanResultCommandというプロパティを持っているようなのでこれをビューモデルのCommandにバインドしてみます。また、ビューモデルからDisplayAlertを呼び出す方法がわからないので、Frameにスキャン結果を記述するようにします。   
  
QRScanPage.xaml.cs

using Xamarin.Forms;

namespace QRCodeStudy
{
    public partial class QRScanPage : ContentPage
    {
        public QRScanPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            zxing.IsScanning = true;
        }

        protected override void OnDisappearing()
        {
            zxing.IsScanning = false;
            base.OnDisappearing();
        }
    }
}

  

QRScanPageViewModel

using System.ComponentModel;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace QRCodeStudy
{
    public class QRScanPageViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public QRScanPageViewModel()
        {
            OnScan = new Command<ZXing.Result>((result)=>
            {
                Device.BeginInvokeOnMainThread( async () =>
                {
                    this.IsAnalyzing = false;  //読み取り停止
                    FrameVisible = true;       //Frameを表示
                    ScannedCode = result.Text;
                    await Task.Delay(1000);    //1秒待機
                    this.IsAnalyzing = true;   //読み取り再開
                    FrameVisible = false;      //Frameを非表示
                });
            });
        }

        public Command OnScan { get; }

        private bool isAnalyzing;
        public bool IsAnalyzing
        {
            get { return isAnalyzing; }
            set
            {
                if (isAnalyzing != value)
                {
                    isAnalyzing = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsAnalyzing)));
                }
            }
        }

        private string scannedCode;
        public string ScannedCode
        {
            get { return scannedCode; }
            set
            {
                if (scannedCode != value)
                {
                    scannedCode = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ScannedCode)));
                }
            }
        }

        private bool frameVisible;
        public bool FrameVisible
        {
            get { return frameVisible; }
            set
            {
                if (frameVisible != value)
                {
                    frameVisible = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FrameVisible)));
                }
            }
        }
    }
}

コードを読み取ったら読み取った値が記載されているFrameを1秒間表示し、その間は読み取りをしないようにします。Frameが非表示になったら読み取りを再開するようにしています。
  
動きを見てみましょう。

f:id:takataka430:20190321153800g:plain:w200

うまく動きました!

参考にしたページ

ZXing.Net Mobile を使ってみた - Android 編 - - Xamarin 日本語情報

ZXing.Net Mobile を使ってみた - iOS、UWP 編 - - Xamarin 日本語情報

GitHub - Redth/ZXing.Net.Mobile: Zxing Barcode Scanning Library for MonoTouch, Mono for Android, and Windows Phone

Is there a way to render the Zxing ScannerPage in Xaml? — Xamarin Community Forums

【Xamarin.Forms】ページ間での値の受け渡し方法を考えてみた(その2)

以前、ページ間の値の受け渡しをコードビハインドに記述してやってみるという記事を投稿しました。

takataka430.hatenablog.com

今回はMVVMっぽく、ViewModelとModelを使ってやる方法を考えてみました。
1ページ目と2ページ目それぞれのVidwModelを作り、それぞれがModelを参照・更新するというような感じです。

環境

Visual Studio Community 2017 for Mac
Xamarin.Forms (3.4.0.1008975)

手順

まずは以下のようなStaticなPersonクラスを作ります。これで複数のクラスから参照することができます。

namespace XF_NavigationMVVM.Models
{
    public static class Person
    {
        public static string Name { get; set; }
    }
}

  

1ページ目の画面、コードビハインド、ビューモデルは以下のようになります。Entryに値が入力されるとビューモデルのNameプロパティと、PersonクラスのNameプロパティに値が設定されます。   

画面

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="XF_NavigationMVVM.Views.FirstPage">
    <ContentPage.Content>
        <StackLayout VerticalOptions="Center">
            <Entry Text="{Binding Name}"
                   Placeholder="名前を入力してください"/>
            <Button Text="次のページへ"
                    Clicked="ToSecondPage"/>
        </StackLayout> 
    </ContentPage.Content>
</ContentPage>

  
コードビハインド

using System;

using Xamarin.Forms;
using XF_NavigationMVVM.ViewModels;

namespace XF_NavigationMVVM.Views
{
    public partial class FirstPage : ContentPage
    {
        public FirstPage()
        {
            InitializeComponent();
            BindingContext = new FirstPageViewModel();
        }

        void ToSecondPage(object sender, EventArgs e)
        {
            Navigation.PushAsync(new SecondPage());
        }
    }
}

  
ビューモデル

namespace XF_NavigationMVVM.ViewModels
{
    public class FirstPageViewModel 
    {
        private string name;
        public string Name 
        {
            get { return name; }
            set
            {
                name = value;
                Models.Person.Name = name;
            }
        }
    }
}

  

2ページ目の画面、コードビハインド、ビューモデルは以下のようになります。ビューモデルのコンストラクタでPersonクラスのNameプロパティを受け取り画面に表示します。   
  
画面

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="XF_NavigationMVVM.Views.SecondPage">
    <ContentPage.Content>
        <StackLayout VerticalOptions="Center">
            <Label Text="{Binding Name}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

  
コードビハインド

using Xamarin.Forms;
using XF_NavigationMVVM.ViewModels;

namespace XF_NavigationMVVM.Views
{
    public partial class SecondPage : ContentPage
    {
        public SecondPage()
        {
            InitializeComponent();
            BindingContext = new SecondPageViewModel();
        }
    }
}

  
ビューモデル

namespace XF_NavigationMVVM.ViewModels
{
    public class SecondPageViewModel
    {
        public SecondPageViewModel()
        {
            this.Name = Models.Person.Name;
        }

        public string Name { get; set; }
    }
}

動きを確認すると以下の方な感じです。

f:id:takataka430:20190316211321g:plain

一応画面上ではできているようですが、こんな感じでいいのかな・・?

気になる事

この場合だと逆のパターン、つまり2ページ目に値を入力した後、ナビゲーションバーで1ページ目に戻りそこで2ページ目に入力した値を表示する場合はどうすればいいですかね?今回の方法だとできなさそうなので気になりました。ちょっと調べてみようと思います。