SwiftUIのWebViewでFatal error: Unexpectedly found nil while unwrapping an Optional value

SwiftUIでWebView表示しようとしたところエラーが発生。

現象

Xcodeのシミュレーターで日本語を含むURLを読み込むと、以下のエラーが発生して強制的に落ちる。

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

エラーが発生したソースコード

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    let loadUrl: String

    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.load(URLRequest(url: URL(string: loadUrl)!))
    }
}

struct WebView_Previews: PreviewProvider {
    static var previews: some View {
        WebView(loadUrl: "https://example.com/")
    }
}

原因

URLに日本語が含まれていると強制的にnilになってしまうらしい。

対策

URLエンコードを行う。
具体的にはURLに .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! をつけてURLエンコード化する。

実装したソースコード

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    let loadUrl: String

    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        let loadUrlEncoding = loadUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
        uiView.load(URLRequest(url: URL(string: loadUrlEncoding)!))
    }
}

struct WebView_Previews: PreviewProvider {
    static var previews: some View {
        WebView(loadUrl: "https://example.com/")
    }
}

参考

macOSでUSBメモリーに書き込みできない現象

macOS CatalinaでUSBメモリーをマウントすると、読み込み専用になってしまう現象が発生。原因はウイルス対策ソフト側で制御されていたためだった。

現象

Macのディスクユーティリティで「MS-DOS(FAT)」や「Mac OS 拡張」などを選択してフォーマットしたが、「書き込み可能 いいえ」となっていて、なぜか書き込みができない。しかし、lsコマンドで直接権限を確認すると書き込み権限はついている。

原因

違うMacBookでUSBメモリーを取り付けると、ちゃんと書き込みができるため、Mac環境によるものと判明。いろいろ調べた結果、ウイルス対策ソフト側でUSBメモリーへの書き込み禁止の設定をしているためだった。

Mac用のSymantec Endpoint Protectionを利用していて、以下の設定になっていた(USBメモリーなどのデバイスへの書き込み禁止・読み取り専用)。

対応

Symantec Endpoint Protectionで「デバイス制御」をオフにして、USBメモリーを取り出し・取り付けを行うと、無事に書き込みできるようになった。

備考

セキュリティ対策の関係で、Symantec Endpoint Protectionの「デバイス制御」を一時的にオフにして、USBメモリーへの書き込みなどの作業が終わったら、再度オンにすることをおすすめします。
なお、Symantecの設定はUSBメモリーの取り出し・取り付けを行わないとUSBメモリー側に設定が反映されないため要注意。

Gmailの社外メール送信で添付ファイルを削除できず送信ブロックされる件

Gmail(G Suite)のコンプライアンス設定で添付ファイルをスキャンする仕組みがある。そのときに、もし添付ファイルにパスワードがかかっていなかった場合に送信をブロックする設定ができる。

G Suite 添付ファイルに関するコンプライアンス ルールの設定

添付ファイルを意図せず送信しないようにセキュリティ強化ができる一方で、添付画像がどこに挿入されているのかわからず、ハマることも多い。

メール転送時の添付ファイルの削除

添付ファイル付きのメールを転送すると、当然添付ファイルもついたままになっている。
添付ファイルを削除したい場合は、メール本文の一番下に添付ファイルの一覧が表示されるため、そこから「×」ボタンをクリックすると削除することができる。

これは操作方法さえわかれば、そこまでハマらない。

インライン画像の削除方法

たとえば、以下のようにメール本文に画像が挿入(インライン画像)されている場合。

このままメール返信すると、インライン画像も添付ファイル扱いになるため、送信ブロックされてしまう。

方法1:プレーンテキストモード

インライン画像の場合、自動的にHTML形式のメールになってしまうため、テキスト形式のメールに変更すればよい。
方法は、メール返信時に、右下の「︙」から「プレーンテキストモード(Plain text mode)」を選択するだけ。これでインライン画像が削除される。

方法2:強制テキスト化

たまに方法1でも解決されない場合がある。ハッキリとした原因は不明だが、Gmail以外からメール送信された場合(たとえばOffice365経由など)に、発生することがある。

その場合は一旦テキスト帳に貼り付けることで強制的にテキストにすることができる。

STEP1. メール返信を選択して、プレーンテキストモードにする
STEP2. メール全文(本文も返信の引用文も署名もすべて)を全選択して切り取る
STEP3. テキスト帳を起動して、そこに貼り付ける。そして、そのまま全選択してコピーする
STEP4. メール返信欄に貼り付けて、返信する

方法3:メールの新規作成

