Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

Windows 10のフォトアプリでiPhoneからの画像転送がうまくいかない

f:id:fa11enprince:20200812020709j:plain
iPhoneから写真を転送しようとUSBで繋ぐと、フォトアプリが立ち上がって、
インポートするように促してくるのに、
「問題が発生しました。ファイルがインポートされていない可能性があります。」
とほぼ確実にエラーが出てきます。その対処法を書きます。
詳細のリンクを押してもまるで役に立たないし、リトライすると同じファイルがリネームされてダブってしまいます。
せめて中途半端にインポートした写真を残さずにゴミ箱に入れてくれと思います。エラーも詳細がわかりません(十中八九動画の変換エラーです)。 時期アップデートでこの辺りが治ってくれると嬉しい。

前提条件と結論

おおよそこのバージョンに近ければ状況はほぼ同じだと思います。
私の場合の環境を書いておきます。

OS バージョン
Windows 10 Pro 1903
iOS 13.6

結論を先に書くと対処法1,2がおすすめです。

まるで効果がないガセネタ対処法

  • ケーブルを純正にする
    →関係ありません

対処法1 iPhone側で画像・動画の形式の変換をしないようにする

  • メリット
    フォトアプリがそのまま使えてすべてのエラーが解決するわけではありませんが、9割型成功する方法です。  
  • デメリット
    動画はデフォルトでWindows上ではそのままでは見れない。

画像・動画の形式の変換をしないようにするにはiPhone上で、
設定 > 写真から一番下の元のフォーマットのままを選択する(デフォルトは自動)
f:id:fa11enprince:20200812023937j:plain

これをやってからもう一度インポートするとエラーが出ずに正常終了できるかと思います。
これでも解決しない場合は対処法2か3を試します。

対処法2 Explorerの画像とビデオのインポートを使う

  • メリット
    確実に成功する。どのファイルでエラーが起きたかわかる。リトライが可能。
  • デメリット
    フォルダ分けが通常のフォトアプリの分け方と違う。

ExplorerでiPhoneアイコンで右クリック > 画像とビデオのインポート
f:id:fa11enprince:20200812022718p:plain
あとは「すべての新しい項目のインポート」を選んで「次へ」を押しましょう。
グループ分けができるのですが、奇妙なフォルダわけを行うので1フォルダにまとめてしまうのが良いでしょう。
インポートが実行されてエラーが出るとダイアログが出現するのでスキップするなりしましょう。

対処法3 フォトアプリを使わずiCloudアプリを使う

  • メリット
    従来からある方法で安定している
  • デメリット
    iPhone→クラウド→Windowsとなるし、そもそもiCloudで大きい容量を契約していないと使えない。 さらに、わざわざiCloudアプリを入れないといけないうえにiCloudのアカウントが必要(iPhone使っていたら持っているが)。

対処法4 iTunes経由で同期

  • メリット
    同期はできるが、2020年現時点ではデメリットが大きすぎて使うメリットが皆無。
  • デメリット
    iPhoneにしかないデータが消失する可能性がある(ということが過去にあった。現在は不明)。PCにしかなくてiPhoneにない場合もあり得る。複数デバイス間で同期している場合さらにわけがわからなくなる。そもそも複数デバイス間の同期はシステム的にも難易度が高い。

これはやめたほうが良い。

対処法5 何らかの別アプリで写真を抜き出す

実は書いていてこれが一番いいような気がしてきた…。

参考

投稿日・更新日で古い記事だと強調表示するカスタマイズ

f:id:fa11enprince:20200805232031j:plain

概要

はてなブログの記事毎のページで更新日を表示しつつ、投稿日 or 更新日から1年以上経過していたら
「この記事は投稿・更新されてから一年以上経過しています」と表示します。
更新日ははてなブログ上では表示されないので、自分で書く必要があります。
どこでもいいのですが記事の先頭とかに次のようなHTMLを記述します

<time class="entry-updated updated">2015-01-24</time>

表示例PC1

f:id:fa11enprince:20200805232227p:plain
投稿日の右側に更新日がアイコン付きで表示され、さらに見出し下部に、 「この記事は投稿・更新されてから一年以上経過しています」と表示されています。

