20220117のSwiftに関する記事は3件です。

ARでメタバース 巨大ロボットを出現させる

大迫力の3Dオブジェクトを操作する方法 コンピュータのパワーでよりパワフルなコンテンツを ARってなんだか難しそうな印象ありますか? ARKitを使ってスマホでかんたん表示 実はかんたんだったりします。 AppleがARをかんたんに扱えるフレームワークを出してくれています。 手順 アップルのサイトからUSDZモデルを手に入れます。 https://developer.apple.com/jp/augmented-reality/quick-look/ ロボットという名前のUSDZファイルを読み込んでシーンに追加します。 guard let robot = try? Entity.load(named: "robot") else { return } let anchor = AnchorEntity(plane: .horizontal) // 平面に配置する anchor.addChild(robot) arView.scene.addAnchor(anchor) ロボットを100倍のスケールに大きくします。 robot.setScale([100,100,100], relativeTo: robot) ロボットを動かします。 for animation in robot.availableAnimations { robot.playAnimation(animation.repeat()) // 歩行アニメーション } robot.move(to: Transform(translation: [0,0,20]), relativeTo: robot, duration: 4, timingFunction: .easeInOut) // 実際に移動させる 詳しいサンプルコードはこちら ゲームや、映像、舞台インタラクションなど様々なコンテンツに ARコンテンツを表示するのは意外とかんたんです。色々な表現の可能性を探りたいですね。 ? フリーランスエンジニアです。 お仕事のご相談こちらまで rockyshikoku@gmail.com Core MLやARKitを使ったアプリを作っています。 機械学習/AR関連の情報を発信しています。 Twitter Medium
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【RxSwift】テストを書こうとしたら「No such module 'RxSwift'」

はじめに RxSwiftで実装した個人アプリにテストを書き始めましたが 普段テストを書かないので、こんな初歩的なところで詰まりました。 やったこと Editor -> Add Target -> Unit Testing Bundle を追加 テストファイルも追加 さてテスト書くか、ってところで No such module'RxSwift' と怒られる 解決方法 target '{$AppName}Tests' do inherit! :search_paths end が必要だったんですね。 おまけ inherit! 現在のターゲットに対する継承モードを設定する Parameters inheritanceSymbol 設定する継承モード Available Modes :complete ターゲットは親からすべての動作を引き継ぎます。 :none 対象は親からどの動作も引き継ぎません。 :search_paths 対象は親の検索パスのみを継承します。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[iOS]SwiftでLocalizable.stringsを動的に差し替える

Swift で Localizable.strings を動的に差し替える 特に多言語対応しているiOSアプリでは、Localizable.strings を使ってアプリ内の文字列を管理している場合が多いと思います 私が作っているアプリでは、SwiftPM で作ったリソース用のモジュールがあり、Bundle.module.localizedString を使ってバンドルした文字列を取り出しています この方法では、翻訳データを更新するためには、アプリを再度ビルドする必要があります そこで、動的に Localizable.strings を差し替える仕組みを作ってみました うまくいったやり方 実際に作成したコードはこちらです 文字列データは、DynamicLocalize.localizedString を使って取り出します public class DynamicLocalize { internal static func localizedString(_ key: String, _ table: String) -> String { return bundle.localizedString(forKey: key, value: nil, table: table + ".nocache") } private static let bundleName = "DynamicLocalize.bundle" private static let bundleURL: URL = { let doc = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return doc.first! .appendingPathComponent(bundleName, isDirectory: true) }() private static let bundle: Bundle = { let dir = bundleURL.appendingPathComponent("en.lproj") if !FileManager.default.fileExists(atPath: dir.path) { try! FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) } let url = dir.appendingPathComponent("Localizable.nocache.strings") try! "\"Key001\" = \"First Value\";".write(to: url, atomically: true, encoding: .utf8) return Bundle(url: bundleURL)! }() public static func update() { let url = bundleURL .appendingPathComponent("en.lproj") .appendingPathComponent("Localizable.nocache.strings") try! "\"Key001\" = \"\(UUID().uuidString)\";".write(to: url, atomically: true, encoding: .utf8) } } 実装上のポイント ドキュメントディレクトリ下に bundle のディレクトリを作成する Bundle.module は編集する事ができません そこで、ドキュメントディレクトリ下に作る必要があります 文字列のファイル名に、.nocache をつける これで、キャッシュされなくなります https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html Table 2-1 あたり 文字列を差し替えた時に、.nocache を付けておくことで、最新のデータが取得されます SwiftGen で DynamicLocalize を利用する 文字列を使う場所で毎回、localizedString すると大変なので、SwiftGen を利用して文字列データを管理したいです 設定ファイル(swiftgen.yml) はこちらです strings: inputs: - Modules/Sources/Assets/ResourceFiles/Locales/en.lproj filter: .+\.strings$ outputs: - templateName: structured-swift5 output: Modules/Sources/Assets/Generated/Strings+Generated.swift params: publicAccess: true enumName: AppLocales lookupFunction: DynamicLocalize.localizedString 実際に生成されるコードがこちらです public enum AppLocales { /// Value001 public static var key001: String { return AppLocales.tr("Localizable", "Key001") } } extension AppLocales { private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { let format = DynamicLocalize.localizedString(key, table) return String(format: format, locale: Locale.current, arguments: args) } } lookupFunction を指定したので、tr 内で、DynamicLocalize.localizedString が呼ばれています また、AppLocales.key001 が Stored property から Computed property に変わります おかげで stencil をいじらなくて済みました これで、AppLocales.key001 が呼ばれる度に、DynamicLocalize に問い合わせられるようになります 動的に差し替えられる文字列データを利用する AppLocales.key001 を利用できます DynamicLocalize.update() してから objectWillChange などで画面を再描画させると、文字列が更新されていることを確認できます import SwiftUI import Assets public struct ContentView: View { @ObservedObject var viewModel = ContentViewModel() public init() { } public var body: some View { VStack { Text(AppLocales.key001) Button("Update") { DynamicLocalize.update() viewModel.update() } } } } class ContentViewModel: ObservableObject { func update() { self.objectWillChange.send() } } まとめ 最終的にかなりシンプルな仕組みになりましたが、.nocache など辿り着くまで大変でした あと、SwiftGen は神
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む