ikeh1024のブログ

ZennやQiitaに書くにはちょっと小粒なネタをこちらに書いています

macOSのUI Element Colorsのプレビュー

追記(2023-09-04)

  • 下記の通り昇華させてみた。

github.com


概要

  • 定義済みNSColorのイメージを見たかったので作成。
  • 今回スクショの手作業が多かったので、次回はもっと効率化する。
    • ダークモードも追加したい。

参考

Gist

NSColorのプレビュー · GitHub

Preview

コマンドでmacOSアプリケーションをビルドする

参考

ビルド例

xcodebuild \
 -target <ターゲット名> \
-project <path-to-file>/XXX.xcodeproj \
 -configuration Release \
-sdk macosx12.3 \
build

アーカイブ

xcodebuild \
-project <path-to-file>/XXX.xcodeproj \
-scheme <スキーム名> \
-configuration Release \
-archivePath ./build/XXX.xcarchive \
archive

xcodebuild  \
  -exportArchive  \
  -archivePath  ./build/XXX.xcarchive  \
  -exportPath ./build  \
  -exportOptionsPlist ./build/XXX.xcarchive/Info.plist

証明書周りで参考になりそうなリンク

メモ

  • 証明書の期限が切れる場合は、更新するのではなく新しい証明書を作成するみたい

参考

円記号問題とその経緯

Swiftで適当なエラーを使いたいときの実装

参考

struct MessageError: Swift.Error & CustomStringConvertible {
  var description: String
}

使用例

  • 実装例
let error = MessageError(description: "hoge")
print(error.localizedDescription)
print(error.description)
  • 出力結果
The operation couldn’t be completed. (iOSEngineerCodeCheck.MessageError error 1.)
hoge

別の案

  • もしくは以下が便利

  • String+LocalizedError.swiftを作成
#if DEBUG
extension String: LocalizedError {
    public var errorDescription: String? { self }
}
#endif
  • 呼び出し例
private func someFunction() throws {
    throw "エラーだよ"
}

do {
    try someFunction()
} catch {
    print(error.localizedDescription)  // エラーだよ
}

forkしたリポジトリを本家リポジトリの最新情報で更新する

概要

  • main(デフォルトブランチ)に関しては下記のようにGitHubから更新可能

image

  • developに関しては下記の手順。
    • 本家のdevelop(upstream)をfetchして情報を取得
    • forkしたdevelopをチェックアウトし、本家のdevelop(upstream)にマージ

参考

SourceTreeで、GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する

SwiftPMの自動アップデート

DependabotはSwiftPMに非対応

Renovate

概要

Renovateの導入デモ

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'GitHubPlayground' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for GitHubPlayground
  pod 'SDWebImageSwiftUI', '1.3.3'

end

RenovateをiOSアプリ開発に導入してみた - dely tech blog 1つのPRでまとめて更新してほしいものをpackageNamesでまとめています。 また、バージョンを更新したくない場合、"enabled": falseを設定することでPRが生成されなくなります(e.g. SwiftLint)

{
  "packageRules": [
    {
      "groupName": "SDWebImage",
      "managers": [
        "cocoapods"
      ],
      "packageNames": [
        "SDWebImageSwiftUI",
      ]
    }
  ]
}
  • しばらくするとRenovateのbotがPRを作成してくれる

image

image

NSSavePanelの保存パスを記憶しているplistの場所

/Users/ユーザ名/Library/Preferences/jp.co.ikeh.Hoge.plist

image

[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"NSNavLastRootDirectory"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"NSNavLastCurrentDirectory"];
[[NSUserDefaults standardUserDefaults] synchronize];

NSSavePanel *savePanel = [NSSavePanel savePanel];

ArchiveがGeneric Xcode Archiveとなり公証できない問題の対処

概要

  • static libraryを含めるプロジェクトの場合、Archiveがうまく作られずに公証処理に進めない問題。

image

  • ライブラリ側のbuild settingsにてSkip InstallをYesにする必要がある。

image

参考

developer.apple.com The Skip Install build setting is set to YES in your Build Settings pane. Skip Install (SKIP_INSTALL) must be set to YES for static libraries and NO for applications as shown in Figure 3. See SKIP_INSTALL for more information about it.

FileManager.default.urlsの出力結果

概要

  • アプリから何かしらのファイルを保存したい場合、フォルダのパスの取得にurls(for:in:)を使用する。
  • 以下はその際の出力のメモ書き。

参考

出力例