表示例PC2

f:id:fa11enprince:20200805232253p:plain
同様です。こちらの例はここに示した方法とは別にCSSで別途調整したほうが良いかもしれません。
スマホの表示例は割愛します。

設定方法

JavaScriptとCSSを各箇所に追加します。

headに要素を追加

設定 > 詳細設定 > headに要素を追加

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<script>
(function(){
  document.addEventListener('DOMContentLoaded', function() {
    var dstr_updated = insertUpdatedDate();
    if (dstr_updated !== '') {
      displayRecentlyNotUpdated(dstr_updated);
    }
  }, false);
  
  function insertUpdatedDate() {
    var entry = document.getElementsByClassName("page-entry");
    if (entry.length >= 1) {  // 記事のみのページで有効
      var entry_date_wrapper = entry[0].getElementsByClassName("date first");
      var dstr_updated = entry[0].getElementsByClassName("entry-updated updated");
      if (entry_date_wrapper.length >= 1 && dstr_updated.length >= 1) {
        entry_date_wrapper[0].appendChild(dstr_updated[0]);
        return dstr_updated[0].innerText;
      }
    }
  }
   
  function displayRecentlyNotUpdated(dstr_updated) {
    var today = new Date();
    // 記事の投稿日時
    var entry_created = document.getElementsByClassName("updated");   // .entry-footer-time > .updated
    var dst_created = entry_created.item(0).getAttribute("datetime");
    var entry_date = new Date(dst_created);
    // 記事の投稿日時に一年を加算する
    entry_date.setFullYear(entry_date.getFullYear() + 1);
    var entry_updated_date = undefined;
    if (dstr_updated != null) {
      entry_updated_date = new Date(dstr_updated);
      // 記事の更新日時に一年を加算する
      entry_updated_date.setFullYear(entry_updated_date.getFullYear() + 1);
    }
    // 記事の投稿日時が記事を開いた日時よりも過去ならメッセージを追加
    if (entry_date <= today) {
      if (entry_updated_date === undefined || entry_updated_date <= today) {
        var doc = document.getElementsByClassName("entry-content").item(0);
        var entry_notice = "<div class=\"entry-notice\">この記事は投稿・更新されてから一年以上経過しています</div>";
        doc.innerHTML =  entry_notice + doc.innerHTML;
      }
    }
  }
})();
</script>

PC

デザイン > カスタマイズ > デザインCSSに下記コードを入れてください。

.entry-content .updated {
    display:none;
}
.page-entry .entry-header .updated {
    display:inline-block;
    font-size: 15px; /* PCのみ */
}
.page-entry .entry-header .updated:before {
    font-family: FontAwesome;
    content: "\f021";
    left: 0;
    top: 0;
    color: #454545;
    padding-left: 20px;
    padding-right: 8px;
}
.entry-notice {
    text-align: right;
    font-size: 80%;
    color: #999;
    background-color: #F0F0FA;
    margin-bottom: 20px;
}

スマホ

レスポンシブ設定の場合は、特に何もしなくて大丈夫です。
レスポンシブ設定でない場合は、デザイン > スマートフォンの記事上に下記コードを入れてください。

<style>
.entry-content .updated {
    display:none;
}
.page-entry .entry-header .updated {
    display:inline-block;
}
.page-entry .entry-header .updated:before {
    font-family: FontAwesome;
    content: "\f021";
    left: 0;
    top: 0;
    color: #454545;
    padding-left: 20px;
    padding-right: 8px;
}
.entry-notice {
    text-align: right;
    font-size: 80%;
    color: #999;
    background-color: #F0F0FA;
    margin-bottom: 20px;
}
</style>

PCとほぼ同じ内容でコピペなのがイケてないですが、無理に共通化するよりましだと思いました。
生成されるHTMLに付与されるクラスが微妙に違ったりするので…。
なお、微妙にスタイルを変えたい場合は適宜CSSを調整してください。

参考

記事の更新日を手動で表示させる:はてなブログ

はてなブログで古い記事にメッセージを表示するスクリプト

