nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

NGUI で UILabel の文字量に従って縦幅だけ変動させるスクリプト

using UnityEngine;
using System.Collections;

/// <summary>
/// UILabel の横幅を固定して text に従った縦幅に設定するスクリプト
/// </summary>
public class UILabelHeightFitter : MonoBehaviour {

    /// <summary>
    /// リサイズ対象の UILabel
    /// </summary>
    public UILabel label;

    private string beforeText = "";

	void Update () {
        // UILabel.text が更新されるたびにリサイズを実行
        if (label.text != beforeText) {
            ResizeHeight();
            beforeText = label.text;
        }
	}

    /// <summary>
    /// UILabel.text の文字量に従って UILabel.height を変更する。
    /// 簡単のため「UILabel.fontSize == 文字の幅 == 文字の高さ」という前提で計算しているので、
    /// 半角全角の混在や可変幅フォントの使用によりずれが生じる場合がある
    /// </summary>
    void ResizeHeight () {
        int line = 1;
        int chara = 0;
        int maxChara = label.width / (label.fontSize + label.spacingX);
        string text = label.text;
        for (int i = 0; i < text.Length; i++) {
            if (text[i] != '\n') {
                chara++;
                if (chara >= maxChara) {
                    chara = 0;
                    line++;
                }
            } else {
                chara = 0;
                line++;
            }
        }
        label.height = (label.fontSize + label.spacingY) * line;
    }
}

NGUI の ScrollView で気持ちのいいスクロールを実装する

気持ちが良いスクロールとは?

  • 今回は「ちょっとスワイプするだけで次の要素にスッと切り替わる」ものを実装する。

バージョン情報

  • Unity 4.6.1f
  • NGUI 3.7.6

ヒエラルキー

UI Root
	ScrollView
		Grid

ScrollView の作成

  • メニューの [NGUI] > [Create] > [Scroll View] で作成

Grid の作成

  • メニューの [NGUI] > [Create] > [Grid] で作成
  • UICenterOnChild をアタッチ

オプション設定

  • UIGrid の Sorting を None 以外にする
    • わからなければ Custom にする
  • UICenterOnChild の NextPageThreshold を 1 にする

動作確認

  • Grid 配下に任意の UIDragScrollView とコライダーがアタッチされたオブジェクトを追加して動作を確認する。

解説

  • UICenterOnChild.NextPageThreshold が 0 より大きく、UIGrid の Sorting が None 以外である時、スワイプした距離が NextPageThreshold より大きければ UICenterOnChild により次あるいは前の要素に切り替わる。

注意点

  • ScrollView をループさせるスクリプトの UIWrapContent が有効であると、この処理は正常に行われなかった。

Rails 4.2 で Heroku にデプロイしたメモ

はじめに

  • Rails 4.2 で開発していたアプリを Heroku にデプロイした時にやったことメモ

環境

Heroku にユーザー登録

Heroku アプリの作成

$ cd /path/to/rails/app
$ heroku create

Heroku 用の gem の追加

$ vi Gemfile
-gem 'sqlite3'
+gem 'sqlite3', :group => [:development, :test]
+gem 'pg', :group => [:production] # heroku で DBMS として PostgreSQL を使用するために必要
+gem 'rails_12factor', group: :production # heroku で Rails 4 を動かすために調整してくれるやつ
$ bundle install --without production

Devise の設定

  • Devise を使っている場合
$ vi config/initializers/devise.rb
config.secret_key = '<%= ENV["DEVISE_SECRET_KEY"] %>' if Rails.env.production? 
heroku config:add DEVISE_SECRET_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

データベースの設定

$ vi config/database.yml
production:
  adapter: postgresql
  encoding: unicode
  pool: 5

シークレットキーの設定

  • シークレットキーを環境変数から読み込むように
$ vi config/secrets.yml
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>                                                                                                                                    
  • .gitignore に config/secrets.yml が登録されている場合は削除する

デプロイ

$ git commit -am 'for heroku'
$ git push heroku master
$ heroku run rake db:migrate

Rails 4.2 で destroy のバリデーションをする

任意の条件でバリデーションをする

  • http://qiita.com/tbaba/items/9ea139dc77443e6d7be2 の通り、before_destroy に指定したメソッド内で条件を判定し、destroy 不可であれば return false する
  • 前記記事の通り before_destroy :method_name の記法ではなく、before_destroy do ... end で宣言すると、return false 時に LocalJumpError の例外が発生して意図したように動作しなくてはまった

関連レコードがある場合は destroy できないように

  • バリデーションの条件として、関連するレコードがあったら destroy 出来なくしたいだけの場合は has_meny のオプションだけで対応できる
models
has_many :associate_name, dependent: :restrict_with_error
# has_many のその他のオプション
# http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
controllers
if @result = @obj.destroy
  # 成功
else
  # 失敗
end

Unity Ads 導入メモ

やったこと

  • Unity Ads のサイトにアカウント登録
  • Unity Ads でアプリの登録とID取得
  • Asset Store から Unity Ads のインポート
  • 広告の呼び出しスクリプトの作成と実行

スクリプト

AdsManager
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;

public class AdsManager : MonoBehaviour {

	void Awake() {
		if (Advertisement.isSupported) {
			Advertisement.allowPrecache = true;
			Advertisement.Initialize (Config.unityAdsId, true);

		} else {
			Debug.Log("Platform not supported");
		}
	}

	public void Show() {
		Advertisement.Show(null, new ShowOptions {
			pause = true,
			resultCallback = result => {
				Debug.Log("広告閲覧終了。広告閲覧報酬を付与するならここで。");
				Debug.Log(result.ToString());
			}
		});
	}
}
Config
using UnityEngine;
using System.Collections;

public class Config {

	#if UNITY_IPHONE
	public static string unityAdsId = "iOSアプリのID";
	#elif UNITY_ANDROID
	public static string unityAdsId = "AndroidアプリのID";
	#endif
}
広告表示
	GameObject.FindObjectOfType<AdsManager>().Show();

MagicalRecord で Date の範囲検索

  • Entity エンティティの creationDate 属性に作成日時が入っているものとして、今日作成されたデータを取得する場合
// 今日の0時0分0秒を取得
NSCalendar* calendar = [NSCalendar currentCalendar];
unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents* components = [calendar components:flags fromDate:[NSDate date]];
NSDate* fromDate = [calendar dateFromComponents:components];

// 明日の0時0分0秒
NSDate* toDate = [fromDate dateByAddingTimeInterval:60*60*24];

// 検索条件の作成と実行
NSPredicate* p = [NSPredicate predicateWithFormat:@"(creationDate >= %@) AND (creationDate < %@)", fromDate, toDate];
Entity* entity = [Entity MR_findFirstWithPredicate:p];