投稿

ラベル(Swift)が付いた投稿を表示しています

[Swift] Music Sequenceで再生しているMIDIデータの情報を表示

Music Sequenceを使ってMIDIデータを再生している時に、なっている音を鍵盤で表示したい! ということで、色々調べてたのですが、多いのは、MIDIのInputPortまたはOutputPortにCallbackを仕込んで通知する方法でしたが、この方法だと、バックグランドモードを有効化しないと動作してくれない。 試行錯誤の結果、バックグランドモードを無効にしたまま、MIDIの再生データを表示することが出来たのでご紹介。 環境 Xcode 10.2 ターゲットOS iOS 9.0 コールバック用の関数定義 クラスの関数として実装 func musicSeqenceCallback(sequence: MusicSequence, track: MusicTrack, eventTime: MusicTimeStamp, data: UnsafePointer&ltmusiceventuserdata&gt, startSliceBeat: MusicTimeStamp, endSliceBeat: MusicTimeStamp) -> Void { // 処理したい内容 let dat = data.pointee.data let idx = Int(eventTime) print(String(format: "%d - %d",dat, idx)) } コールバック関数の割り当て クラスのinit()内で実装 func seqCallback(inClientData: UnsafeMutableRawPointer?, inSequence: MusicSequence, in...

[Swift] MIDIデータの再生

先日のApp審査の却下を受けて、UIBackgroundModes Keyをオフにして再生する方法を調査。 結論としては、AudioKitのフレームワークは使用せず、Appleが提供しているフレームワークで実現することにしました。 シーケンサー MIDIデータを再生するために、下記のオブジェクト利用。 var musicSequence : MusicSequence? var musicPlayer : MusicPlayer? var musicTrack : MusicTrack? これだけだと、サウンドフォントを使った再生がうまくできなかったので、AUGraphも使いました。 var processGraph : AUGraph? var chordUnit : AudioUnit? var ioUnit : AudioUnit? var chordNode = AUNode() var ioNode = AUNode() まずは、初期化。 init() { NewAUGraph(&processGraph) NewMusicPlayer(&musicPlayer) NewMusicSequence(&musicSequence) MusicSequenceNewTrack(musicSequence!, &musicTrack) MusicSequenceSetAUGraph(musicSequence!, processGraph) MusicPlayerSetSequence(musicPlayer!, musicSequence) setup() loadSF2Preset(unit: chordUnit!) } private func setup() { var cd:AudioComponentDescription = AudioComponentDescri...

[iOS] Appの審査

イメージ
先日、Appを審査に出したら、Rejectされました。 Rejectの理由 申請したAppは、バックグランドモード有効(Audio)となっているが、バックグランドモードにしても音がならないよ! ってことらしい。 はい。 フォアグランドの利用しか想定していないので、バックグランドモードでは音がならなくても問題ないです。 では、なぜ、バックグランドモードを有効にしたのか? 答えは、エラーを回避するため です。 Appで何が起きているのか Background Modesをオフにします。  で、Appを実行してみます。 AKMIDISampler()の実行前 AKMIDISampler()の実行後 AKMIDI.swift:init():63:Initializing MIDI CheckError.swift:CheckError:179:Error: kMIDINotPermitted: Have you enabled the audio background mode in your ios app? フレームワーク(AudioKit)でエラーが発生します。 バックグランドモードが有効になってない! だって。 kMIDINotPermitted・・・は、CoreMIDIのエラーのようなので、AudioKitのエラーというよりは、Appleで提供されているモジュールのエラーと思われます。 バックグランドモードを有効にすると、このエラーは出なくなります。 バックグランドで再生はしないので、できることならバックグランドモードは無効にしたい。 一方で、AppleのDocumentには、 Beginning in iOS 6, apps need to have the   audio   key in their   UIBackground Modes   in order to use CoreMIDI’s   MIDISource Create(_: _: _:)   and   MIDIDestination Create(_: _: _: _: _:) ...

[Swift] UISliderをカスタマイズしてみる

イメージ
iOSの標準コントロールに、UISliderというのがありますが、現在の値を表示したいと思ったことはないでしょうか。 プロパティを探してもそれらしいものが見つけられなかったので、UISliderを継承してオブジェクトを作ってみました。 UISlider 今回作成するオブジェクト 環境 MacOSX 10.14 Xcode 10.1 Swift 4 Target iOS 9.0 実現する内容 スライダーの値を表示する スライダーの上に見出し(タイトル)を表示する 増加量(ステップ量)を指定できるようにする 実装 SUISlider UISliderを継承して、SUISliderを作成します。 ソースの全体像は下記の通りです。 import UIKit public class SUISlider : UISlider { var labelTitle: UILabel var valueWidth: CGFloat = 60 var stepValue : Float = 0 private var labelValue: UILabel private let SPACING: CGFloat = 8 public override init(frame: CGRect) { labelTitle = UILabel() labelValue = UILabel() labelValue.textAlignment = NSTextAlignment.right super.init(frame: frame) self.addSubview(labelTitle) self.addSubview(labelValue) self.addTarget(self, action: #selector(self.onValueChanged(sender: )), ...

[Swift] AudioKitを使ってみる

イメージ
iOSで音を鳴らす方法を探してみたところ、AudioKitというフレームワークを使うと、便利そうだったので、使ってみることに。 フレームワークの利用にあたり、CocoaPods前提の情報はたくさんありましたが、 ・Projectファイルを勝手に書き換える ・バージョンが変わるとエラーが出る など、ネガティブな情報も多かったので、CocoaPodsを使わない方法での利用をしてみました。 環境 macOS Mojave (10.14) Xcode 10.1 iOS Target : 9.0 Swift Langage Version : Swift 4.2 AudioKitのダウンロード とりあえず、フレームワークを入手しないと始まらないので、サイトからダウンロードします。 AudioKit :  https://audiokit.io/downloads/ Projectへの組み込み xcodeでプロジェクトを開いて、ダウンロードしたフレームワークをドラッグ&ドロップで追加。 ファイルがごちゃ混ぜになると醜くなるので、私はフォルダを分けてわかりやすくするために、Frameworksというフォルダを作って、その下に追加してます。 フレームワークを追加すると、importができるようになります。 コンパイル はい。ここでハマりました。 ビルドを行うと、エラーが出ました。 ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) x86_64が見つからない? ようなので、プロジェクトファイルのBuildSettingにある Valid Architecturesにx86_64を足してみたりもしましたが、エラーは解消されず。。。 ダウンロードしたAudioKit内には、README.mdがあって、これを見ると、 Make sure to add `-lc++` to the **Other Linker ...

[Swift] UITextView を使って、rtf や rtfd を表示する

イメージ
UITexiViewを使うと、リッチテキスト(RTFファイル、画像付きだとRTFD)を表示することが来ますが、変更履歴、使い方 など、いくつかの長文を表示したいケースがあると思います。 そこで、表示したい文書ファイルを引数にして内容を表示するようにしてみました。 ViewControllerの作成 初期化時にタイトル、文書ファイルのURL、文書の種類を引数で受け取ります。 import UIKit class TextViewController : UIViewController { let txvAbout = UITextView() var viewTitle:String = "" var url:URL! var docType:NSAttributedString.DocumentType! init(title:String, url: URL, docType: NSAttributedString.DocumentType) { super.init(nibName: nil, bundle: nil) self.viewTitle = title self.url = url self.docType = docType } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } 引数で受け取った情報は、クラス内に保持しておきます。 次に、UITextViewを定義します。 今回はUITexiViewしか配置しないため、ViewController内にベタ書きしましたが、凝ったレイアウトにしたり、レイアウトを差し替えたりする場合は、View用のファイルを作成して、外に切り出しても良いと思います。 override func viewDidLoad() { super.viewDidLoad() ...

[Swift] Header - Items形式のデータの読み書きを行う

イメージ
ヘッダデータ[1]と明細データ[0...n]を1つのデータの塊として、 ファイルに保存したり、読み込んだりしたくて、試行錯誤しました。 DBにした方が楽なんじゃない? とか思ったけど、DBにするほどデータも無かったので 、意地でもファイルで実現してやる! ってことで、なんとか動きました。 扱うデータのイメージ <ヘッダデータ> [1]  伝票番号   orderNo  仕入先コード vendorCode  仕入先名   vendorName <明細データ> [0...1]  明細番号   itemNo  明細テキスト itemText  数量     quantity ヘッダは必ず存在し、明細は0以上の可変を想定。 データ受け渡し用の構造 struct DataEntity { // Header var orderNo: Int! var vendorCode: String! var vendorName: String! // Items var items: [Item]! init(){ orderNo = 0 vendorCode = "" vendorName = "" items = [] } } struct Item { var itemNo: Int! var itemText: String! var quantity: Int! init(){ itemNo = 0; itemText = "" quantity = 0 } } コード データをファイルに保存する func writeData(dataEntity: DataEntity){ var data:Dictionary = [String:AnyObject]() // Header data["orderNo"] = dat...

[Swift] StoryBoardを使用しない - 多言語対応

イメージ
多言語対応してます! って言えるとカッコイイかも? と思い、 必要ないかもしれませんが、仕組みを組み込んでみました。(笑 手順 1. Stringファイルを追加する ファイル名は「Localizable.string」とします。 2. プロジェクトのプロパティを開く 3. Localizationsで言語を追加 + ボタンを押して、言語を選択する。 先ほど追加した「Localizable.string」を選択。 4. Stringファイルが言語ごとに用意されていることを確認 Localizable.stringを編集 言語ごとにファイルが用意されているので、言語に合わせてテキストを編集します。 書式は、"任意のID" = "テキスト"; となります。 セミコロン(;)で区切らないと、コンパイルが通りませんので注意です。 Localizable(English) "label-RoundUnit" = "Round Unit"; "label-Rounding" = "Rounding"; "label-TotalAmount" = "Total Amount"; "label-CalcTotal" = "Calc.Total"; "label-CalcResult" = "Calc.Result"; "CalcTypeDIF" = "Difference"; "CalcTypeFIX" = "Fix"; Localizable(Japanese) "label-RoundUnit" = "丸め単位"; "label-Rounding" = "端数処理"; "label-TotalAmount" = "合計金額"; "label-Ca...

[Swift] StoryBoardを使用しない - UITextFieldで編集不可にする方法

イメージ
コーディングでUITextFieldの入力可否を制御する Swiftのバージョンにより実装方法が異なるようで、悩みました・・・。 UILabelを使えば、表示専用にはなりますが、状況によって編集/表示を切り替えたい場合には、UITextFieldの属性を切り替えられる方が便利。 StoryBoardだとControlにあるEnabledにチェックを入れると実現できるので、絶対に何かあるはず! ってことで探しました。 環境 Xcode10 Swift 4.2 編集可否の制御方法 let txtAmount = UITextField() // 編集不可 txtAmount.isEnabled = false isEnabledをtrueにすると、編集可能となります。 感覚的に isXXXX のメソッドって、Get専用と思い込んで見逃してました。。。 スッキリ(笑

[Swift] StoryBoardを使わず画面を作る

イメージ
StoryBoardの使い方(というか細かい設定)がよく分からず、コーディングで全部作ってやる! ってことで、画面表示まで作ってみました。(iOS用です) プロジェクト作成 とりあえず、プロジェクトは「Single View App」を選択。 自動で作成されるStoryBoardなど、不要なものは削除しますし、少ない方が良い! ってことで。 削除したファイル ・Main.storyboard ・LaunchScreen.storyboard そして、プロファイル定義で、StoryBoardを設定している箇所を変更 ファイルを追加 ViewController 自動生成されているViewControllerの名前をBasicSettingViewController変更して、コーディングを追加。 BasicSettingViewController.swift import UIKit class BasicSettingViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let basicView = BasicSettingView(frame: self.view.bounds) basicView.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.view.addSubview(basicView) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() } } 画面の定義(オブジェクト類)は、viewDidLoad()の中に書いても良かったのだけど、 オブジェクトの数が多くなったり、複雑な画面を作ろうとした場合、外出しにした方が見やすいかな〜 と思い、BasicSettingViewを作成して組み込んでみました。 BasicSettingView.swift im...

[Xcode] StoryBoardって便利なの・・・?

イメージ
StoryBoardを使うと 多分良いところ ・ラベルやボタンなどを配置しながら作っていけるので、直感的にはわかりやすいかも? ・デバイスを切り替えるとデザインが調整されるので、他の機器での表示イメージも確認できる? なんかイマイチなところ (私のスキルが不足してるだけかもしれませんが・・・(汗 ・「こうしたい」に対し、どこをどう設定したら実現できるのかがわかりにくい。 ・少し複雑なレイアウトを作ろうとしたらめんどくさい(笑 ・オブジェクトが多くなると、プロパティの変更がめんどくさい。  色とか、フォントとか・・・ StoryBoardとの格闘 StoryBoardで画面を作ってみてるのですが、AutoLayout関係で警告が出るわ出るわ・・・。 なんでも制約がおかしいらしい。 一応、自動調整してくれる機能があるみたいです。 警告アイコンをクリックすると、ポップアップが表示されるので、Confirmをポチ。 Failed to automatically update constraints んー。 自動調整はできなかったようですね。 警告なので無視しても良いのかもしれませんが、気になる性格でして。 警告無しの綺麗な状態にしたいのですが、いちいち制約をつけていくのも面倒な作業だし、StoryBoardを使わず、コーディングでやった方がわかりやすいのでは? なんて思ったりした。 コーディングなら、プロパティの設定を変数や定数で定義しておけば、後から変更するのも楽にできそうだし。 結論 私には、StoryBoardは合わないようです。 もしかしたら効率が悪かったり、分かりやすさに欠けるかもしれませんが、 コーディングで作った方が、白黒はっきりして良いかも?