CSSとJSがだんだん肥大化してきてえらいこっちゃになってますが、WordPressをメンテするよりましかなとおもいながらメンテしています。
整理も兼ねてこの記事を書きました。

JavaScriptでコールバックで失敗を検知した時にどうやってリトライするか

f:id:fa11enprince:20200729013245j:plain Node.jsの例えばfs.renameのような非同期のメソッドを使っていたときなどに、
リトライしようとして、それをどうやって実現するかという話です。
コールバックだと単純にはうまくいきません。
いろいろ方法はあると思いますが、一例を説明しようと思います。
Node.jsのv12以降なら動くと思います。

サンプルの関数

気軽に実行するには
https://repl.it/
とかのNode.jsに貼り付けて実行してもらえればと思います。
例えば次のような関数があったとします。fsモジュールとかfsExtraモジュールの非同期系メソッドだと思ってください。 同期系はわけあって使いたくないです。
awaitを使うのと同期系のメソッドを単に使うのとでは次のように違いがあります。

asyncというキーワードをメソッドに宣言した上で、awaitというキーワードを使うことで手続き型らしくも非同期的な処理を記述することが出来ます。注意してほしい点としては、あくまでも開発者が同期的に書き下すことができるだけであって、つまりはコンパイラ(インタプリタ)がよしなに非同期に書き換えているということです。 非同期処理を理解する - Sansan Builders Blog

async function dummyMove(src, dst, option, cb) {
    console.log(`src: ${src}`);
    console.log(`dst: ${dst}`);
    console.log(option);
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(cb('error occurred')), 500)
    });
}

なにやら引数を受け取って、500ミリ秒経過後に非同期で必ずエラーを返す関数です。 今回の例ではPromiseを使っているのですが、async functionにしています。
本来はPromiseを返す場合はasyncにする必要がないのですが、特に無害なのでasyncにします。 呼び出し方はこんな感じです。

第一形態

(() => {
    dummyMove("aaa1.txt", "bbb1.txt", { overwrite: true }, (err) => {
        if (err) {
            console.log(`error occurred. src: aaa1.txt, dst: bbb1.txt, error: ${err}`);
        } else {
            console.log(`succeeded. src: aaa1.txt, dst:  bbb1.txt`);
        }
    });
})();

さて、ここでこのdummyMoveを複数回呼び出す必要があります。
しかもわけあって、一つ目が終わったら二つ目というように処理をしないといけません。

第二形態

じゃあ、関数化するか…。で、こいつはコールバックを使ってるからPromiseもしくはasyncにしてやればいいねってなります。

async function moveWithRetry(src, dst) {
    return new Promise((resolve, reject) => {
        dummyMove(src, dst, { overwrite: true }, async (err) => {
            if (err) {
                console.log(`error occurred. src: ${src}, dst: ${dst}, error: ${err}`);
                reject(`failed: src: ${src}, dst: ${dst}, error: ${err}`);
            } else {
                console.log(`succeeded. src: ${src}, dst: ${dst}`);
                resolve(null);
            }
        });
    });
}

(async () => {
    await moveWithRetry("aaa1.txt", "bbb1.txt").catch(() => console.log('e1'));
    await moveWithRetry("aaa2.txt", "bbb2.txt").catch(() => console.log('e2'));
})();

ちなみにですが、さっきのケースとは異なり、
今回のルールでは二つ目は一つ目が終わってからでないとダメというルールがあるのでawaitをつけてあげます。
つけないとどうなるかは外して何度か実行してみるとわかると思います。パラレルに実行される感じになります。
さらに、これだとエラーかどうかにかかわらず、必ず一つ目も二つ目も実行されます。 こう書いた場合、

    try {
        await moveWithRetry("aaa1.txt", "bbb1.txt");
        await moveWithRetry("aaa2.txt", "bbb2.txt");
    } catch(e) {
        console.log('e');
    }

この場合は当然一つ目で失敗すると二つ目は呼ばれません。 どちらが適切かはケースバイケースだと思います。

第三形態