方法1、方法2でも解決できない場合がある(過去に一度だけ発生)。
その場合は、そのままの状態だとメール返信ができないため、メールを新規作成して返信するしかない。その際に、メールの引用文などもコピーしてはならず、まっさらな状態で要件のみを記載する。
件名だけはメール返信欄からコピーして貼り付けておく。こうすることでメールの続きであることがわかる。
ただし、メール返信の引用がなく、まっさらな状態だと相手先が混乱する可能性があるため、「セキュリティ設定の都合上、メール返信時の引用を削除して送信させていただきます。」と、一言断りを入れておくとよい。

Xcode12のDebug Previewで変数の値参照

Xcode12 betaの状態からprintが効かないという情報あり。

現象

  • Xcode12でDebug Previewモードでprintが出力されない
  • Simulator起動した場合は問題なく出力される

対策

Previewで変数の値を参照したい場合は、Breakpointを追加して値を参照するか、コンソール(poコマンド)から出力する。

左下のウィンドウにオブジェクトの中身が、右下のウィンドウにBreakpointでストップしたあとにLLDBコマンドのpoで変数出力できる

補足

Breakpointで止めた箇所のオブジェクトを[i]アイコンでprint出力できる

参考情報

HUAWEI製 SoftBank 604HW

HUAWEI製の604HW(ソフトバンク回線)がMac(MacBook Pro mid2018 x Catalina v 10.15.6)でインターネット接続ができなくなった。

試したこと(アップデートツール)

アップデートツールをインストールしようとするも、解凍後に.appを起動すると「ファイルが壊れているため開けません」と表示される。
(参考)604HW ソフトウェアアップデートツール(MAC版) | 2020-02-28 | 70.12 MB

HUAWEIに問合せと回答

HUAWEIのチャットサポートに問合せたところ、「端末のソフトウェアが古い可能性があるため、604HWを別の端末につないで更新してみてください」とのこと。

Windows端末に一旦つないでWeb UIにアクセスしてから、604HWのソフトウェアを更新(下図参照)。

そのあとにMacに再度接続したら無事にインターネット通信ができた。

Mac側の604HWアプリが原因とばかり思っていたが、今回は604HW側のソフトウェア(おそらく実際はファームウェアを指していると思われる)が原因だった。

Xcode起動時の「Developer Tools Accessはデバッグを続行するために」ダイアログ

Xcode起動時のダイアログ

XcodeでデバッグモードやPlaygroundを使用すると、再起動後の起動時に毎回ダイアログが表示される。これは_developerグループに所属していないユーザーが起動すると表示されるとのこと。

Developer Tools Accessはデバッグを続行するために別のプロセスを制御する必要があります。
許可するには"developer tools"グループに属するユーザの名前とパスワードを入力してください。

DevToolsSecurity --enable

以下コマンドで解決されるとのコメントを見たが、自分のケースだと解決されず。

$ /usr/sbin/DevToolsSecurity --enable
Developer mode is already enabled.

_developerグループの存在確認

対象ユーザーが_developerグループに所属している必要もあるとのことで、グループが存在するか以下コマンドで確認。

$ dscl . -list /Groups
_amavisd
_analyticsd
_analyticsusers
_appleevents
_applepay
_appowner
_appserveradm
_appserverusr
_appstore
_ard
_assetcache
_astris
_atsserver
_calendar
_captiveagent
_ces
_clamav
_cmiodalassistants
_coreaudiod
_coremediaiod
_ctkd
_cvms
_cvs
_datadetectors
_detachedsig
_devdocs
_developer
_devicemgr
_displaypolicyd
_distnote
_dovenull
_driverkit
_eppc
_findmydevice
_fpsd
_gamecontrollerd
_geod
_guest
_hidd
_iconservices
_installassistant
_installer
_jabber
_keytabusers
_launchservicesd
_lda
_locationd
_lp
_lpadmin
_lpoperator
_mailman
_mbsetupuser
_mcxalr
_mdnsresponder
_mobileasset
_mysql
_nearbyd
_netbios
_netstatistics
_networkd
_nsurlsessiond
_nsurlstoraged
_odchpass
_ondemand
_postdrop
_postfix
_postgres
_qtss
_reportmemoryexception
_sandbox
_screensaver
_scsd
_securityagent
_serialnumberd
_softwareupdate
_spotlight
_sshd
_svn
_taskgated
_teamsserver
_timed
_timezone
_tokend
_trustevaluationagent
_unknown
_update_sharing
_usbmuxd
_uucp
_warmd
_webauthserver
_webdeveloper
_windowserver
_www
_wwwproxy
_xserverdocs
accessibility
admin
authedusers
avdefs
bin
certusers
com.apple.access_disabled
com.apple.access_ftp
com.apple.access_remote_ae
com.apple.access_screensharing
com.apple.access_sessionkey
com.apple.access_ssh
com.apple.sharepoint.group.1
com.apple.sharepoint.group.2
com.apple.sharepoint.group.3
consoleusers
daemon
dialer
everyone
group
interactusers
kmem
localaccounts
mail
netaccounts
netusers
network
nobody
nogroup
operator
owner
procmod
procview
staff
sys
tty
utmp
wheel