FileManager.SearchPathDirectory Detail Paths
applicationDirectory Supported applications (/Applications). /Users/hogeuser/Applications
demoApplicationDirectory Unsupported applications and demonstration versions. /Users/hogeuser/Applications/Demos
developerApplicationDirectory Developer applications (/Developer/Applications). /Users/hogeuser/Developer/Applications
adminApplicationDirectory System and network administration applications. /Users/hogeuser/Applications/Utilities
libraryDirectory Various user-visible documentation, support, and configuration files (/Library). /Users/hogeuser/Library
developerDirectory Developer resources (/Developer). /Users/hogeuser/Developer
userDirectory User home directories (/Users). (nil)
documentationDirectory Documentation. /Users/hogeuser/Library/Documentation
documentDirectory Document directory. /Users/hogeuser/Documents
coreServiceDirectory Core services (System/Library/CoreServices). (nil)
autosavedInformationDirectory The user’s autosaved documents (Library/Autosave Information). /Users/hogeuser/Library/Autosave Information
desktopDirectory The user’s desktop directory. /Users/hogeuser/Desktop
cachesDirectory Discardable cache files (Library/Caches). /Users/hogeuser/Library/Caches
applicationSupportDirectory Application support files (Library/Application Support). /Users/hogeuser/Library/Application Support
downloadsDirectory The user’s downloads directory. /Users/hogeuser/Downloads
inputMethodsDirectory Input Methods (Library/Input Methods). /Users/hogeuser/Library/Input Methods
moviesDirectory The user’s Movies directory (~/Movies). /Users/hogeuser/Movies
musicDirectory The user’s Music directory (~/Music). /Users/hogeuser/Music
picturesDirectory The user’s Pictures directory (~/Pictures). /Users/hogeuser/Pictures
printerDescriptionDirectory The system’s PPDs directory (Library/Printers/PPDs). (nil)
sharedPublicDirectory The user’s Public sharing directory (~/Public). /Users/hogeuser/Public
preferencePanesDirectory The PreferencePanes directory for use with System Preferences (Library/PreferencePanes). /Users/hogeuser/Library/PreferencePanes
applicationScriptsDirectory The user scripts folder for the calling application (~/Library/Application Scripts/<code-signing-id>. /Users/hogeuser/Library/Application Scripts/com.apple.dt.Xcode.PlaygroundStub-macosx
itemReplacementDirectory The constant used to create a temporary directory. (nil)
allApplicationsDirectory All directories where applications can be stored. /Users/hogeuser/Applications
/Users/hogeuser/Applications/Utilities
/Users/hogeuser/Developer/Applications
/Users/hogeuser/Applications/Demos
allLibrariesDirectory All directories where resources can be stored. /Users/hogeuser/Library
/Users/hogeuser/Developer
trashDirectory The trash directory. /Users/hogeuser/.Trash

Code

import Cocoa

struct Directory {
    var directory: FileManager.SearchPathDirectory
    var name: String
    var detail: String
    
    var commonDirectoryURLs: [URL] {
        let urls = FileManager.default.urls(for: directory, in: .userDomainMask)
        return urls
    }
    
    var descriptionForMarkdown: String {
        var message = "|\(name)|\(detail)"
        
        let urls = self.commonDirectoryURLs
        
        if urls.isEmpty {
            message += "|(nil)"
        }
        
        for (index, url) in urls.enumerated() {
            if index == 0 {
                message += "|\(url.path)"
            } else {
                message += "<br>\(url.path)"
            }
        }
        message += "|"
        
        return message
    }
}

extension Directory {
    // ref: [FileManager\.SearchPathDirectory](https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory)
    // 2022/07/14
    static let allDirectories = [
        Directory(directory: .applicationDirectory, name: "applicationDirectory", detail: "Supported applications (/Applications)."),
        Directory(directory: .demoApplicationDirectory, name: "demoApplicationDirectory", detail: "Unsupported applications and demonstration versions."),
        Directory(directory: .developerApplicationDirectory, name: "developerApplicationDirectory", detail: "Developer applications (/Developer/Applications)."),
        Directory(directory: .adminApplicationDirectory, name: "adminApplicationDirectory", detail: "System and network administration applications."),
        Directory(directory: .libraryDirectory, name: "libraryDirectory", detail: "Various user-visible documentation, support, and configuration files (/Library)."),
        Directory(directory: .developerDirectory, name: "developerDirectory", detail: "Developer resources (/Developer)."),
        Directory(directory: .userDirectory, name: "userDirectory", detail: "User home directories (/Users)."),
        Directory(directory: .documentationDirectory, name: "documentationDirectory", detail: "Documentation."),
        Directory(directory: .documentDirectory, name: "documentDirectory", detail: "Document directory."),
        Directory(directory: .coreServiceDirectory, name: "coreServiceDirectory", detail: "Core services (System/Library/CoreServices)."),
        Directory(directory: .autosavedInformationDirectory, name: "autosavedInformationDirectory", detail: "The user’s autosaved documents (Library/Autosave Information)."),
        Directory(directory: .desktopDirectory, name: "desktopDirectory", detail: "The user’s desktop directory."),
        Directory(directory: .cachesDirectory, name: "cachesDirectory", detail: "Discardable cache files (Library/Caches)."),
        Directory(directory: .applicationSupportDirectory, name: "applicationSupportDirectory", detail: "Application support files (Library/Application Support)."),
        Directory(directory: .downloadsDirectory, name: "downloadsDirectory", detail: "The user’s downloads directory."),
        Directory(directory: .inputMethodsDirectory, name: "inputMethodsDirectory", detail: "Input Methods (Library/Input Methods)."),
        Directory(directory: .moviesDirectory, name: "moviesDirectory", detail: "The user’s Movies directory (~/Movies)."),
        Directory(directory: .musicDirectory, name: "musicDirectory", detail: "The user’s Music directory (~/Music)."),
        Directory(directory: .picturesDirectory, name: "picturesDirectory", detail: "The user’s Pictures directory (~/Pictures)."),
        Directory(directory: .printerDescriptionDirectory, name: "printerDescriptionDirectory", detail: "The system’s PPDs directory (Library/Printers/PPDs)."),
        Directory(directory: .sharedPublicDirectory, name: "sharedPublicDirectory", detail: "The user’s Public sharing directory (~/Public)."),
        Directory(directory: .preferencePanesDirectory, name: "preferencePanesDirectory", detail: "The PreferencePanes directory for use with System Preferences (Library/PreferencePanes)."),
        Directory(directory: .applicationScriptsDirectory, name: "applicationScriptsDirectory", detail: "The user scripts folder for the calling application (~/Library/Application Scripts/<code-signing-id>."),
        Directory(directory: .itemReplacementDirectory, name: "itemReplacementDirectory", detail: "The constant used to create a temporary directory."),
        Directory(directory: .allApplicationsDirectory, name: "allApplicationsDirectory", detail: "All directories where applications can be stored."),
        Directory(directory: .allLibrariesDirectory, name: "allLibrariesDirectory", detail: "All directories where resources can be stored."),
        Directory(directory: .trashDirectory, name: "trashDirectory", detail: "The trash directory."),
    ]
}

print("""
|FileManager.SearchPathDirectory|Detail|Paths|
|---|---|---|
""")

for directory in Directory.allDirectories {
    print(directory.descriptionForMarkdown)
}

Makefileで複数行のコマンドを書くときのセミコロン

概要

  • とても難しい。わかるようなわからんような。
  • 一旦シェルスクリプトで考えるといい。

参考

# Standard
for x in 1 2 3
do
    echo $x
done

# 1 line
for x in 1 2 3; do echo $x; done
.PHONY: test
test:
    @for x in 1 2 3;\
    do\
        echo $$x;\
    done
# Standard
if true; then
    echo "hello"
else
    echo "goodbye"
fi

# 1 line
if true; then echo "hello"; else echo "goodbye"; fi
.PHONY: test
test:
    if true; then\
        echo "hello";\
    else\
        echo "goodbye";\
    fi

SwiftでColorSpaceを扱うときのメモ

まとめ

  • macOS/iOSアプリを作るときはDisplay P3を採用すれば良さそう。
    • より色の表現幅が大きいため。

参考

macOSのRBG指定

  • ある種の条件によっては Deviced にすべきだけれども、広く一般(つまり、common/general user)には Calibrated や NSColor.systemXXX が妥当とのこと?

What's the difference between colorWithSRGBRed vs colorWithDeviceRed vs colorWithCalibratedRed

SwiftUIのプレビューのデバイス設定

SwiftUIのプレビューのデバイス設定

  • 設定方法
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewDevice("iPhone 8")
        ContentView()
            .previewDevice("iPad Pro (9.7-inch)")
    }
}
  • 使用できるデバイスは以下で確認できる
  • 例えばiPhone 4sが指定する対象文字列
