ビギグラマーのノート

自作PCやプログラミングについてのブログです。

MacのBluetoothイヤホンが異常に音質が悪い

 状況

 普段はiPhoneに接続して使っているこのPowerbeats3をMacに繋いで作業しようとしていた時のことでした。なんだこれ 異常に音質が悪い。言葉で表現するなら膜で隔たれた ぼやけた感じになっていました。

f:id:BegiGrammer:20180520101637p:plain

 

問題の把握

 このぼやけ具合は昔ハンズフリーを使った時の感じと似ています。そこでBluetoothの送信方式(コーデック)を確認します。コーデックはBluetoothを接続した状態で Optionキーを押しながら上に出ているバーのBluetoothボタンをクリックします。

f:id:BegiGrammer:20180526210633p:plain

 有効なコーデックがSCOになっていたらハンズフリーイヤホンとしてMacに接続されています。 

解決法

 ハンズフリーのコーデックから音楽鑑賞用のAACに戻すためにはイヤホンとして接続されているものを変えればいいのです。

 具体的には 設定 -> サウンド -> 入力 の「サウンドを入力する装置を選択」で内臓マイクに入力を切り替えます。

f:id:BegiGrammer:20180520103243p:plain

 あなたが音楽鑑賞をしつつこの設定をいじった場合一度音が途切れクリアな音に生まれ変わったのが確認できるでしょう。ここでもう一度Bluetoothのコーデックを確認して見ましょう。確認方法は上のバーのBluetoothボタンを Optionキーを押しながらクリックします。

f:id:BegiGrammer:20180526210711p:plain

 無事AACに切り替わったでしょうか。

参考

 Airpods codec stuck on SCO via Macbook Pro

 

【Swift 4】NSAttributedString ⇆ HTML の変換とUITextViewへの表示

 やりたいこと

 NSAttributedStringとUITextViewを使えばリッチなテキスト表現ができることはご存知かと思います。今回、なんらかのデータファイルからUITextViewへ表示し編集、それを保存する必要があったのでどうにかしようと思ったのです。

How to do

HTML → NSAttributedString

 let html = "<html>ほにゃらら〜</html>"

        

let encoded = html.data(using: String.Encoding.utf8)!

let attributedOptions : [NSAttributedString.DocumentReadingOptionKey : Any] = [

            .documentType : NSAttributedString.DocumentType.html,

]

let attributedTxt = try! NSAttributedString(data: encoded,

                                                              options: attributedOptions,

                                                              documentAttributes: nil)

textView.attributedText = attributedTxt

 tryを使っているので実装ではdo-catchが必須になります。

f:id:BegiGrammer:20180315033947p:plain

NSAttributedString → HTML

let attT = textView.attributedText!

let documentAttributes = [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.html]

let htmlData = try! attT.data(from: NSRange(location: 0, length: attT.length),

                                          documentAttributes: documentAttributes)

let html = String(data: htmlData, encoding: .utf8)

print(html ?? "Empty")

結果

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<meta http-equiv="Content-Style-Type" content="text/css">

<title></title>

<meta name="Generator" content="Cocoa HTML Writer">

<style type="text/css">

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 25.0px '.SF UI Display'; color: #e60012}

p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.SF UI Text'}

p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px '.SF UI Text'; color: #009944}

span.s1 {font-family: '.SFUIDisplay'; font-weight: normal; font-style: normal; font-size: 25.00pt}

span.s2 {font-family: '.SFUIText'; font-weight: normal; font-style: normal; font-size: 12.00pt}

span.s3 {font-family: '.SFUIText'; font-weight: normal; font-style: normal; font-size: 10.00pt}

</style>

</head>

<body>

<p class="p1"><span class="s1">Tomato</span></p>

<p class="p2"><span class="s2">English</span></p>

<p class="p3"><span class="s3">Royal blueberry blue and white.<span class="Apple-converted-space"> </span></span></p>

</body>

</html>

ご丁寧に全文描いてくれいています。

愚痴

 File → NSAttributedString → UITextView(編集) → なんらかのData → File

 こういうことをやりたいが為にこの一週間XMLでフォントスタイルを定義しそれを解読する奴を必死に作っていましたが、ひょんなことでこのような楽な方法を見つけてしまいました。わだじの いっじゅうかん かえじで!

参考

stackoverflow.com

stackoverflow.com

追記 2018/05/13

 上記のコードは変換する度にフォントサイズが大きくなって行きます。原因はスタイルシートのフォントサイズを指定する単位のptからpxへの変換の際にズレが生じているためです。なのでHTMLを出力する際にptをpxへreplaceする正規表現のパッチをつけて見ました。

 追記のためコードは下に移動 

 上記の出力されたHTMLを見てもらうとわかるのですがpタグのスタイルとspanタグのスタイルのフォントサイズの指定は数字こそ同じですが単位がpxとptになっています。このせいでNSAttributedString ⇄ HTMLと変換する度にサイズが大きくなっていってしまうのです。なので上記のコードではNSAttributedStringからHTMLへ出力された際にptをpxに単純に置き換えています。同様にHTMLからの変換の際にもスタイルシートのptをpxに置き換えています。なので外部からHTMLを持ってきてこれで変換した場合pt指定の箇所が崩れます。しかし、私の用途では外部から誰かの書いたHTMLを持ってくることはないのでpt-pxの数値計算を伴う変換は行なっていません。完全にApp内だけでHTMLを回すならばHTMLの出力の際に直しておくだけで良いのですが。

 あとUNIX系はHTMLのpt-pxの倍率が1になっていると聞いたのですが、iOSはどうやら違うみたいですね。

