この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
Xamarin.Macを使用すると、C#でネイティブなMacのアプリが作成可能です。 ここでは、私自身がXamarin.Macに入門して学習した事項を覚書として書かせて頂いています。
今回は、特定のS3バケットのオブジェクトを一覧してみました。
2 NuGetパッケージ
Visual Studioでは、パッケージの管理は、NuGetで行うことができます。
検索で、「awssdk」と入れてみると、作成者が、Amazon Web Servicesとなった公式のSDK(パッケージ)が検索できます。
今回追加したのは、S3とCognitoIdentityの2つですが、依存関係で必要なパッケージも一緒にダウンロードされます。
3 Cognito
プログラムからS3にアクセスするために、CognitoでプールIDを作成しています。
ロールに付与したパーミッションは、特定のバケットのオブジェクト一覧と、取得のみになっています。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::xamarin-s3-sample"
},
{
"Effect": "Allow",
"Action": [
"s3:getObject"
],
"Resource": "arn:aws:s3:::xamarin-s3-sample/*"
}
]
}
4 S3アクセス
Cognitoの認証でS3バケットにアクセスするために作成したクラスは、以下のとおりです。
コンストラクタで、Cognito認証によるS3クライアントを生成し、2つのメソッド(一覧取得とオブジェクト取得)が利用可能になっています。
public class S3Client {
// Cognito Pool ID
private string poolId = "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
// アクセス先のバケット
private string bucketName = "xamarin-s3-sample";
private AmazonS3Client client;
public S3Client() {
// クレデンシャル取得
var cognitoCredentials = new CognitoAWSCredentials(poolId, RegionEndpoint.APNortheast1);
// S3クライアントの生成
client = new AmazonS3Client(cognitoCredentials);
}
// バケット内のオブジェクト一覧取得
public async System.Threading.Tasks.Task<List<string>> getObjectsAsync() {
var result = await client.ListObjectsAsync(bucketName);
return result.S3Objects.Select(o => o.Key).ToList();
}
// 指定したオブジェクトの取得
public async System.Threading.Tasks.Task<string> getObjectAsync(string key) {
var request = new GetObjectRequest {
BucketName = bucketName,
Key = key
};
var response = await client.GetObjectAsync(request);
var reader = new StreamReader(response.ResponseStream);
return reader.ReadToEnd();
}
}
5 画面構成
メインとなるウインドウは、NSSplitViewで3分割され、下のウインドウの左側にNSCollectionView、右側にNSTextViewを配置しています。 それぞれ、CollectionViewとTextViewという名前でOutletが作成されています。
コレクションビューのアイテム用ビューは、Labelが、ファイル名表示用にバインディングされています。
6 DataSource/Delegate
コレクションビューのデータソースは、バケット内のオブジェクト一覧を保持するリストFilesで動作しています。
public class CollectionViewDataSource: NSCollectionViewDataSource {
public List<string> Files = new List<string>();
public CollectionViewDataSource() {
}
public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath) {
var item = collectionView.MakeItem("cell", indexPath) as ItemViewController;
item.FileName = Files[(int)indexPath.Item];
return item;
}
public override nint GetNumberofItems(NSCollectionView collectionView, nint section) {
return Files.Count;
}
}
デリゲートでは、コンストラクタでViewControllerをコピーしておいて、選択が変化したタイミングで、ItemSelectedAsync()を呼び出しています。
public class CollectionViewDelegate: NSCollectionViewDelegateFlowLayout {
ViewController ViewController;
public CollectionViewDelegate(ViewController ViewController) {
this.ViewController = ViewController;
}
public override void ItemsSelected(NSCollectionView collectionView, NSSet indexPaths) {
var paths = indexPaths.ToArray<NSIndexPath>();
_ = ViewController.ItemSelectedAsync((int)paths[0].Item);
}
}
7 ViewController
メインとなるViewControllerです。
S3を操作するクラスをコンストラクタで生成しています。
起動時、若しくはReloadボタンが押されたタイミングで、バケットの一覧を取得して、左側のコレクションビューを初期化します。また、コレクションビューの選択が変化したタイミングで、右側のテキストビューを更新しています。
public partial class ViewController : NSViewController {
S3Client s3client;
public ViewController(IntPtr handle) : base(handle) {
s3client = new S3Client();
}
public override void ViewDidLoad() {
base.ViewDidLoad();
// PictureViewControllerの登録
CollectionView.RegisterClassForItem(typeof(ItemViewController), "cell");
// DataSource
CollectionView.DataSource = new CollectionViewDataSource();
// Flow layout
var flowLayout = new NSCollectionViewFlowLayout() {
ItemSize = new CGSize(100, 100),
SectionInset = new NSEdgeInsets(10, 10, 10, 20),
MinimumInteritemSpacing = 10,
MinimumLineSpacing = 10
};
CollectionView.WantsLayer = true;
CollectionView.CollectionViewLayout = flowLayout;
// Delegate
CollectionView.Delegate = new CollectionViewDelegate(this);
//Reloadボタン
ReloadButton.Activated += ReloadButton_Activated;
//Reload
_ = ReloadObjectsAsync();
}
// Reloarボタンのアクション
private void ReloadButton_Activated(object sender, EventArgs e) {
_ = ReloadObjectsAsync();
}
// リロード(一覧の再取得)
async Task ReloadObjectsAsync() {
((CollectionViewDataSource)CollectionView.DataSource).Files = await s3client.getObjectsAsync();
CollectionView.ReloadData();
}
// 選択が変化した際に呼び出せれる
public async Task ItemSelectedAsync(int index) {
var key = ((CollectionViewDataSource)CollectionView.DataSource).Files[index];
Console.WriteLine(key);
var text = await s3client.getObjectAsync(key);
Console.WriteLine(text);
TextView.Value = text;
}
// ・・・略・・・
8 最後に
AWS SDKは、DotNet対応版が揃っており、Visual Studioでは、これをNuGetで簡単に導入できます。
おかげで、Xamarin.Macからでも、AWSのリソースの利用は、非常に簡単だと思います。