さて、ここで、困ったことが起きました。
なんか知らないけれど、(httpとかの例にすればよかったけれど)たまーに失敗することがあるそうです。
ということでリトライ処理を入れましょう。
ああ、簡単。と思って…同期処理に慣れている人が書くと事故ります(僕です)。 ダメな例

async function moveWithRetry(src, dst, retryCnt = 0, maxRetry = 5) {
    return new Promise((resolve, reject) => {
        console.log(`retryCnt: ${retryCnt} / maxRetry: ${maxRetry}`);
        while (retryCnt < maxRetry) {
            dummyMove(src, dst, { overwrite: true }, async (err) => {
                if (err) {
                    console.log(`error occurred. src: ${src}, dst: ${dst}, error: ${err}`);
                    reject(`failed: src: ${src}, dst: ${dst}, error: ${err}`);
                    retryCnt++;
                } else {
                    console.log(`succeeded. src: ${src}, dst: ${dst}`);
                    resolve(null);
                }
            });
        }
    });
}

(async () => {
    await moveWithRetry("aaa1.txt", "bbb1.txt").catch(() => console.log('e1'));
    await moveWithRetry("aaa2.txt", "bbb2.txt").catch(() => console.log('e2'));
})();

この場合、どうなるかというと、ほぼ無限ループ状態になってしまいます。
というのも、コールバック内でカウントしても、コールバックが呼ばれる前にdummyMoveをものすごい速さで呼ぶので、意図した動きになりません。
ということで、エラーの時はretryCntを超えていなければ、再帰的にmoveWithRetryを呼んであげればいい感じになります。

async function moveWithRetry(src, dst, retryCnt = 0, maxRetry = 5) {
    return new Promise((resolve, reject) => {
        if (retryCnt >= maxRetry) {
            console.log('retryCnt exceeded!');
            reject(`failed: src: ${src}, dst: ${dst}`);
        }
        dummyMove(src, dst, { overwrite: true }, async (err) => {
            if (err) {
                console.log(`error occurred. src: ${src}, dst: ${dst}, error: ${err}`);
                console.log(`retryCnt: ${retryCnt}`);
                if (retryCnt < maxRetry) {
                    console.log('retry!');
                    await moveWithRetry(src, dst, ++retryCnt).catch((e) => reject(e));
                } else {
                    reject(`failed: src: ${src}, dst: ${dst}, error: ${err}`);
                }
            }
            else {
                console.log(`succeeded. src: ${src}, dst: ${dst}`);
                resolve(null);
            }
        });
    });
}

(async () => {
    await moveWithRetry("aaa1.txt", "bbb1.txt").catch(() => console.log('e1'));
    await moveWithRetry("aaa2.txt", "bbb2.txt").catch(() => console.log('e2'));
})();

こうすれば意図通りです。 まぁそんなわけでPromiseを返してくれない旧来のAPIはちょっとこういうことをしようと思うと、妙に苦労します…。

補足

なんかUnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().とか出るんですけどって思って書いたときのコードがコレ。
しかも二つ目が実行されないし。

async function moveWithRetry(src, dst, retryCnt = 0, maxRetry = 5) {
    return new Promise((resolve, reject) => {
        if (retryCnt >= maxRetry) {
            console.log('retryCnt exceeded!');
            reject(`failed: src: ${src}, dst: ${dst}`);
        }
        dummyMove(src, dst, { overwrite: true }, async (err) => {
            if (err) {
                console.log(`error occurred. src: ${src}, dst: ${dst}, error: ${err}`);
                console.log(`retryCnt: ${retryCnt}`);
                if (retryCnt < maxRetry) {
                    console.log('retry!');
                    await moveWithRetry(src, dst, ++retryCnt);
                } else {
                    reject(`failed: src: ${src}, dst: ${dst}, error: ${err}`);
                }
            }
            else {
                console.log(`succeeded. src: ${src}, dst: ${dst}`);
                resolve(null);
            }
        });
    });
}

ひとつ前のコードと比べてもらうとわかりますが、await moveWithRetry(src, dst, ++retryCnt);catchしていません。
なんかエラーがでたら落ち着いてコードを見直しましょう。

参考