参考 -2

Swiftの正規表現はそんなに使わなくて毎回忘れてしまう orz

qiita.com

追記 2018/06/12

 改行のみの行の変換で<p>タグと<br>が同時使用され行が2倍になるのを発見したのでそれの修正コードをあげて置きます。見た感じではAttributedString -> HTMLの際のオプション NSAttributedString.DocumentAttributeKey には改行の際の不具合を治すためのものなどはなさそうなので、思い切ってCSSでbrタグを無効化しました。私はHTMLに明るくないのですがbrタグは最近嫌われているそうなので。

簡単な修正方法などがありましたら教えてください。お願いします。

 再々追記のためコードは下記

 これだけNSAttributedString ⇄ String の不具合?があるのはどうなんですかね?もしかしていい感じにHTMLを編集、描写できるTextViewライクなLibraryがあったりするのでしょうか。

追記 2018/08/10

 日本語を入力してHTMLに変換後、AttributedStringに再度変換するとLineHeightがおかしなことになっている不具合の修正をしてみました。

f:id:BegiGrammer:20180810153030p:plain

もともと入力した際はこのような間隔ですが、

AttributedString -> HTML -> AttributedString の操作をするとこうなります。

f:id:BegiGrammer:20180810153224p:plain

これは日本語を含むHTMLをAttributedStringに変換した際にLineHeightのMaximun = 0 Minimun = 23 になってしまう事が原因の一つです。これをこのようにするFixです。よくみてみるとOriginとは若干間隔が異なりますが、こっちの方が見やすいのでここで止めておきます。いくら調べても改善策が見付からなかったので放置した訳では断じてありません。()

f:id:BegiGrammer:20180810153400j:plain

【Xcode 9.2】PlaygroundでLibraryを使う

Xcode 9.4.1 現在この方法ではLibraryを追加できません。

 Playground Single View使ってますか?

 最近(それほど最近でもないけど)XcodeのPlaygroundにSingle Viewモードが追加されました。

f:id:BegiGrammer:20180104103033p:plain

いちいちテストアプリを作ってやっていくのはめんどくさいので非常に重宝していますが、Cocoapodで入れられるLibraryを使えないことが大きな欠点です。この記事ではそのSingleViewモードでLibraryを使えるようにします。

How to

 まずはPlaygroundのSingle View単体で作ります。

f:id:BegiGrammer:20180104103436p:plain

 次にCocoapodをインストールしたXcode Projectを作ります。これに必要なライブラリをよしなにインストールしておいてください。

 作成したおいたPlaygroundをXcode Projectにドラッグ&ドロップします。

f:id:BegiGrammer:20180104104548p:plain

 追加されるさいのオプションを聞かれるので、Add to targetしCopy item if neededにチェックを入れておきます。

f:id:BegiGrammer:20180104104758p:plain

 Playground追加後ビルドします。 これでプロジェクトに追加したPlaygroundの中で必要なライブラリがImportできるようになりましった。

f:id:BegiGrammer:20180104105748p:plain

Playgroundでライブラリを使うために色々とサイトを巡ったのですが、結局このような非常に簡単な方法にたどり着きました。全体的に見直して見ると、Workspaceに別に作っておいたD&DでPlaygroundを追加するだけでした。

お疲れ様でした

問題点

  • ソフトウェアキーボードが隠れて見えること
  • TextFeild等にMacのキーボード操作が効かないこと
  • アニメーションがラグいこと 
  • self.view.centerが使えないこと  (viewWillAppear内で使用可能)
  • たまにxcodeが落ちること (index out of rangeすると落ちる?)

追記

 しばらくデザイン関係のチェックのために使用していましたが、TableViewでミスるとXcodeが落ちたりして結構使いずらいことがわかりました。しかし、単純なTextLabelを作ってみたり、Libraryでデータを弄ってみたりすることに関しては非常に使いやすかったです。当方の環境がMacBook Pro Mid 2015 i7 2.2GHz iGPUなのでdGPUを搭載したものやiMacだとスムーズに作業ができるかもしれません。

参考

m.pardel.net

qiita.com

 

追記 -2018/06/29-

久しぶりにLibraryを含むPlaygroundを作成したところ、Playground内でLibraryの追加ができなくなっていました。私の環境では少し前からPlayground自体も2、3回書き直すとRunning Playground状態で動かなくなったりどうも不安定です。

