Xcode10.2 (10E125)にしたらcarthageでIncompatible Swift version

carthageはバイナリが準備されていればダウンロードしてビルド短縮しますが
importしたバイナリがXcodeのアップデートで4から5になってしまったので
buildした環境と変わってしまったのでエラーが出てしまいました。


Skipped installing FontAwesome.swift.framework binary due to the error:
	"Incompatible Swift version - framework was built with 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1) and the local version is 5.0 (swiftlang-1001.0.69.5 clang-1001.0.46.3)."

version0.20からはSwiftのバージョンが異なる場合ビルドしてくれるそうなので
Carthageをバージョンアップしました。


brew upgrade carthage

version0.20からはSwiftのバージョンが違ったので「Falling back to building from the source」を勝手に実行してくれました。


** Downloading FontAwesome.swift.framework binary at "Dynamic Type"
***  Skipped installing FontAwesome.swift.framework binary due to the error:
	"Incompatible Swift version - framework was built with 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1) and the local version is 5.0 (swiftlang-1001.0.69.5 clang-1001.0.46.3)."

    Falling back to building from the source

SlimフレームワークでLaravelで有名なEloquentのEvent(self::creating,updating,savingイベント)が動かなかったのを解決できた

EloquentはLaravelでなくても便利なのでORMとしてCodeigniterやSlimで利用してますが
Eloquentのモデルが設定したイベントが呼ばれないので調べてみました。

エラーにはならず、普通にORMとして機能するんですけど、イベントが如何せんよばれない。。