https://qiita.com/G-awa/items/652107a9abf7ff6d0d06
https://qiita.com/hey1you1/items/a9b144c94f84cd1d91b8
https://ja.javascript.info/async-await
https://stackoverflow.com/questions/18581483/how-to-do-repeated-requests-until-one-succeeds-without-blocking-in-node
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

C++でオブジェクトを返す関数を書いてもいいのか問題

f:id:fa11enprince:20200722012730j:plain
C++でオブジェクトを返す関数を書いてもいいのか問題→OKです。
遅かったらプロファイル取りましょうで終わりです。

かなり過去にC++でstd::stringをどう返すべきかという記事を書いたこともあり結局いま、例えば、関数内でvectorを加工してその結果を呼び出し側で使いたいニーズがある場合のコードはどう書くのが正解なの? ということを思い至り備忘録として残しておきます。
※話が複雑になるので、例えばsortするときのようにあらかじめあるvectorを加工する場合ではないことを明記しておきます

主にC++11が出る前のように

void foo(std::vector<int>& v) {
  ...(vector書き換え)
}
std::vector<int> vec = { 1, 2, 3 };
foo(vec);

とやるのがいいのか、

std::vector<int> foo() {
  std::vector<int> v = { 1, 2, 3 };
  ...(vector書き換え)
  return v;    // ここが気になる!
}
std::vector<int> vec = foo();

のがいいのかという話です。自信がなかったので調べてみました。

前者だと前時代的な感じだし、引数経由で結果を受け取るっていうのもアレだし、
参照だとそもそも呼び出し側で書き換えてますよってのがよくわかんない…
っていうのもあって微妙感ありますよね。
後者で書ければいいけど、可読性重視したけどコピーが発生して速度低下したら元も子もない。
さらに、後者の場合でstd::moveの必要があるのかどうなのか?ってあたりも気になりました。

結論

ググったらすぐわかることなのですが、 こことか ここに答えが書いてあります。

もはや現代では(あらかじめ何か値があるものを外から受け取って加工するわけでないこのケースでは)オブジェクトを返す関数を書くのが最適解という結論が出てしまいました。

検証コード

www.bit-hive.com
のコードを参考にRVOが効いているかどうか検証しました。

#include <iostream>
#include <vector>

// xにrbpレジスタの値を設定(gcc)
#define CURRENT_RBP(x) \
  __asm__("mov %%rbp, %0;" \
            :"=r"(x) \
          );

// RVOが適用されているかをチェックするマクロ
#define CHECK_RVO(tag, object) \
{ \
  unsigned long rbp; \
  CURRENT_RBP(rbp); \
  unsigned long address = reinterpret_cast<unsigned long>(&object); \
  std::cout << "rbp:     0x" << std::hex << rbp << std::endl; \
  std::cout << "address: 0x" << std::hex << address << std::endl; \
  if (rbp > address) { \
    std::cout << tag << ": RVO isn't applied." << std::endl; \
  } else { \
    std::cout << tag << ": RVO applied." << std::endl; \
  } \
}

class Something {
public:
  int value;
  Something() : value(0) {}
  Something(const Something& obj): value(obj.value) {
    std::cout << "Copy constructor called." << std::endl;
  }
  Something(const Something&& obj) noexcept: value(std::move(obj.value)) {
    std::cout << "Move Constructor called." << std::endl;
  }
};

// 名前付きのオブジェクトを返す関数
Something create_object() {
  Something object;
  CHECK_RVO("object", object);
  object.value = 1;
  return object;
}

// 名前付きのオブジェクトを返す関数 vector
std::vector<Something> create_objects() {
  std::vector<Something> objects;
  //std::vector<Something> objects {Something(), Something(), Something()}; だとコピーになる
  CHECK_RVO("objects", objects); 
  objects.emplace_back(Something());
  objects.emplace_back(Something());
  objects.emplace_back(Something());
  int i = 0;
  for (Something& s : objects) {
    s.value = ++i;
  }
  return objects;
}

int main() {
  Something object1 = create_object();
  std::cout << "Check result" << std::endl;
  std::cout << object1.value << std::endl;
  
  std::cout << "------" << std::endl;
  std::vector<Something> objects = create_objects();
  std::cout << "Check result" << std::endl;
  for (Something& s : objects) {
    std::cout << s.value << std::endl;
  }
}

