学生iOSエンジニア日記

iOSエンジニアの大学生(20)が思ったことをアプトプットします。コメント等でフィードバックをお願いします。

Mashup Camp for Student優勝しました!

この土日で、Mashup Awards 9のスピンオフ企画である、Mashup Camp for Studentに参加してきました!

実は、先日のTechCrunchハッカソンにらも参加してたのですが、なかなか思うようなプロダクトが作れなかったので今回はガチで行こうって思ってました。

作ったのは以前から構想していた、Twilioという電話APIを使って、リアルタイムのグルメ店予約サービス「YoyakuNow」です。
使い方としては、まず周辺のお店を位置情報と条件から抽出して、その中から行きたい店を第5候補まで複数選択します。そして、予約確認ボタンを押すとTwilioが優先度順に自動で店に発信し、自動音声で条件通り予約できるかを確認し、成立した店舗をユーザーにプッシュ通知してくれます。
発展性としては、Facebookと連携して自分のお気に入りの店に友達が予約したら教えてくれたり、ユーザーの情報に合わせて趣向が合う且つ空席ありの店をリコメンドするようなことを考えてます。

f:id:SonyGulss:20131117213527j:plainf:id:SonyGulss:20131117213538j:plain

本流の方で最優秀賞をとった、「1Click飲み」と似たサービスですが、こちらは実用性を重視して作られています。
アルゴリズムだと怖くて使えなかったり、良い店をリコメンドできないなどの問題をなくしています。集まるデータベースもより有益で発展性があると思っています。

ハッカソン自体の感想としては、学生でもこんなにエンジニアやデザイナーがいるんだなーって思いました。
探しても見つからなかったんですけど、集まるとこには集まるんですね。
あと、自分たちでひっそりやるより開発速度が倍速になりました。周りもやっている環境だとモチベーションも上がりますね。

審査員の方々にも評価していただいたのは、とても嬉しいものでした。サービスを作っていると本当に使ってくれるか不安になりますが、こういうのは励みになります。

しかし、まだ市場からの評価を得たわけじゃないので、それまでは慢心せず謙虚でいなければだめだと思ってます。

YoyakuNowはまだ公開されていませんが、近日公開予定なので是非使って見てください!
みなさんお疲れ様でした!

f:id:SonyGulss:20131117214506j:plain



※開発中サービス、オウンドメディア

http://blog.cloudrestaurant.jp

今最も革新的な3つのテクノロジー、Google Car、3Dプリンター、そしてBitcoin

今最も革新的な技術である「Googleカー3DプリンターBitcoin」についてのWashington Timesの記事を和訳しました。

 いつの日も、自由市場は私たちに新しく素晴らしいものを提供してくれます。携帯電話、PC、飛行機、バイク、蒸気機関、Movable Typeなど遡ればきりがありません。創造的な個人が便利でそして有益な何かを日常にあえて届けてくれるのです。

 過去数年間で私たちはiPad、アプリ市場、電気自動車、その他多くのものを得ました。この中でも3つの発明が際立ちます。Googleカー3Dプリンター、そしてBitcoinです。

 

Google無人自動車

 まずはGoogleの無人自動車です。これまでの数年間Googleチームは”自立的運転計画”に取り組んできました。目的は車の中の運転手を必要とせず自分で運転するような車を提供することです。この技術により駐車できないときや飲み過ぎたときに車を自宅に送ってもらうことができます。

 プロジェクトマネージャーAnthony Levandowskiによると、この車は3~5年で提供することができるはずです。「来年Googleカーをガレージに置くことは出来ないが、我々はあと5年このテクノロジーを世に出すことを望んでいる。」と彼は言います。「どのような形でリリースされるかはまだ決定していませんが。」

 もちろん、そのタイムラインは政府が技術をどの程度規制するかに強く影響されます。明らかにどの政府もこの時点で無人自動車を認めることはないでしょう。そして、政府はいつもとろいペースで動くので、必要のない標準規格を作るのに甘ったるい時間を費やすことは想像できます。