class User extends Model {
public static function boot(){
	parent::boot();
	self::creating(function ($q) {
log出力とかしたい。
	});
	self::updating(function ($q) {
log出力とかしたいのに、イベントが呼ばれない。。
	});
}

$user = User::find(1);
$user->last_login_at = time();
$user->save();

最初slim eloquent event not working,slim eloquent event not callなどで
ググったけど、SlimでEloquentとなるとModelの基本しか見つからないので
vendorの中をちゃんと読むことにしました。

Illuminate\Database\Eloquent\Model.phpを見ると
トレイトにHasEventsってぽいやつがいる。
そして中でイベントが設定されていれば、Dispatcher読んでる。



Model.php

namespace Illuminate\Database\Eloquent;

abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
{
    use Concerns\HasAttributes,
        Concerns\HasEvents,
        Concerns\HasGlobalScopes,
        Concerns\HasRelationships,
        Concerns\HasTimestamps,
        Concerns\HidesAttributes,
        Concerns\GuardsAttributes,
        ForwardsCalls;


HasEvents.php
namespace Illuminate\Database\Eloquent\Concerns;

use Illuminate\Contracts\Events\Dispatcher;

trait HasEvents
{
    /**
     * The event map for the model.
     *
     * Allows for object-based events for native Eloquent events.
     *
     * @var array
     */
    protected $dispatchesEvents = [];
省略
    /**
     * Get the observable event names.
     *
     * @return array
     */
    public function getObservableEvents()
    {
        return array_merge(
            [
                'retrieved', 'creating', 'created', 'updating', 'updated',
                'saving', 'saved', 'restoring', 'restored',
                'deleting', 'deleted', 'forceDeleted',
            ],
            $this->observables
        );
    }
省略
    protected function registerObserver($class)
    {
        $className = $this->resolveObserverClassName($class);

        // When registering a model observer, we will spin through the possible events
        // and determine if this observer has that method. If it does, we will hook
        // it into the model's event system, making it convenient to watch these.
        foreach ($this->getObservableEvents() as $event) {
            if (method_exists($class, $event)) {
                static::registerModelEvent($event, $className.'@'.$event);
            }
        }
    }

イベントディスパッチャーはIlluminate\Contracts\Events\Dispatcherか。
と思いディレクトリを探すと無い。
そこで気づきました。。イベント設定してもDispatcher無いじゃん。
EventってEloquentが持ってるのかよければ依存で持ってきてると思ったけど。。。違うよね。。

今回はSlimを利用していて、下記のようにDBを読んでいます。


// DIC configuration
$container = $app->getContainer();

$container['db'] = function( $c ) {
	$capsule = new \Illuminate\Database\Capsule\Manager;
	$capsule->addConnection( $c['settings']['db'] );
	$capsule->getConnection()->enableQueryLog();
	$capsule->setAsGlobal();
	$capsule->bootEloquent();
	return $capsule;
};

composer.jsonはこんな感じ


"require": {
	"slim/slim": "^3.12",
	"monolog/monolog": "^1.24",
	"danielstjules/stringy": "^3.1",
	"respect/validation": "^1.1",
	"illuminate/database": "^5.5"
},

さっそくイベントライブラリを追加します。


composer require illuminate/container
composer require illuminate/events

そして、コンテナに入れてるDBにも設定を追加します。
最初間違って、setAsGlobalの後にsetEventDispatcherして動かなくて悩みました。。


use Illuminate\Events\Dispatcher as Dispatcher;
use Illuminate\Container\Container as Container;

// DIC configuration
$container = $app->getContainer();

$container['db'] = function( $c ) {
	$capsule = new \Illuminate\Database\Capsule\Manager;
	$capsule->addConnection( $c['settings']['db'] );
	$capsule->setEventDispatcher( new Dispatcher( new Container ) );
	$capsule->getConnection()->enableQueryLog();
	$capsule->setAsGlobal();
	$capsule->bootEloquent();
	return $capsule;
};

これでSlimフレームワークでもEloquentのModelイベントが動くようになりました。

Slim Frameworkでsettingsに追加した設定値が$c->get(‘settings’)でnull

SlimでTwitterAPIやSessionの設定をsettingsに追加しましたが

コンテナに追加する際に、設定値がNullになっていしまう。


$container['twitterOAuth'] = function ($c) {
    $settings = $c->get('settings')['twitter'];
    var_dump( $c->get('settings') );
    exit;

Null

エラーも特に出てないので、Slimがどうやってsettingsを読んでいるか見てみた。

slim/slim/Slim/Collection.php


他はgetterなどなんで、フィルターはない。
public function __construct(array $items = [])
    {
        $this->replace($items);
    }

slim/slim/Slim/Container.php


settingsが空ならEmptyでCollection作るけど
valuesにはあるけど、userSettingsにはない。
public function __construct(array $values = [])
{
       parent::__construct($values);
var_dump( $values ); ある

       $userSettings = isset($values['settings']) ? $values['settings'] : [];

var_dump( $userSettings );  ない

    $this->registerDefaultServices($userSettings);
}
private function registerDefaultServices($userSettings)
{
    $defaultSettings = $this->defaultSettings;

    /**
     * This service MUST return an array or an
     * instance of \ArrayAccess.
     *
     * @return array|\ArrayAccess
     */
    $this['settings'] = function () use ($userSettings, $defaultSettings) {
        return new Collection(array_merge($defaultSettings, $userSettings));
    };

    $defaultProvider = new DefaultServicesProvider();
    $defaultProvider->register($this);
}

なんてことはなく、settings.phpのsettingsの閉じが意図してなかっただけ。。
return ‘settings’ , ‘session’ , ‘twitter’;
になってただけだった。。

settings.php


// Monolog settings
    'logger' => [
        'name' => 'App',
        'path' => __DIR__ . '/logs/app.log',
        'level' => \Monolog\Logger::DEBUG,
        ],
    ], // 多いい。。。。

Android App Bundle (Androidアプリバンドル) -aabからapkを作成してサイズ削減量をチェックしてみる

mobile-ffmpegを組み込んだAndroidアプリをリリースしたけどサイズが大きい。。
full-gplからminにするだけで20MB以上は削減できるけど
それでもAPKファイルは35MB近くある。。

Android App Bundleでリソースファイルだけでも小さくできないか試してみました。

アプリバンドルの作成

Android StudioのビルドからAPKではなく、バンドルを選んで出力するだけ。

アプリバンドルから端末向けのAPK生成

bundletoolをダウンロード

https://github.com/google/bundletool
Bundletool is a tool to manipulate Android App Bundles.
The Android App Bundle is a new format for publishing Android apps in app distribution stores such as Google Play.

”–connected-device”でadbで接続中の端末に向けたApkができるらしい。


 java -jar bundletool-all-0.9.0.jar build-apks \
 --bundle=/ path to /app.aab \
 --output=/ path to /myapp.apks \
 --ks=~/.android/debug.keystore \
 --ks-pass=pass:android \
 --ks-key-alias=androiddebugkey \
 --key-pass=pass:android \
 --connected-device

自分の環境では35MB->30MBだったので効果はあった。

既存のAPK配信アプリをバンドルへ移行

upload_cerとdeployment_certは表示されてるので、ローカルのkeystoreとPEPKで紐づけるのか
PEPKツール(Play Encrypt Private Key)が必要らしいけどダウンロードボタンどこ?。。
あとでにします。

jad(Linux on Intel platform)でNo such file or directoryが出たのでstatically linkedにしたら動いた

https://varaneckas.com/jad/

ubuntuの環境でわかりにくかったエラー
ソースを無くしたので、Classファイルをjavaファイルに戻そうと
jadを実行しようとしたら、”jad: No such file or directory”??


root@doroidpanic-ubuntu:/opt/Jad1.5.8e/jad# jad
-bash: /opt/Jad1.5.8e/jad: No such file or directory
root@doroidpanic-ubuntu:/opt/Jad1.5.8e/#
root@doroidpanic-ubuntu:/opt/Jad1.5.8e/# ls -la
-rwxrwxr-x 1 root root 961596 Aug  6  2001 jad

ダウンロードしたのは
「Jad 1.5.8e for Linux on Intel platform (214917 bytes)」でLinux向けは
「Jad 1.5.8e for Linux (statically linked) (389972 bytes)」もあるけど

take this version if the one above crashes or displays the “seek error” message.

とあるので、.soがないとか言ってなからどうなんだろうと思いながら
(statically linked)に変更したら、動いた。。。


root@doroidpanic-ubuntu:/opt/Jad1.5.8e/jad# jad
Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov (kpdus@yahoo.com).
Usage:    jad [option(s)] 
Options: -a       - generate JVM instructions as comments (annotate)
         -af      - output fully qualified names when annotating
         -b       - generate redundant braces (braces)
         -clear   - clear all prefixes, including the default ones

ちなみにVPSはintelだったのでいいと思ったんだけどな。。


root@doroidpanic-ubuntu:$cat /proc/cpuinfo
vendor_id	: GenuineIntel
cpu family	: 6
model		: 62
model name	: Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz

iOSでAdMob No ad to show.がでるけど追跡型広告を制限をOFFで解決した

iOSでAdMobを設定してリリース前にTestDeviceID設定してないiPhoneでバナーなどが表示されないことがよくある。
AdmobのAppIDとコードはあってるけど
こんなエラー。。


Banner error Request Error: No ad to show.

コード作成してすぐはNGとか0ptの枠に表示してるとかStackOverflowにはあるけど
自分の場合は、iOS側のプライバシー設定の「追跡型広告を制限」をOFFにすると広告が表示される。
ということはたまたま金額などの関係で追尾広告だけが配信されてるってことなのかな?

EXC_BAD_ACCESSが出たけど、よく見たら凡ミスだった

EXC_BAD_ACCESSはlogに書き込むデータを取得しているところだった
さっきまで動いてたんだけどな。。


formatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
return formatter.string(from: date)

let fileName = filePath.components(separatedBy: "/").last

と思ったら、SwiftBeaverから切り替えたときについでにprint()がプロジェクトにところどころ残ってたので調子に乗ってLoggerに置き換えしたら、logger自身のアウトプットのprintもloggerメソッドに切り替えたので無限ループしてEXC_BAD_ACCESSでした。

UIStackViewはsetBackgroundColorで背景色変更が出来なかった

背景を変えようとsetBackgroundColorしたけど
エラーは出ないけど、UIStackViewってsetBackgroundColorでは色変わらないらしい。


こんな感じではダメだった。XCodeサジェストだすなよ。。
UIStackView.setBackgroundColor( UI.Color )

how to change the background color of UIStackView?
https://stackoverflow.com/questions/34868344/how-to-change-the-background-color-of-uistackview