dsclコマンドのeDSPermissionErrorエラー

_developerグループに所属させるためのコマンドを実行する。
(本来はsudoが必要だが、以下はなしでも通るか試した結果)

以下<ユーザー名>の箇所は適用したいユーザー名に変更する。

$ dscl . append /Groups/_developer GroupMembership <ユーザー名>
<main> attribute status: eDSPermissionError
<dscl_cmd> DS Error: -14120 (eDSPermissionError)

当然だが、権限の関係でsudoじゃないと適用できなかった。

ルートユーザーの有効化

ルートユーザーを無効化していたため、一時的に有効化する。以下ブログ記事を参考に設定する。

【Mac】sudo をできるようにする。 -ものぐさ日記(仮)

dsclコマンドの再実行

ルートユーザーを適用したユーザーで以下コマンドを実行する。

以下<ユーザー名>の箇所は適用したいユーザー名に変更する。

$ sudo sudo dscl . -append /Groups/_developer GroupMembership <ユーザー名>

無事に通った。

ルートユーザーの再無効化

Macではセキュリティの関係で、ルートユーザーを永続的に有効化するのは推奨していないようなので、ルートユーザーを無効化しておく。

Xcodeの謎エラー対応用ビルドファイル削除コマンド

どう見てもSwiftUIのコードが正しいのにエラーや警告文が表示され、またXcodeを再起動しても治らない場合は、Macだと以下対応で直る場合がある。

1) ビルドファイルの削除

Shift + Command + K

2) Xcodeの再起動

それでも治らない場合はSwiftUIのコードがおかしい可能性があるため、Xcodeで1からProjectを作って(つまり、まっさらなデフォルト状態)、エラーが出ているソースコードを埋め込んでみて検証するとよい。

さくらVPSのスタートアップスクリプトでマインクラフトサーバー構築

マイクラサーバーをさくらVPSで構築して、iOS(iPhone, iPad)でプレイできる環境を構築したときのメモ。

マニュアル

さくらのGaming script:Minecraft Server(統合版) に必要な手順がすべて載っている。ほかにもマニュアルがあったが、これが必要手順をすべて網羅されていた。
# さくらインターネットさんはどれを見てもマニュアルがわかりやすい

初期構築〜オペレータ権限付与

マニュアルをもとに、「オペレータ権限の設定」まで進める。

なお、オペレータ権限の設定の箇所でのハマリポイントは、権限付与するユーザーがマイクラサーバーに接続していないといけない、ということ。

ubuntu@:~$ screen -ls
There is a screen on:
        687.minecraft   (04/19/2020 01:24:15 PM)        (Detached)
1 Socket in /run/screen/S-ubuntu.

screenコマンドでマイクラのセッション名が表示される。
「$ screen -r minecraft」だけで接続できた。

ubuntu@:~$ screen -r minecraft

NO LOG FILE! - setting up server logging...
[2020-04-19 13:24:16 INFO] Starting Server
[2020-04-19 13:24:16 INFO] Version 1.14.60.5
[2020-04-19 13:24:16 INFO] Session ID e35268cf-9718-4153-a8be-14cc4abbc8b8
[2020-04-19 13:24:16 INFO] Level Name: Bedrock level
[2020-04-19 13:24:16 INFO] Game mode: 1 Creative
[2020-04-19 13:24:16 INFO] Difficulty: 1 EASY
[2020-04-19 13:24:16 INFO] opening worlds/Bedrock level/db
[2020-04-19 13:24:18 INFO] IPv4 supported, port: xxxxx
[2020-04-19 13:24:18 INFO] IPv6 not supported
[2020-04-19 13:24:18 INFO] IPv4 supported, port: xxxxx
[2020-04-19 13:24:18 INFO] IPv6 not supported
[2020-04-19 13:24:19 INFO] Server started.
op MyAuthor
No targets matched selector

「MyAuthor」というユーザー名にオペレータ権限を付与したところ、「No targets matched selector」(対象がいません)と表示されてしまった。

「MyAuthor」というユーザーで今回さくらVPSで構築したマイクラサーバーの世界に接続してMap上に放置した状態で再度コマンドを実行。

[2020-04-19 13:25:42 INFO] Player connected: MyAuthor, xuid: xxxxxxxxxxx

op MyAuthor

Opped: MyAuthor

「Opped: MyAuthor」と表示され、無事に権限付与完了。

サバイバル→クリエイティブに設定変更

オペレータ権限のあるMyAuthorユーザーの設定メニューから、ゲームモードを変更するだけ。

その他設定ファイル

さくらVPSのMinecraft Server(統合版)のスタートアップスクリプトで構築すると、「/opt/minecraft/server.properties」にマイクラの設定ファイルが設置される。