xcrun simctl list devicetypes
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
iPhone 6 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus)
iPhone 6 (com.apple.CoreSimulator.SimDeviceType.iPhone-6)
iPhone 6s (com.apple.CoreSimulator.SimDeviceType.iPhone-6s)
iPhone 6s Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus)
...

macOSアプリ→Sentry→Slackの連携を考えたときのメモ

概要

  • macOSアプリ→Sentry→Slackの連携をしようと思ったけど、SentryとSlackの連携は有償プランなので諦めた。
  • 忘備録としてメモだけ残す。

Memos

    @IBAction func buttonTapped(_ sender: Any) {

        let event = Event(level: .warning)
        event.environment = "develop"
        event.message = SentryMessage(formatted: "Sentry Message \(12)")
        event.extra = ["at": "\(#function),\(#line)"]
        SentrySDK.capture(event: event)
        
        do {
            try doSomething()
        } catch {
            SentrySDK.capture(error: error)
            return
        }
        SentrySDK.capture(message: "Task Completed!")
    }
    
    func doSomething() throws {
        throw NSError(domain: "さんごさんご", code: -1, userInfo: nil)
    }

Xcodeのアップデートが進行しているかどうかを確認する方法

概要

  • Xcodeのアップデートがいつまで経っても終わらない、ということが偶によくある。
  • しかし下記を見ても表示がざっくりとしていて、進捗があるかどうか分からない…

image

image

  • 具体的に進捗は何%なのかと知りたい…!

アップデートの進捗を確認する方法

  • コンソールを開き、右上にApp Storeと入力し絞り込む
  • メッセージのCompleted: xxx of 1000で進捗が確認できる

ScreenShot_2021-11-01_16_37_20

  • 数字が進んでいれば、進捗があることが確認できる

ScreenShot_2021-11-01_16_37_26

  • 800/1000から進みが遅くなり、そこから5時間ほどかかった…。
  • 一見止まっているのではと思ってしまうので、数字で進捗が見れるとまだ放置していいと分かり精神衛生上良い。

参考