Self-Driving Car Test: Steve Mahan - YouTube

3Dプリンター

 次は、3Dプリンターです。”加算的製造技術”として知られ、一度に小さな素材の層を足し合わせて行くことでものを作って行きます。”加算的”とは、従来ののこぎり、ドリル、切断などのような”減算的”プロセスとは対極にあります。

 デジタルのファイルのように、ダウンロード可能なデザインモデルによって印刷され、世界のどこにいてもインターネットを通して送ることができます。

 最近では、3Dプリンターの値段は顕著に低下していて、実験的な使用を可能にしています。テクノロジーを限界まで押し進めるエンジニアJim Korは、3Dプリンターで車を作ることに成功しました。半分の重さでスチールと同じ程度の強度を持っていて、Korのデザインでは形状や材料組成を維持して燃費を最大化することができています。

 ヘッドライト、ウィンカー、安全装置などの従来の車に搭載されている必須の要素も持つようになりますが、これは重量の関係でオートバイとして登録されるでしょう。政府の馬鹿げた規制と監視から逃れるのが目的です。

 3Dプリント技術は個人が銃を製造するためにも使われています。個人的使用で売ったりしない場合は合衆国政府の監視の外であるため、現状および潜在的な銃規制措置を迂回する手段となっています。


[よく分かるIT]「3Dプリンター」で簡単に造形 - YouTube

Bitcoin

 最後は、Bitocoin。2008年に”中本哲史”と呼ばれる男によって創られ、Bitcoinは史上初めての現実の持続的な通貨としての用件を満たす電子通貨となりました。珍しいことに、ただ一つの実体ではなくすべての人によってコントロールされるオープンソースです。暗号化されていてハックするのは到底困難です。個々人が所有し、ピラミット構造のスキームになる可能性を排除しています。

 この新しいイノベーションの技術的な点を把握するのは難しいが、現実世界ではそんなことはありません。数セントの取引は、現在それが行われると1コイン100ドル以上の価値があります。Bitcoinは増大し続けているデジタル市場のなかで使用することができます。近いうちに、すべてのオンラインストアで仮想的に使える決済の選択肢の一つになるでしょう。

 Bitcoinについて最も注目すべきことは、国家の介入から完全に自由になることができることです。今日私たちが世界のどこでも見るような、通貨の供給量をコントロールするような人物や組織はだれもいません。数十年前にインターネットやEメールがしたように、紙幣や金の代替として、Bitcoinは全く新しい世界を解放するでしょう。

 経済の専門家のJeffrey TuckerがBitcoinについて語りました。「お金の革新は、お金と国家の間の完全な分離につながり、国家がお金をコントロールできなければ、何もコントロールできないのに等しいのです。私は国家がそれに気づいていないと思っています。」彼は続けます、「事実、彼らに取って脅威であるのに、考えることさえできていませんし、彼らが止めるために出来ることは何もないのです。もしBitcoinが条件を満たしているのであれば、それは世界を変えることができるのです。

 Bitcoinは存在を保証した通貨ではないかもしれません。それでもやはり、Bitcoinは議論の余地もなくデジタル通貨が世界に君臨する未来の前兆です。Bitcoin自体は”一時的なブーム”または”バブル”かもしれませんが、デジタル通貨というアイデアとその有益さはそんなものではないのです。

 もし政府がお金をコントロールしなければ、議会の債務を買うための連邦準備制度理事会は必要なくなります。結果として、私たちが知る戦争、私たちが知る福祉制度、私たちが知る政府というものはなくなるでしょう。

 そして、それは素晴らしい世界になるでしょう。


ビットコインとは?(Bitcoinの説明) - YouTube


マイク•マロニー ビットコインを語る [吹き替え] - YouTube

 いつだって政府は愚かなことをし、正常に機能している自由市場を妨げる馬鹿げた法律を制定します。一方で、いつだって起業家、イノベーターそしてクリエイターは、人々が感じる問題点を解決して光の道を探しています。Googleの無人自動車、3Dプリンター、そしてBitcoinは正常に機能している自由市場が生んだ3つの素晴らしい最近の事例なのです。