実行結果

https://wandbox.org/permlink/3SHbmZ1DybX6nXB4

そもそもRVOってどうやってやってるんだという話

上記の検証コードを見ていただけるとわかりますが、
要は関数の戻り先の領域ににあらかじめ値を格納してやれば、
関数が終わってもその値がコピーせずに使える…というものらしいです。

上記のマクロ(CHECK_RVO)でチェックしているところはこんな感じです。
RBP(64bitスタックベースポインタレジスタ)は要は関数の始まりのアドレスです。
スタックはあとのが上に積まれるので(ただし、アドレスは小さい方向に成長していく)、
通常は、

+---------------------------+
|0x7fff1e32bc60 オブジェクト |
+---------------------------+
|0x7fff1e32bc4c 関数 RBP    |
+---------------------------+

となっているのだけれど、

+---------------------------+
|0x7fff1e32bc60 関数 RBP    |
+---------------------------+
|0x7fff1e32bc9c オブジェクト |
+---------------------------+

RVOが効いたときは、このようになっています。
これでコピーしなくてよい!めでたしめでたしとなるわけです。

自然なコードを書いてもよさそう。

例外的なケース

とはいえ、sortのときのように何かを渡して加工する場合を考えると…

std::vector<int> foo(std::vector<int> v) {
  ...(vector書き換え)
  return v;
}
std::vector<int> vec1 = { 1, 2, 3 };
std::vector<int> vec2 = foo(vec1);

としてしまうとセマンティクスはいいものの、引数に渡したときにコピーが発生します。 速度と引き換えにImmutableな関数にしたい場合はこんな感じになっちゃうのかなと。 そのときは引数にconstつけてあげたほうが良いですね。
vectorが巨大な配列だった場合は前者の参照渡しにするしかないのかもしれません。

void foo(std::vector<int>& v) {
  ...(vector書き換え)
}
std::vector<int> vec1 = { 1, 2, 3 };
foo(vec1);

速度を求める場合はこうするしかなさそう。これはほかの言語でも結局こういう書き方になりますね。

この辺の話はここにまとまっていました。 …残念ながらC++を仕事で使うのは当分なさそうですが(T_T)

関連する話題

ふと、ここで、昔からどうするのがいいか悩んでいるところなのだけれど、 下記はJavaですが、
1.参照を更新

private void updateList(List<A> listOfA) {
  listOfA.forEach(item -> { 
    item.setProperty1(findSomething());
  }
}

2.参照を更新したものをreturn

private List<A> updateList(List<A> listOfA) {
  listOfA.forEach(item -> { 
    item.setProperty1(findSomething());
  }

  return listOfA;
}

3.新たなリストをreturn

private List<A> updateList(List<A> listOfA) {
  List<A> newList = new ArrayList<>();
  // Logic to copy listOfA in newList....
  newList.forEach(item -> { 
    item.setProperty1(findSomething());
  }
  return newList ;
}

3は状況に応じて最適ってわかるんですが、問題は1がいいのか2がいいのか… 2が個人的にはよく使っていたのですが、2だとおいおい、渡したやつも書き換わってるのかよ!って突っ込まれそうです。
2のメリットは書き換わっていることが書き方的にわかりやすいのと戻り値に直接メソッドを適用できてメソッドチェーンができるといったところでしょうか。でも無難に1にしようかなと迷うところです。
参考: java - Update parameters of a list in a method: return list or not - Stack Overflow
あーいやいや、ちゃんとオブジェクト指向をしていれば引数にListが渡ってくることはない?っていう気もしなくもない

あとがき

ふと、こんなツイートをみたのが記事を書いたきっかけです。

ちょっとだけ(本当にちょっとだけ)最近どうなってるの?っていうのを見てみたら、何やら色々増えてます。
気になったのが、
値のコピー省略を保証 - cpprefjp C++日本語リファレンス
で、そういえばRVO周りどうなってるんだ?っていうのがそもそもの発端です。