【Java】EventListenerで他クラスにイベントのタイミングを伝える

 前置き

 諸事情でAndoroidではないデスクトップアプリでJavaを使用することになりました。私はSwiftしかりオブジェクト指向の言語で毎回クラス間、特に子→親の間のイベント通知に戸惑うようで今回も例に漏れず半日ほど唸っていました。

 SwiftではNotificationで比較的自由かつ簡単にクラス感のイベント送受信ができたのですが、JavaではEventListenerを作成することで大体同じような感じになりました。

 同じようにメソッドの呼び出しとしてsuperクラスによるものもありますが、これは単にメソッドを借りて実行しているため今回の用途ではうまく動きませんでした。

本文

 口で言うよりまずコードを見てもらった方が早いですね。

 

 今回は親となるReciveEvent.javaインスタンスにしてあるEventBeginning.javaからのイベントを受け取ると言うことをします。EventBeginning.javaeventListenerを実行するとのそのイベントが親のbuttonAction()を発火させると言うことです。

 この独自のEventListenerの構成を設定しているのがListenerInterfaceでこれに発火させるものを追加していくことができます。又、引数をEventListenerを指定すれば値を渡すこともできます。

【JavaScript】Switchに複数の評価する値を入れる

 やりたい事

 ここでやりたいことはJavaScriptのSwitch文に複数の評価する値を入れて判別するということです。文章にするより実際のコードを見てもらった方が良いかもしれません。(もちろんこのコードは正常に動きません。swiftのコードです。)

 この場合defaultが選択されるのを期待しますが、 実際動かしてみるとpoint1が選択されます。

なのでこうします。

 これの味噌はtoString()で配列をStringに直す事です。そうでないと比較はアドレスの違いを見ることになり期待した動きをしません。数値以外にもtoString()でStringにして比較をしても良いものは大抵この方法でできます。しかしHTMLの要素などのtoString()しても一定の値しか返ってこない場合は使用できません。もっと要素を展開して識別できる値を見つける必要があります。

 結局のところ文字列と数値がくらいが安全に比較できる限界でしょうか。また、これは値を文字に直して完全一致の場合、すなわち両方の評価する値が一致する場合のみcaseが実行されるのでどちらか片方が一致する場合という条件をつけることができません。

【Swift3】吹き出しを作る

 制作意図

 アプリケーションの初回起動などで吹き出しを使って機能を説明したい時があります。しかしデフォルトの吹き出し等が用意されていないので、今回balloonViewというカスタムビューを作成しました

f:id:BegiGrammer:20170602094059p:plain

コード

 BalloonView.swift with initializer

こっちがイニシャライザを使って綺麗に整えたやつ。動かせる機能はオミットされた。

BalloonView.swift Old Version

グリグリと動かせるけどあまり推奨しないし、意味がない。

解説

 やっていることはCoreGraphicsを使って吹き出しのイメージをBalloonViewに貼り付け。そしてその吹き出しの真ん中にUITextLabelを貼り付けているだけです。本当はもじもCoreGraphicsを使って吹き出しのイメージに書き込もうかと思いましたが、拡張性を考え今回このような形にしました。なのでラベル以外にもボタンなどを、吹き出しの中心であるcenterPointプロパティで位置決めして使うことができます。

 また四角形の形をCGRectで指定し、CGPointで頂点つまり吹き出しの三角のところを決めると自動でこれらの吹き出しを生成します。

f:id:BegiGrammer:20170603140031p:plain

 halfBaseLengthプロパティで吹き出しの三角形の底辺の大きさを変更することができます。上の図では赤と青の点の距離を示します。

 使用例のViewControllerでは吹き出し部分をグリグリとタッチで動かせるようになっていますが、静的な部分も毎回描写し直しているので効率はとても悪いです。実証用に付け足した機能なので実装する際は使用しないでください。

 使用するとUIImageViewとBalloonViewの二枚のSubViewがかぶさることになります。そうすると親のViewへの操作が一切受け付けなくなります。親への操作の透過についてこの2枚のsubViewのisUserInteractionEnabledfalseにしてください。

【Swift3】<Error>: CGContextClosePath: no current point.

No Current Point

  SwiftでCoreGraphicsを触っている時にこのような実行時エラーに遭遇しました。

f:id:BegiGrammer:20170528203441p:plain

 一見問題なく描写が済んでいるものの「現在のポイントではない」という誠に不親切なことが書かれており、一瞬無視しそうになりましたが怒られるので治しときましょう。

目次作るほどでもないSolution 

 このエラーはいくつかの問題によって発生するそうですが、私の場合はfillPath()で塗りつぶすのをclosePath()の前に置いたことで発生しました。つまりその順序を逆にしたところ解決しました。

円を描写する時

 円を描写する時にも同様のエラーに遭遇する時があります。で、これがエラーの出ない円を描写する基本的な順番になります。

f:id:BegiGrammer:20170603132542p:plain

 fillEllipse(in:)だけでも円は描写できますが、contextの描写の中でaddEllipse(in:)で塗りつぶされていない円を描写する必要があります。そして線の描写と同じようにcloseしてから塗りつぶしの作業をします。