URLから画像を非同期に読み込む3種類の実装

URLから画像を生成するときは、普通に実装すると以下のようになります。

NSURL *url = [NSURL URLWithString:@"画像のURL"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];

しかし、この実装だとシングルスレッドで読み込むので、その間他の処理が止まり固まったように見えてしまいます。 なので、画像は非同期に読み込むことが必要になります。今回は非同期での画像読み込みの実装を3種類してみました。 3つの実装をまとめたソースコードは、こちらからダウンロードしてください。

  1. 一度読み込んだ画像をキャッシュしない。(UITableViewCellの画像)
  2. 一度読み込んだ画像をキャッシュして、再び読み込まない。(UITableViewCellの画像)
  3. UIImageViewのインスタンスに読み込み処理を任せて、それぞれで読み込む。(UIImageView)

1. 一度読み込んだ画像をキャッシュしない。

参考URL: ネット上の画像を表示させた UITableView をぬるぬる動作させる方法

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    
    // この部分が重要
    dispatch_queue_t q_global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t q_main = dispatch_get_main_queue();
    cell.imageView.image = nil;
    dispatch_async(q_global, ^{
        NSString *imageURL = @"http://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Apple_Computer_Logo_rainbow.svg/150px-Apple_Computer_Logo_rainbow.svg.png";
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL: [NSURL URLWithString: imageURL]]];
        
        dispatch_async(q_main, ^{
            cell.imageView.image = image;
            [cell layoutSubviews];
        });
    });
    
    return cell;
}

2. 一度読み込んだ画像をキャッシュして、再び読み込まない。

参考URL: UITableViewの要素を非同期に設定する

以下のクラスを組み込んで下さい。

  • Downloader.h (非ARC)
  • Downloader.m (非ARC)
#import "Downloader.h"

@interface CacheAsyncTableController : UITableViewController

@property (nonatomic, strong) NSMutableDictionary *imageCache;
@property (nonatomic, strong) NSMutableDictionary *downloaderManager;

@end
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 非同期表示・キャッシュ用の配列の初期化
    self.imageCache = [NSMutableDictionary dictionary];
    self.downloaderManager = [NSMutableDictionary dictionary];
}

***(略)***

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    
    if ([_imageCache objectForKey:indexPath]) {
        // すでにキャッシュしてある場合
        cell.imageView.image = [_imageCache objectForKey:indexPath];
    } else {
        if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
        {
            // キャッシュがない場合、読み込む
            [self startIconDownload:indexPath];
        }
    }
    
    return cell;
}


***(略)***

// 以下のメソッドを実装する(ソースコード参照)
- (void)startIconDownload:(NSIndexPath *)indexPath;
- (void)loadImagesForOnscreenRows;
- (void)downloader:(NSURLConnection *)conn didLoad:(NSMutableData *)data identifier:(id)identifier;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

3. UIImageViewのインスタンスに読み込み処理を任せて、それぞれで読み込む。

参考URL: 非同期通信で画像をロードする方法について

以下のクラスを組み込んで下さい。

  • AsyncImageView.h
  • AsyncImageView.m

UIImageViewを生成するところで、以下のように書きます。

AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
NSString *imageURL = @"http://upload.wikimedia.org/wikipedia/commons/a/a5/Apple_gray_logo.png";
[imageView loadImage:imageURL]; // 画像を非同期で読み込む

※開発中サービス、オウンドメディア http://blog.cloudrestaurant.jp

