LoginSignup
8
8

More than 5 years have passed since last update.

【Unity】SocialWorkerをObservableに使うラッパークラスを書いた【UniRx】

Last updated at Posted at 2017-07-06

はじめに

【Unity】SocialWorkerでLINEにテキスト投稿ができない問題の対応【SocialWorker】 の記事でも紹介してますが、SocialWorker はUnityからSNSに手軽にシェアを行うことができる素晴らしいアセットです。

ただ、UniRx 使いとしてコールバックを受け取るようなメソッドは使いたくなかったのでRxの世界で使いやすいようにIObservable<Unit>を返すラッパークラスを書いてみました。

ソースコード

LINEへの投稿については 【Unity】SocialWorkerでLINEにテキスト投稿ができない問題の対応【SocialWorker】 の記事で解説している問題への対応を含めています。

2017/7/6 追記

実装が色々まずかったので修正しました。

  • 各メソッド名の最後に"Async"をつけた
  • Subscribe()されないと実行されないようにした
  • マルチスレッド対応(できてるか不安...)
  • 専用のエラークラス実装
ObservableSocialWorker.cs
using SWorker;
using UniRx;

namespace Jagapippi.Social
{
    public static class ObservableSocialWorker
    {
        public static IObservable<Unit> PostTwitterAsync(string message, string url, string imagePath)
        {
            return Observable.Create<Unit>(observer =>
            {
                var gate = new object();
                var isDisposed = false;
                SocialWorker.PostTwitter(message, url, imagePath, result =>
                {
                    lock (gate)
                    {
                        if (isDisposed) return;
                        if (result == SocialWorkerResult.Success)
                        {
                            observer.OnNext(Unit.Default);
                            observer.OnCompleted();
                        }
                        else
                        {
                            observer.OnError(new SocialWorkerException(result));
                        }
                    }
                });
                return Disposable.Create(() =>
                {
                    lock (gate)
                    {
                        isDisposed = true;
                    }
                });
            });
        }

        public static IObservable<Unit> PostFacebookAsync(string imagePath)
        {
            return Observable.Create<Unit>(observer =>
            {
                var gate = new object();
                var isDisposed = false;
                SocialWorker.PostFacebook(imagePath, result =>
                {
                    lock (gate)
                    {
                        if (isDisposed) return;
                        if (result == SocialWorkerResult.Success)
                        {
                            observer.OnNext(Unit.Default);
                            observer.OnCompleted();
                        }
                        else
                        {
                            observer.OnError(new SocialWorkerException(result));
                        }
                    }
                });
                return Disposable.Create(() =>
                {
                    lock (gate)
                    {
                        isDisposed = true;
                    }
                });
            });
        }

        public static IObservable<Unit> PostLineAsync(string message, string imagePath)
        {
            return Observable.Create<Unit>(observer =>
            {
                var gate = new object();
                var isDisposed = false;
                SocialWorker.PostLine(System.Uri.EscapeUriString(message), imagePath, result =>
                {
                    lock (gate)
                    {
                        if (isDisposed) return;
                        if (result == SocialWorkerResult.Success)
                        {
                            observer.OnNext(Unit.Default);
                            observer.OnCompleted();
                        }
                        else
                        {
                            observer.OnError(new SocialWorkerException(result));
                        }
                    }
                });
                return Disposable.Create(() =>
                {
                    lock (gate)
                    {
                        isDisposed = true;
                    }
                });
            });
        }

        public static IObservable<Unit> PostInstagramAsync(string imagePath)
        {
            return Observable.Create<Unit>(observer =>
            {
                var gate = new object();
                var isDisposed = false;
                SocialWorker.PostInstagram(imagePath, result =>
                {
                    lock (gate)
                    {
                        if (isDisposed) return;
                        if (result == SocialWorkerResult.Success)
                        {
                            observer.OnNext(Unit.Default);
                            observer.OnCompleted();
                        }
                        else
                        {
                            observer.OnError(new SocialWorkerException(result));
                        }
                    }
                });
                return Disposable.Create(() =>
                {
                    lock (gate)
                    {
                        isDisposed = true;
                    }
                });
            });
        }

        public static IObservable<Unit> PostMailAsync(
            string[] to,
            string[] cc,
            string[] bcc,
            string subject,
            string message,
            string imagePath)
        {
            return Observable.Create<Unit>(observer =>
            {
                var gate = new object();
                var isDisposed = false;
                SocialWorker.PostMail(to, cc, bcc, subject, message, imagePath, result =>
                {
                    lock (gate)
                    {
                        if (isDisposed) return;
                        if (result == SocialWorkerResult.Success)
                        {
                            observer.OnNext(Unit.Default);
                            observer.OnCompleted();
                        }
                        else
                        {
                            observer.OnError(new SocialWorkerException(result));
                        }
                    }
                });
                return Disposable.Create(() =>
                {
                    lock (gate)
                    {
                        isDisposed = true;
                    }
                });
            });
        }

        public static IObservable<Unit> CreateChooserAsync(string message, string imagePath)
        {
            return Observable.Create<Unit>(observer =>
            {
                var gate = new object();
                var isDisposed = false;
                SocialWorker.CreateChooser(message, imagePath, result =>
                {
                    lock (gate)
                    {
                        if (isDisposed) return;
                        if (result == SocialWorkerResult.Success)
                        {
                            observer.OnNext(Unit.Default);
                            observer.OnCompleted();
                        }
                        else
                        {
                            observer.OnError(new SocialWorkerException(result));
                        }
                    }
                });
                return Disposable.Create(() =>
                {
                    lock (gate)
                    {
                        isDisposed = true;
                    }
                });
            });
        }
    }

    public class SocialWorkerException : System.Exception
    {
        private readonly SocialWorkerResult _result;

        public SocialWorkerResult error
        {
            get { return _result; }
        }

        public SocialWorkerException(SocialWorkerResult result)
        {
            _result = result;
        }
    }
}

雑感

だいぶRx使いこなせるようになったけど

  • メソッド名に"Async"とか"AsObservable"とつけるべきか

@toRisouP さんに教えていただきました!ありがとうございます!
↑ 2017/7/6 追記

  • こういうラッパーはSubscribe()されない限り処理を行わないべきか
    • ↑のコードはメソッド呼び出し時にSocialWorkerのメソッドを呼ぶようになってる
    • ↑他のストリームと組み合わせたときに待たないと困る(2017/7/6 追記)
がよくわかりません。主に慣習的な部分? 「一般的にはこうです」というのを知ってる方がいたら是非教えてください。
8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8