中身は以下のような形でゲームモードなど諸々の設定が変更できる。設定変更後は「$ sudo systemctl restart minecraft.service」で反映できる。面倒だったらサーバー再起動の「$ sudo reboot」でも大丈夫。

ubuntu@:~$ cat /opt/minecraft/server.properties

server-name=Dedicated Server
# Used as the server name
# Allowed values: Any string

gamemode=survival
# Sets the game mode for new players.
# Allowed values: "survival", "creative", or "adventure"

difficulty=easy
# Sets the difficulty of the world.
# Allowed values: "peaceful", "easy", "normal", or "hard"

allow-cheats=false
# If true then cheats like commands can be used.
# Allowed values: "true" or "false"

max-players=10
# The maximum number of players that can play on the server.
# Allowed values: Any positive integer

online-mode=true
# If true then all connected players must be authenticated to Xbox Live.
# Clients connecting to remote (non-LAN) servers will always require Xbox Live authentication regardless of this setting.
# If the server accepts connections from the Internet, then it's highly recommended to enable online-mode.
# Allowed values: "true" or "false"

white-list=false
# If true then all connected players must be listed in the separate whitelist.jsonfile.
# Allowed values: "true" or "false"

server-port=19132
# Which IPv4 port the server should listen to.
# Allowed values: Integers in the range [1, 65535]

server-portv6=19133
# Which IPv6 port the server should listen to.
# Allowed values: Integers in the range [1, 65535]

view-distance=32
# The maximum allowed view distance in number of chunks.
# Allowed values: Any positive integer.

tick-distance=4
# The world will be ticked this many chunks away from any player.
# Allowed values: Integers in the range [4, 12]

player-idle-timeout=30
# After a player has idled for this many minutes they will be kicked. If set to 0 then players can idle indefinitely.
# Allowed values: Any non-negative integer.

max-threads=8
# Maximum number of threads the server will try to use. If set to 0 or removed then it will use as many as possible.
# Allowed values: Any positive integer.

level-name=Bedrock level
# Allowed values: Any string

level-seed=
# Use to randomize the world
# Allowed values: Any string

default-player-permission-level=member
# Permission level for new players joining for the first time.
# Allowed values: "visitor", "member", "operator"

texturepack-required=false
# Force clients to use texture packs in the current world
# Allowed values: "true" or "false"

content-log-file-enabled=false
# Enables logging content errors to a file
# Allowed values: "true" or "false"

compression-threshold=1
# Determines the smallest size of raw network payload to compress
# Allowed values: 0-65535

server-authoritative-movement=true
# Enables server authoritative movement. If true, the server will replay local user input on
# the server and send down corrections when the client's position doesn't match the server's.
# Corrections will only happen if correct-player-movement is set to true.

player-movement-score-threshold=20
# The number of incongruent time intervals needed before abnormal behavior is reported.
# Disabled by server-authoritative-movement.

player-movement-distance-threshold=0.3
# The difference between server and client positions that needs to be exceeded before abnormal behavior is detected.
# Disabled by server-authoritative-movement.

player-movement-duration-threshold-in-ms=500
# The duration of time the server and client positions can be out of sync (as defined by player-movement-distance-threshold)
# before the abnormal movement score is incremented. This value is defined in milliseconds.
# Disabled by server-authoritative-movement.

correct-player-movement=false
# If true, the client position will get corrected to the server position if the movement score exceeds the threshold.

世界に接続できない問題

「世界に接続できませんでした」

自前マイクラサーバーに接続して以下メッセージが表示される場合、スマホ側でマイクラを再起動すると直る。

世界に接続できませんでした

挙動を正確に掴めていないが、自前マイクラサーバーの設定変更をした場合に、このエラー表示が出る確率が高いように思える。

「他のデバイスでこの世界を現在プレイしています」

おそらく、ログインセッションがサーバー側に残ってしまっているために発生する現象と思われる。

世界に参加できません。サインインしているアカウントは、他のデバイスでこの世界を現在プレイしています。

マイクラサービスを再起動する必要があるため、サーバーにログインして以下コマンドを打つと直る。

$ sudo systemctl restart minecraft.service

Xcodeで行選択するショートカットの追加設定

AtomやSublime Textみたいに1行選択するショートカットをXcodeにも割り当てる方法。

  1. Xcode起動
  2. Xcodeメニューの Preferences > Key Bindings を開く
  3. Filterと表示された検索窓で「line」と入力
  4. 「Select Line」の右側のショートカットを割り当てる箇所でダブクリックして編集モードにする
  5. 「cmd + L」と入力してEnter

  1. 「cmd + L」が「Go to Line」か「Jump to Line」か、なにかと競合するため、エラーマークが表示される。競合しているショートカットを削除するとエラーマークが消える。