iOS7搭載「iBeacon」が作る新しい位置情報の世界

 iOS7とiPhone5sがリリースされてからしばらくが立ち、iOS7のシェアが72時間でiOS6を上回るという人気ぶりです。アプリ開発者としては、大きくUIの変わったiOS7アプリを作るのは手間が増えて大変なのですが、ユーザーとしたら新機能満載のiOS7は魅力的であり、必然的に専用のアプリを望んでいるのでしょう。

 iOS7から搭載された新機能はいくつかあり、以前から待ち望まれていたものから全く新しいものまで様々です。

 その中でも、私が注目しているのは「AirDrop」です。さらに言えばAirDropで使われている「iBeacon」という技術です。iBeaconとはこの記事で紹介されているように、6月のWWDCでひっそりと発表された隠れキラーコンテンツです。

iBeaconは、新興企業Estimote社が開発したBeaconという名のセンサーを利用した近距離無線通信技術です。

 iBeaconの使い方を紹介した動画がこちら。店内にスタイリッシュなデザインが施されたiBeaconを配置することで店内での顧客の正確な位置情報を把握し、スマートフォンに情報を映すことで全く新しいショッピング体験を実現しています。

 Estimote社は、シリコンバレーのあのY Combinator出身のスタートアップで、TechCrunch Disrupt SF 2013のハードウェア部門優勝者です。TechCrunchのインタビューの中で以下のように語っています。

 製品は岩石のような形をしたBluetooth Low Energyを使用するデバイスで、例えば小売店が客のいる列に応じてバーゲン情報を送ったり、スマートフォンから支払いトークンを送り、レジでタップするあるいはレジに近づくだけで支払いを済ませるなどといったことが可能になる。 (略)

 同社は、iBeaconを活用する様々な種類のハードウェアを作る計画だ。例えば放置されたショッピングカートの追跡なども、リアル店鋪にとって現実的な可能性になる。 (略)

 小売店は、客がどれだけの時間試着室にいたかを知ることができるため、例えば、20分間試した後それを買わずに店を出たことがわかる。この後その商品専用のクーポンを発行して客をフォローアップすることによって、これまででは不可能だったプロモーションが可能になる。

 また、こちらは別のインタビュー動画です。「なぜローエナジーのBluetooth通信が重要なのか」、「NFCQRコードはiBeaconによって不要になる」などを説明しています。

 私の予想ではこのiBeaconが取得するローカルでの正確な位置情報は、Google GlassTelepathy Oneに代表されるウェアラブルデバイスが普及してから、さらに重要度が増すはずです。 このGlassのイメージ動画での1:03からは、もはや先ほどのiBeaconの紹介動画と同じ体験です。

 Estimote社はこれからも成長を続けるでしょう。そして、今は夢のようなこのユーザー体験もあと数年で当たり前になると思っています。

※開発中サービス、オウンドメディア http://blog.cloudrestaurant.jp

ウェブページをキャッシュで保存してオフライン閲覧するためのシンプルな実装

 UIWebViewで読み込んだウェブページをキャッシュ(Cache)で保存して、オフラインで閲覧するための実装です。今回は、あとで読む機能を搭載する「Pocket」などのアプリように、テキストデータのみを抽出して保存するのではなく、テキスト・画像・サイドバーなどのすべてのページの状態を記録する手法をとります。つまり、見たページをそのまんま保存するということです。

 こちらがサンプルコードです。

 ページキャッシュの実装方法は基本的に、こちらの記事「Drop-in offline caching for UIWebView (and NSURLProtocol)」を参考にしています。ちなみに、プログレスバーの実装はこちらの記事「UIWebViewにプログレスバーを出すためのモジュールを作りました」を参考にしました。

(1) 必要なファイル・プレームワーク

  • Reachability.h
  • Reachability.m
  • RNCachingURLProtocol.h
  • RNCachingURLProtocol.m
  • SystemConfiguration.framework(フレームワーク

(2) 実装

 「RNCachingURLProtocol」は、ネットワークのプロトコルをカスタムしています。「AppDelegate.m」でこのプロトコルを以下のように設定してしまいます。すると、どこでNSURLConnectionを使っても、このプロトコルに従って動くようになります。少し工夫するとプロトコルを、通常と「RNCachingURLProtocol」のモードを切り替えるように実装することもできると思います。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // プロトコルの設定
    [NSURLProtocol registerClass:[RNCachingURLProtocol class]];

    .
    .
    .
}

 このプロトコルの挙動は、

  • 初めての読み込みのときは普通にロードする。
  • 一度読み込みが完了した場合、それをキャッシュディレクトリに保存する。
  • 次読み込んだときに、すでにキャッシュが保存されていればそれをUIWebViewに表示する。

