Swift
ナビゲーションに移動
検索に移動
| Xcode | Mac | IPhone Xcode | SwiftUI | Swift Sample |
環境
Xcode
コマンドライン
- swiftと入力
- 終了には、:q もしくは、ctrl+D
- パスが通ったところに配置されていれば実行できる
$ swift Welcome to Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8). Type :help for assistance. 1> print("test") test
コマンドラインツールを実行
- アクティブ開発ディレクトリのコマンドラインツールを見つけて実行する
- アクティブ開発ディレクトリは、xcode-select で指定する
- アクティブ開発ディレクトリを表示
$ xcode-select -p /Applications/Xcode.app/Contents/Developer
- 以下のようにswiftコマンドを実行もできる
$ xcrun swift
SDK
- SDKを指定してswiftを起動するときに、指定できるSDK一覧を表示
$ xcodebuild -showsdks iOS SDKs: iOS 14.2 -sdk iphoneos14.2 iOS Simulator SDKs: Simulator - iOS 14.2 -sdk iphonesimulator14.2 macOS SDKs: DriverKit 20.0 -sdk driverkit.macosx20.0 macOS 11.0 -sdk macosx11.0 :
SDKを指定して、swiftを起動
$ xcrun -sdk macosx11.0 swift
環境変数にSDKパスを指定
- 以下でSDKのパスを取得し、SDKROOT環境変数に設定し、swiftを起動
$ xcrun -sdk macosx11.0 --show-sdk-path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk
コメント
クイックヘルプ
- 「///」 : クイックヘルプ用コメント
- マークアップ
/// arp -a の結果をHostListに格納する /// /// - Parameters: /// - hosts: 結果を格納する Host のリストを渡す /// - Throws: /// - Returns:
アクセス制御
アクセス制御 | 意味 |
---|---|
open | モジュール情報をインポートすればどんなソースファイルからでもアクセス可能、サブクラスの作成や上書き定義も自由にできる |
public | モジュール情報をインポートすればどんなソースファイルからでもアクセス可能、サブクラスの作成や上書き定義はそのクラスを定義したモジュール内でのみ可能 |
internal | 定義を含むソースファイルと同じモジュール内からはどのソースファイルからもアクセス可能。アクセス制御規定値 |
fileprivate | 定義されたソースファイルの中だけで使用できる |
private | 定義単位の内部のみで利用できる |
データ型
- 型の実体はインスタンス
- 値型と参照型
- 基本データ型
- Int
- UInt
- Float
- Double
- Bool : true/false
- Character : Unicodeの1文字
- String : 値型
変数の定義
- 変数
var 変数名 : 型 = 式
var age : Int = 49
- 定数(単一代入)
let 変数名 : 型 = 式
let age = 49
型変換
- 暗黙の型変換は行われない
- Double() や Int() などのイニシャライザを利用する
1> var i:Int = 5 2> var d:Double = 0; 3> d = i error: repl.swift:3:5: error: cannot assign value of type 'Int' to type 'Double' 3> d = Double(i) 4> d $R0: Double = 5
文字列
- 連結は +
- リテラルは、"で囲む
- \n 改行など\でエスケープ
トリミング
let trimmed = " abc ".trimmingCharacters(in: .whitespaces)
文字列埋め込み
- \(式) で展開される
> var i:Int = 5 i: Int = 5 > let s: String = "Number \(i * 3)" s: String = "Number 15"
Raw文字列
- 文字列の前に1つ以上の#記号を配置
let pattern = #"[0-9]{0,3}"#
Substring
- Stringをスライスした場合など、Substringのインスタンスが結果として返される
ヒアドキュメント
- 三重引用符で開始位置を揃える
let magicpacket = service.createData(mac:"64:00:6a:20:EC:60") print(""" MAGIC PACKET ======== FROM ============ \(magicpacket) MAGIC PACKET ======== TO ============ """)
エンコーディング
オプショナル型
- 扱う値が存在しないことを表すため、nil が用意されている
- nil 値を持つことがある場合、Int? 型などで表す -> オプショナル型
- パラメータ付型指定では、Optional<Int>
- オプショナル型からデータを取り出 -> アンラップ
- アンラップのためには、式の後ろに、! を置く
- オプショナルをprintする場合、明示的にString(describing:)を使用する
var opi:Int? print("\(String(describing:opi))") opi = 1 var i:Int = opi! print("\(i)")
- 実行
nil 1
オプショナル束縛構文(if-let文)
- オプショナルがnilでない場合、すぐに処理で使用したい場合
- if や while の条件部にのみ記述できる
let optNum: Int? = hoge() if let num = optNum { // nil でない場合 } else { // nil の場合 }
- 複数同時にも使用できる
let optNum1: Int? = hoge() let optNum2: Int? = hoge() if let num1 = optNum1, let num2 = optNum2 { // nil でない場合 } else { // nil の場合 }
Data型
- メモリ上のバイト列を管理
- Foundationのimportが必要
コレクション
配列
- T型の配列は、Array<T> もしくは、[T]
- 型省略初期化
> var ia = [1,2,3,4,5]
- 型宣言初期化
> var ia2: [Int] = [1,2,3,4,5]
- 要素0で初期化
> var sa = [String]() sa: [String] = 0 values
- もしくは
> var sa2: [String] = [] sa2: [String] = 0 values
参照と追加と削除
1> var ia = [1,2,3] ia: [Int] = 3 values { [0] = 1 [1] = 2 [2] = 3 }
- 追加
2> ia.append(4) 3> ia $R0: [Int] = 4 values { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }
- 削除
4> ia.remove(at:2) $R1: Int = 3 5> ia $R2: [Int] = 3 values { [0] = 1 [1] = 2 [2] = 4 }
- 追加
6> ia.insert(-1, at:2) 7> ia $R3: [Int] = 4 values { [0] = 1 [1] = 2 [2] = -1 [3] = 4 }
map関数
- 元の配列内の全てのアイテムに対してアクションを行い結果に基づいた配列を作成
let base = [1,2,3] let dbl = base.map { (val) -> Int in return val * 2 } print(dbl) 結果:[2, 4, 6]
- 省略形
let base = [1,2,3] let dbl = base.map({ $0 * 2 }) print(dbl) 結果:[2, 4, 6]
filter関数
- 元配列から条件に一致する配列を生成
let nums = [0,1,2,3,4,5,6] print(nums.filter({ (num) -> Bool in return num % 2 == 0 })) 結果:[0, 2, 4, 6]
- 省略形
let nums = [0,1,2,3,4,5,6] print(nums.filter({ $0 % 2 == 0 }))
reduce関数
- 配列内の全ての値を単一の結果に集約
let nums = [1,2,3] let initial = 10; print(nums.reduce(initial, { (curTotal, val) -> Int in return curTotal + val })) 結果:16
- 省略形
let nums = [1,2,3] let initial = 10; print(nums.reduce(initial,{ $0 + $1 })) 結果:16
タプル
- インデックスでアクセス
let prof : (String, Double, Int) = ("Yagi", 173.0, 49) print("\(prof.0) \(prof.1) \(prof.2)")
- 変数に代入
let (name, tall, age) = prof print("name is \(name) \(tall) cm \(age) yo")
- 名前付タプル
let prof2 = (name:"Yagi",tall:173.0, age:49) print("name is \(prof2.name) \(prof2.tall) cm \(prof2.age) yo")
- 結果
Yagi 173.0 49 name is Yagi 173.0 cm 49 yo name is Yagi 173.0 cm 49 yo
辞書
1> var sex = ["1":"male","2":"female"] sex: [String : String] = 2 key/value pairs { [0] = { key = "2" value = "female" } [1] = { key = "1" value = "male" } } 2> sex["1"] $R0: String? = "male" 3>
- 削除
3> sex.removeValue(forKey:"1") $R1: String? = "male" 4> sex $R2: [String : String] = 1 key/value pair { [0] = { key = "2" value = "female" } }
Set
var setOfStrings = Set<String>() var fruitSet : Set = ["apple","orange","orange","banana"]
演算子
- C言語の演算子はほぼ使える
- ポインタはないため、*、&、-> は異なった意味
- インクリメント(++)、デクリメント(--) は廃止された
キャスト
式 as 型
- as :
- as? : キャストが正しく行われた場合オプショナル型、不正な場合、nil
- as! :
モジュールと名前空間
モジュールのインポート
- フレームワークや外部モジュールからクラスや関数情報をimportで取込む
- Xcodeにある、*.swiftdoc や *.swiftmodule がSwiftが利用できるモジュール情報
import Foundation
名前空間
- ドットで区切って修飾
制御構文
if
- 条件の()は不要
- 1文しかなくても{}は省略不可
- 条件はBool型である必要がある
if 条件 { } else if 条件 { } else { }
for
for 変数 in コレクション { }
整数のレンジ
- 開始値...終了値
for i in 0...10 { print(i) }
- 開始値..<終了値
for i in 0..<10 { print(i) }
- ステップでシーケンス作成(to値を含まない)
for num in stride(from: 0, to: 10, by: 2) { print(num) } //結果 0 2 4 6 8
- ステップでシーケンス作成(through値を含む)
for num in stride(from: 0, through: 10, by: 2) { print(num) } //結果 0 2 4 6 8 10
for-in
- where以下は省略可能
for 定数 in 式 where 式 { }
for i in 0 ... 10 where i % 2 == 0 { print(i) }
while
while 条件 { }
repeat-while
repeat { } while 条件
switch
- break不要
- 分岐に文字列や構造を持つ型も利用できる
- 列挙/範囲指定できる
- breakがなくてもcaseブロック終了でswitchを抜ける
- break書いても良い
- fall through は明示することで可能
- 式がとりうる値を網羅していないとコンパイルエラー
switch 式 { case ラベルn: 文 default: 文 }
for i in 0 ... 10 { switch i { case 2, 4: // 列挙できる print("twe,four\(i)") // breakがなくてもcaseブロック終了でswitchを抜ける case 5: print("five \(i)") case 6: break // break書いても良い case 7 ..< 9: // 範囲指定 print("7 <= i < 9: \(i)") fallthrough // fall through は明示することで可能 default: // 式がとりうる値を網羅していないとコンパイルエラー print("other \(i)") } } 結果: other 0 other 1 twe,four2 other 3 twe,four4 five 5 7 <= i < 9: 7 other 7 7 <= i < 9: 8 other 8 other 9 other 10
タプルに適用
let switchingTuple = ("Yes", 123) switch switchingTuple { case ("Yes", 123): print("Tuple contains 'Yes' and '123'") case ("Yes", _): print("Tuple contains 'Yes' and something else") case (let string, _): print("Tuple contains the string '\(string)' and something else") }
ラベル
- break はラベルのブロックを抜ける
- continue はラベルの次繰り返しへ
ループ
loop1: while 式 { loop2: while 式 { while 式 { break loop1 continue loop1 break loop2 continue loop2 } } }
if switch
cond1: if 式 { cond2: if 式 { if 式 { break cond2 } break cond1 } }
do
エラー処理
エラーを投げる
- プロトコル Errorに適合している必要がある
throw 式
- エラーを投げる関数は直後に、throws宣言が必要
- エラーを投げる関数を呼び出すには、関数名の前にtryを付与して呼び出す必要がある
- tryを使って呼び出すだけ -> さらに上位に伝播
- do-catch -> 捕捉
- try? -> 戻り値をオプショナルとして扱う。エラーが発生した場合値が nil となる
- try! -> 戻り値を通常型として扱う。エラー発生時は実行エラー
- パターンは、定数または変数のマッチング
- パターンを記述しないcatchも可能。発生したエラーは、errorで参照できる
do { try 関数 } catch パターン where節 { 文 } catch { 文 }
- 例
enum ParaErr : Error { case NIL case OVERFLOW } func sub(para:Int?) throws { if let val = para { if val > 5 { throw ParaErr.OVERFLOW } print("para is \(val).") } else { throw ParaErr.NIL } } func test() { let paras: [Int?] = [1, nil, 10] for para in paras { do { try sub(para:para) } catch ParaErr.NIL { print("Parameter is nil.") } catch { print(error) } } } test()
- 結果
para is 1. Parameter is nil. OVERFLOW
guard文
- 想定外の状況が発生した場合に、その状況から抜け出す
- 条件には、通常の条件やオプショナル束縛などを記述できる
guard 条件 else { /* break や return、throw など制御が戻らないことが自明な文 */ }
構造体
- structは値型
- プロトコルは、実装すべきメソッドやプロパティが定まっている
- 構造体の値を変更するメソッドは先頭に mutating を付与
struct 名前 : プロトコル{ 変数・定数定義 イニシャライザ定義 メソッド定義 その他定義 }
- 例
- init() イニシャライザ
struct Person { var name: String var age: Int init(name :String , age : Int) { self.name = name self.age = age } mutating func addAge(num: Int) { self.age += num } } struct Team { let name: String let members: [Person] func printMembers(){ for member in members { print("\(member.name) \(member.age)") } } } func test() { var me = Person(name: "Yagi", age: 49) me.addAge(num: 3) print(me) let team = Team(name:"family", members: [me]) team.printMembers() } test()
- 実行
$ swift struct.swift Person(name: "Yagi", age: 52) Yagi 52
イニシャライザ
- カスタムイニシャライザは値を返さない関数のような形式で定義
- func や関数名はかかず、init というキーワードを記述し、初期化のための手続きをコードブロックに記述する
- 構造体のプロパティに自由にアクセス可能
- 初期値のある定数の初期化はできないが、初期値がなければ一度だけ可能
- イニシャライザで構造体のメソッドを利用できるのは、全てのプロパティの初期化が完了してから(メソッドを利用してプロパティの初期値を設定することはできない)
複数のイニシャライザ
- 関数のオーバーロードのように、必要に応じて複数のイニシャライザを定義できる
- 引数のないイニシャライザ、全項目のイニシャライザは便宜的にコードをかかなくても既定イニシャライザとして、利用できるが、特定のイニシャライザを作成した時点で利用できなくなるので、利用するには別途記述する必要が生じる
クラス
宣言
class クラス名: スーパークラス, プロトコル { var 変数: 型 = 初期値 init(引数: 型) { super.init(引数) self.変数 = 引数 } func 関数(引数: 型) -> 戻り値の型 { return 戻り値 } }
- 例
class Person { var name: String = "" var age: Int = 0 init(name :String , age : Int) { self.name = name self.age = age } func addAge(num: Int) { self.age += num } } class Team { let name: String = "" var members: [Person] = [] func addMember(_ person: Person) { self.members.append(person) } func printMembers(){ for member in members { print("\(member.name) \(member.age)") } } } func test() { let me = Person(name: "Yagi", age: 49) me.addAge(num: 3) print(me) let team = Team() team.addMember(me) team.printMembers(); } test()
- 結果
$ swift classes.swift classes.Person Yagi 52
文字列表現
class SomeClass: CustomStringConvertible { var description: String { return "This is SomeClass" } }
列挙型
enum FoodChoice { case cereal,salad,sandwich,pizza,chiken,pie } enum Meal { case breakfast,lunch,dinner,snack func foodChoices() -> [FoodChoice] { switch self { case .breakfast: return [.cereal] case .lunch: return [.salad,.sandwich,.pizza] case .dinner: return [.sandwich, .pizza, .pie] case .snack: return [.cereal,.pie] } } } let meal: Meal = .lunch print(meal.foodChoices()) 結果:[__lldb_expr_29.FoodChoice.salad, __lldb_expr_29.FoodChoice.sandwich, __lldb_expr_29.FoodChoice.pizza]
関数
定義
func 関数名(引数名:型 = 初期値, ...) -> 戻り値型{ ステートメント return 戻り値 }
import Foundation // 関数定義 func goodmorning(name: String) -> String { return "Good Morning \(name)!" } // return の省略、引数ラベルの別名 func hello(n name: String) -> String { "Hello \(name)!!" } // 引数ラベルの省略 func goodbye(_ name: String) -> String { "Good-bye \(name)!!"} // 関数定義 仮引数、戻り値は省略できる func test() { print(goodmorning(name:"Yagi")) print(hello(n:"Hiroto")) print(goodbye("Hiroto Yagi")) } test()
- 実行結果
$ swift main.swift Good Morning Yagi! Hello Hiroto!! Good-bye Hiroto Yagi!!
inoutによる参照渡し
- 引数のを値を変更する場合、inoutを付与
- 実引数を&を付与して渡す
import Foundation func funcIntou(n: inout Int, m: inout Int) { let temp = n n = m m = temp } func test() { var a = 111; var b = 999; print(a, b) funcIntou(n:&a, m:&b) print(a, b) } test()
- 実行結果
$ swift func_inout.swift 111 999 999 111
ネストした関数
- デフォルトでは外部から隠されている
- 囲っている関数からは呼び出すことができる
- 囲っている関数は、ネストした関数を外部で使用するために返すことができる。
func chooseStepFunction(backward: Bool) -> (Int) -> Int { func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 } return backward ? stepBackward : stepForward } var currentValue = -4 let moveNearerToZero = chooseStepFunction(backward: currentValue > 0) // moveNearerToZero now refers to the nested stepForward() function while currentValue != 0 { print("\(currentValue)... ") currentValue = moveNearerToZero(currentValue) } print("zero!") // -4... // -3... // -2... // -1... // zero!
可変長引数
- ...を記述
func shell(_ outputPipe:Pipe, path:String ,args: String...) -> Int32 { }
プロパティ
構造体、列挙、クラスに定義可能
格納型プロパティ
- 定数、変数
計算型プロパティ
- 手続きで構成
var プロパティ名:型 { get { プロパティの値を返す文 } set(仮引数) { プロパティの値を更新する文 } }
- 例
struct Tentimes { var origin: Int var ten: Int { get { return self.origin * 10 } set(num) { origin = num / 10 } } } func test() { var n = Tentimes(origin: 10) print(n.ten) n.ten = 10 print(n.origin) } test()
- 結果
$ swift property.swift 100 1
タイププロパティ/静的プロパティ
- 型に関連
- static を付与
プロパティオブザーバー
- プロパティの変更をトリガーに手続きを起動
- willSet:プロパティに格納される直前の値を、newValueで参照できる。willSet(仮引数) と具体的に引数を指定もできる
- didSet:プロパティに今まで格納されていた値を、oldValueで参照できる。didSet(仮引数) と具体的に引数を指定もできる
struct PropertyObserver { var val:Int = 0 { willSet { print("new value:\(newValue)"); } didSet { print("old value:\(oldValue)"); } } } func test() { var po = PropertyObserver() po.val = 1; print("\(po.val)") po.val = 2; print("\(po.val)") } test()
- 実行
ew value:1 old value:0 1 new value:2 old value:1 2
添字付け
subscript(仮引数) -> 型 { get { 添字で指定したプロパティを返す } set (仮引数) { プロパティの値を変更する } }
- 実行
struct Upper { var items:[String] init(count: Int) { self.items = Array(repeating:"", count:count); } subscript(pos: Int) -> String { get { return self.items[pos] } set { self.items[pos] = newValue.uppercased() } } } func test() { var u = Upper(count:3) u[0] = "a" u[1] = "b" u[2] = "c" print("\(u[0])\(u[1])\(u[2])") } test()
- 結果
$ swift subscript.swift ABC
プロトコル
- Swiftではインターフェースを定義するためのプロトコルをクラスだけでなく、構造体や列挙にも適用可能
- プロトコルには実装を共有できない問題があるが、拡張機能を活用することで問題を軽減できる
- 本来関係ない型どうしをプロトコルと拡張を用いて後から連携するようにできる
- Swiftでは、プロトコル指向開発を進めることが可能
クロージャ
- 実行する文を記述する前に、inキーワードが必要
- 仮引数には、inout、可変長引数も利用可能
{ ( 仮引数: 型 ) -> 型 in // 省略可 文 }
- 例(引数、戻り値なし)
var hello = { () -> () in print("hello")} hello()
- 結果
hello
キャプチャリスト
- クロージャはローカル変数を共有する
- 共有の必要がない場合、クロージャのインスタンス生成時にローカル変数の値をコピーする
{ [キャプチャリスト] ( 仮引数: 型 ) -> 型 in // 省略可 文 }
- 例
var message = "Start" let c1 = { () -> () in print("\(message)") } let c2 = { [message] () -> () in print("\(message)") } message = "End" c1() c2()
- 結果
End Start
クロージャを引数にとる関数
// クロージャ(c1)を引数に取る func hoge(_ s1:String, _ s2:String, _ c1:(String, String) -> String) { print(c1(s1,s2)) } // クロージャを引数に取る関数の呼び出し func testHoge() throws { hoge("hello", "swift", {(m1:String, m2:String) -> String in "\(m1),\(m2)!" }) }
- 結果
hello,swift!
接尾(トレイリング)クロージャ
- クロージャを関数の引数として使用する場合、末尾であれば特別な書き方をすることができる
- クロージャを()の外に出し、可読性を高めることができる
// クロージャ(c1)を引数に取る func hoge(_ s1:String, _ s2:String, _ c1:(String, String) -> String) { print(c1(s1,s2)) } // 接尾クロージャを使用した、クロージャを最後の引数として引数取る関数の呼び出し func testHoge() throws { // クロージャを()の外に出し、可読性を高めることができる hoge("hello", "swift") { (m1, m2) in "\(m1),\(m2)!" } }
- 結果
hello,swift!
並行処理
Swiftでの非同期処理GDP|ディスパッチキューの解説|DispatchQueue.globalとmain
Button(action: { let rootDir = EncConverterService.chooseDir() let queue = DispatchQueue.global(qos: .userInitiated) queue.async { EncConverterService.loadFile(directoryPath: rootDir, filepaths: self.filePaths) } }) { Text("Choose dir") }
正規表現
- https://www.hackingwithswift.com/example-code/strings/nsregularexpression-how-to-match-regular-expressions-in-strings
- https://www.2nd-walker.com/2020/04/21/swift-how-to-use-nsregularexpression/
do { let pattern = #"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"# let regex = try NSRegularExpression(pattern: pattern, options:[]) for subinput in input.split(separator: "\r\n") { let line = String(subinput) let maches = regex.matches(in: line, options: [], range: _NSRange(0..<line.count)) print(line) for mach in maches { for i in 0 ..< mach.numberOfRanges { let start = line.index(line.startIndex, offsetBy: mach.range(at: i).location) let end = line.index(start, offsetBy: mach.range(at: i).length) let text = String(line[start..<end]) print(text) } } } } catch { print("RegEx fail.") }
SwiftUI
UIKitとのインターフェース
SwiftUIは既存のApplieプラットフォームUIフレームワークとシームレスに動作する。
MacOS
Playground
値の変化をグラフで見る
チュートリアル
Objective-Cの動作モデルとセレクタ
- Apple製品はObjective-Cの動作モデルに基づいている
- オブジェクトがプログラムを構成しオブジェクトが相互にメッセージを送信し合うことで動作する
- このモデルではメッセージの送り先について詳しく知る必要がないため、組み合わせの自由度が高い
- Objective-Cでは、メッセージ送信の際、セレクタと呼ばれるデータを使ってメソッドを指定し動的な起動を可能としている
- SwiftではSelector型が提供されており、Selector型でメソッドを呼び出す仕組みは、Objective-CのNSObjectで定義されている
- Selector型は構造体だが、#selectorという特殊なイニシャライザを使用する
Swift Package Manager
Tips
再起的にファイルパスを表示
static func printFiles(directoryPath: String) { print(directoryPath) do { let fm = FileManager.default let fileNames = try fm.contentsOfDirectory(atPath: directoryPath) for fileName in fileNames { let childPath = directoryPath + "/" + fileName var isDir = ObjCBool(false) fm.fileExists(atPath: childPath, isDirectory: &isDir) if isDir.boolValue { printFiles(directoryPath: childPath) } print("\t" + childPath) } } catch { print(error) } }
UnitTest(XCode)
Network
URLからデータを取得
let url = URL(string: "https://www.typea.info/blog/")! let session = URLSession(configuration: .default) let task = session.dataTask(with: url){data, response, error in guard error == nil else { return } if let httpResponse = response as? HTTPURLResponse { guard httpResponse.statusCode == 200 else { return } if let recieveData = data { if let text = String(bytes: recieveData, encoding: .utf8) { print(text) } } } } task.resume()
Bonjour
- https://developer.apple.com/bonjour/
- 概要
- TCP/IP環境に革新もたらすZeroConfネットワーク「Bonjour」
- Bonjour
- サンプル
- サービスタイプ
- DNS Service Discoveryの仕組み
- DNS Service Discovery
- dns-sd
- macOSのdns-sdコマンドではDNSの逆引きに 相当することが出来ない
- How to get MAC address from OS X with Swift
$ dns-sd dns-sd -E (Enumerate recommended registration domains) dns-sd -F (Enumerate recommended browsing domains) dns-sd -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service) dns-sd -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Register Proxy) dns-sd -B <Type> <Domain> (Browse for service instances) dns-sd -Z <Type> <Domain> (Output results in Zone File format) dns-sd -L <Name> <Type> <Domain> (Resolve (‘lookup’) a service instance) dns-sd -Q <name> <rrtype> <rrclass> (Generic query for any record type) dns-sd -q <name> <rrtype> <rrclass> (Generic query, using SuppressUnusable) dns-sd -G v4/v6/v4v6 <hostname> (Get address information for hostname) dns-sd -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping) dns-sd -H (Print usage for complete command list) dns-sd -V (Get version of currently running daemon / system service) dns-sd -O [-compress|-stdout](Dump the state of mDNSResponder to file / STDOUT)
calcutta:~ hirotoyagi$ dns-sd -B Browsing for _http._tcp DATE: ---Wed 24 Feb 2021--- 22:20:24.598 ...STARTING... Timestamp A/R Flags if Domain Service Type Instance Name 22:20:24.599 Add 2 6 local. _http._tcp. Brother DCP-J973N
$ dns-sd -q puli.local DATE: ---Sat 01 May 2021--- 10:52:54.599 ...STARTING... Timestamp A/R Flags if Name Type Class Rdata 10:52:54.771 Add 2 6 puli.local. Addr IN 192.168.0.45
digで逆引き
- @224.0.0.251 -p 5353 はBonjourのアドレス
$ dig +short -x 192.168.0.45 @224.0.0.251 -p 5353 puli.local.
Error Domain=NSURLErrorDomain Code=-1022 の対処
- info.plistのソース編集で以下を追加
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
UDP
bind: Operation not permitted
/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/bind9/bind9-57.5/bind9/lib/isc/unix/socket.c:5580: bind: Operation not permitted /usr/bin/dig: isc_socket_bind: unexpected error
© 2006 矢木浩人