となっています。

 あとは、通常と同じようにUIWebViewでページを読み込めばこのプロトコルに従って読み込みが開始されます。

- (void)reloadWebView 
{
    [self.webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:_urlString]]];
}

(3) もっとできそうなこと

  • 記事全体を保存するのではなく、テキストだけを抽出する機能
  • ページに含まれる画像だけを抽出して保存する機能
  • 保存した記事の情報をユーザーが管理する機能(delegateメソッドなどの実装?)
  • 読み込んだページだけでなく、それに含まれるリンク階層の部分も含めて保存する機能

※ 参考記事: ネットワーク接続が3GかWifiか圏外かを調べる簡単な方法 - YoheiM .NET

※開発中サービス、オウンドメディア http://blog.cloudrestaurant.jp

よく使うアイコン画像を「Font-Awesome」を使って生成する方法

 iOSアプリの開発では、UITabBar、UIButtonなどいろいろなところでそのボタンの役割を表すためのアイコン画像が使われます。 SNS固有のアイコンや、一般的なアイコンなどさまざまなものがありますが、「Font-Awesome」は、その中でよく使われるアイコンを集めたものです。

 iOSでは「FontAwesomeKit」というライブラリを使えばFont-AwesomeのアイコンをUIImageとして生成して簡単に使うことできます。 以下はその実装方法を紹介します。具体的な実装は、GitHubで公開されているサンプルコードを参考にしてください。

(1) 環境(Requirements)

  • Xcode 4.5 +
  • iOS 5.0 +
  • ARC enabled
  • CoreText framework(CocoaPodsを使うと自動で追加されます)

(2) 必要なファイル

  • FontAwesome.otf
  • FontAwesomeKit.h
  • FontAwesomeKit.m

(CocoaPodsを使う場合)

「Podfile」

pod 'FontAwesomeKit'

を追加し、ターミナルから

pod update

を実行する。これで、(1)と(2)をしたのと同様に、実装する準備はすべて完了します。

(3) 実装

まず、アイコン画像を生成するクラス内でFontAwesomeKitをインポートしておきます。

#import "FontAwesomeKit.h"

これで自由にFont-Awesomeのアイコンを生成することができます。 例えば、星のアイコンを生成して、タブのアイコンに設定する場合は以下のようになります。

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    // タブのタイトル
    self.tabBarItem.title = @"Icon Cheat Sheet";
    // アイコン画像を生成
    UIImage *tabbarIcon = [FontAwesomeKit imageForIcon:FAKIconStar
                                             imageSize:FAKImageSizeTabbar
                                              fontSize:29
                                            attributes:nil];
    // タブのアイコンとして設定
    self.tabBarItem.image = tabbarIcon;
}

星のアイコンは生成時に、"imageForIcon"の部分を"FAKIconStar"で設定していますが、この部分を変えることでいろいろなアイコンを生成できます。マクロの定義は「FontAwesomeKit.h」で以下のように定義されているので参照して下さい。

// generated marcos
#define FAKIconGlass @"\uf000"
#define FAKIconMusic @"\uf001"
#define FAKIconSearch @"\uf002"
#define FAKIconEnvelopeAlt @"\uf003"
#define FAKIconHeart @"\uf004"
#define FAKIconStar @"\uf005"
#define FAKIconStarEmpty @"\uf006"
#define FAKIconUser @"\uf007"
#define FAKIconFilm @"\uf008"
#define FAKIconThLarge @"\uf009"
#define FAKIconTh @"\uf00a"
.
.
.

アイコンの種類を見た目で確認したいときは、こちらが見やすいです。

(4) もっとカスタムしたい人

もっとアイコンをカスタムしたい場合は、attributesの部分を変えます。色や影の具合を調整することができます。以下その一例です。

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    // タブのタイトル
    self.tabBarItem.title = @"Icon Cheat Sheet";
    
    // 陰のattributes
    NSDictionary *shadowAttr = @{FAKShadowAttributeColor : [UIColor grayColor],
                                 FAKShadowAttributeOffset : [NSValue valueWithCGSize:CGSizeMake(0.0f, 1.0f)],
                                 FAKShadowAttributeBlur : [NSNumber numberWithFloat:1.0f]};
    // 非選択時のattributes
    NSDictionary *unselectedIconAttrs = @{FAKImageAttributeForegroundColor : [UIColor lightGrayColor],
                                          FAKImageAttributeBackgroundColor : [UIColor clearColor],
                                          FAKImageAttributeShadow : shadowAttr};
    // 選択時のattributes
    NSMutableDictionary *selectedIconAttrs = unselectedIconAttrs.mutableCopy;
    selectedIconAttrs[FAKImageAttributeForegroundColor] = [UIColor colorWithRed:0.3 green:0.3 blue:1 alpha:1];
    
    
    // 非選択時のアイコン画像
    UIImage *unselectedIconImage = [FontAwesomeKit imageForIcon:FAKIconStar
                                                       imageSize:FAKImageSizeTabbar
                                                        fontSize:29
                                                      attributes:unselectedIconAttrs];
    // 選択時のアイコン画像
    UIImage *selectedIconImage = [FontAwesomeKit imageForIcon:FAKIconStar
                                                       imageSize:FAKImageSizeTabbar
                                                        fontSize:29
                                                      attributes:selectedIconAttrs];
    
    // タブの画像を、非選択時と選択時で別々に設定
    [self.tabBarItem setFinishedSelectedImage:selectedIconImage
                  withFinishedUnselectedImage:unselectedIconImage];
}

以上です。これでアイコン画像をどっかから拾ってくる徒労から解放されることでしょう!

※開発中サービス、オウンドメディア http://blog.cloudrestaurant.jp

読み込み時のLoadingViewのシンプルな実装

ほとんどの場合、何らかのデータ読み込んで処理に時間がかかる場合、ユーザーにそのことを伝えておくとストレスが軽減されるため、多くのアプリでカスタマイズされたLoadingViewを表示しています。 標準的でシンプルなLoadingViewは以下の手順で簡単に実装できます。

また、非常に単純な実装にしてあるので、自分でいじってさらにリッチにカスタマイズすることも可能です。

サンプルプロジェクトはこちらからダウンロードしてください。

必要なファイル

  • LoadingView.h
  • LoadingView.m

LoadigViewの初期化

インスタンス変数を定義

@interface ViewController ()
{   
    LoadingView *loadingView;           // 標準
    LoadingView *loadingViewWithTitle;  // カスタム
}
@end

初期化(標準とカスタムの2つ)

// デフォルトテキストで初期化
loadingView = [[LoadingView alloc] init];
loadingView.center = CGPointMake(self.view.center.x, self.view.center.y-40);
[self.view addSubview:loadingView];
    
// カスタムテキストで初期化
loadingViewWithTitle = [[LoadingView alloc] initWithTitle:@"処理中..."];
loadingViewWithTitle.center = CGPointMake(self.view.center.x, self.view.center.y-40);
[self.view addSubview:loadingViewWithTitle];
// 色をカスタム
loadingViewWithTitle.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.7];

表示・非表示の切り替え

// 表示
[loadingView show];
// 非表示
[loadingView hide];

※ 表示・非表示時には拡大縮小のアニメーションにより、ユーザーにとって何をしているかわかりやすいUXになっています。

もっとかっこよく作りたい人

この記事が参考になります。

オリジナルの「loadingView」をサクッとつくるために「SVProgressHUD」をforkしてみた。

※開発中サービス、オウンドメディア http://blog.cloudrestaurant.jp