質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Swift

    7448questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

構造体(Swift)の型について

受付中

回答 6

投稿

  • 評価
  • クリップ 1
  • VIEW 961

hirdd

score 42

swiftにおける構造体の型?について質問です。

現在、swiftでiOSアプリを開発していて、documents配下のファイルパスを取得しようとした際、以下のような記載をするかと思うのですが、

let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!

この.userDomainMaskって何者なのかと思い、⌘を押しながらクリックしてみたところ以下のようになっていました。
(fileManagerのExtensionに含まれている。)

public struct SearchPathDomainMask : OptionSet {

        public init(rawValue: UInt)


        public static var userDomainMask: FileManager.SearchPathDomainMask { get } // user's home directory --- place to install user's personal items (~)

        public static var localDomainMask: FileManager.SearchPathDomainMask { get } // local to the current machine --- place to install items available to everyone on this machine (/Library)

        public static var networkDomainMask: FileManager.SearchPathDomainMask { get } // publically available location in the local area network --- place to install items available on the network (/Network)

        public static var systemDomainMask: FileManager.SearchPathDomainMask { get } // provided by Apple, unmodifiable (/System)

        public static var allDomainsMask: FileManager.SearchPathDomainMask { get } // all domains: all of the above and future items
    }

この定義が全く理解できません。
まず、SearchPathDomainMaskという構造体は、OptionSet型なのでしょうか??そして、public staticで宣言されている変数達の型はこの構造体自身の型になっている??
Google検索などしてみましたが、このような記載方法をしている例を上手く見つけられませんでした。。。
どなたかswiftの文法を説明頂ける方、ご教授いただけないでしょうか??
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

+2

構造体の文法の説明

public struct SearchPathDomainMask : OptionSet{}の文法的な意味は「構造体SearchPathDomainMaskはOptionSetというプロトコルを採用している」という意味になります。
Swiftでは、構造体(struct)や列挙型(enum)にもプロトコルを採用することができます。
Objective-Cではクラスしかプロトコルを採用できなかったのですが、それが拡張されました。

構造体でプロトコルを採用する文法は以下の通りです。構造体の型の名前の後ろに:(コロン)をつけて定義します。

struct <構造体の型の名前> :<プロトコル名>{
}


質問で書かれていた

SearchPathDomainMaskという構造体は、OptionSet型なのでしょうか??

ですが、クラスの定義とごっちゃになっていそうなので、クラスの定義もお伝えすると

class <クラスの型の名前>:<親クラス or プロトコル名>,<プロトコル名>{
}


というように、クラスの定義では:(コロン)の後は継承する親クラスか、採用するプロトコル名を指定して、その後「,(カンマ)」で区切ってプロトコル名を書いていきます。

クラスでは親クラスから継承できるんですが、構造体は継承ができないので:(コロン)の後は必ずプロトコルになります。


OptionSetって何?

じゃあ、OptionSetプロトコルってどんな時に使うんじゃいという話になりますが、OptionSetにカーソル当てて⌘+クリックして定義を見るとどうやらビットマスクを行うためのプロトコルになるそうです。ちょっと抜粋します。

A type that presents a mathematical set interface to a bit mask.
  You use the OptionSet protocol to represent bit mask types, where
individual bits represent members of the set. Adopting this protocol in
your custom types lets you perform set-related operations such as
membership tests, unions, and intersections on those types. What's more,
when implemented using specific criteria, adoption of this protocol
requires no extra work on your part.

*意訳:OptionSetは数学上の集合を表現する型です。OptionSetプロトコルを使用して、ビットマスクタイプを表し、それらを集合として表現できます。このプロトコルを採用することで論理和や論理積などの計算が楽に表現できます。

Swift2ですがOptionSetについて説明した記事があったので紹介します。

>Swift 2.0 の新しいOption、OptionSetType
>http://www.toyship.org/archives/2208

どうやら、iOSのアプリのフォルダ指定をビットマスクによって管理しているようです。
ビット自体の説明は以下の記事がわかりやすいです。

>ビットをどう使うかよく判らない人へ
>http://qiita.com/satoshinew/items/566bf91707b5371b62b6

 userDomainMask等の型指定について

私も初めてこの形をみましたし、⌘+クリックの定義ファイルでは具体的な実装まではわからないのでなんとも言えないですが、

public static var userDomainMask: FileManager.SearchPathDomainMask { get }


と書いた時に結局userDomainMaskプロパティってOptionSetプロトコルを採用してることになるんですよね。

「構造体SearchPathDomainMaskのプロパティ(userDomainMaskなど)に自身の型を指定しているのか?」が何故なのかですが、予想するに、FileManagerのextensionでプロパティを増やしたいからだと思います。

extension(拡張)では保持型のプロパティの追加はできないです。
ですが、ネストする形でまず構造体(ここではSearchPathDomainMask)を定義して、その構造体のプロパティを追加するとextensionでもプロパティを追加できます。

今Playgroundで確認しました。

class A {}
extension A {
    struct StructA {
        static var nestValue : A.StructA {
            get {
                return A.StructA()
            }
        }
    }
    //var addNumber :Int ->保持型のプロパティをextensinoでは追加できない!!
}

A.StructA.nestValue//A.StructA型になる


上記のコードを実行するとA.StructA.nestValueA.StructA型になります。

extensionってコードの可読性を上げるために、追加の機能は全てextensionで書かれることがあり、Foundationライブラリーはその書き方にならっているので、こんな書き方になっていると予想します。


 【追記】 iOSのアプリのフォルダ指定をビットマスクによって管理するとはどうゆうことなのか?

ビットをどう使うかよく判らない人へ
ではビットフラグを作り、フラグを立てることで変数に複数の状態を表すことができると書かれています。
それを今回のSearchPathDomainMask例で提示します。

突然ですが、今すぐXcodeで言語をObjective-Cで新しいプロジェクトを作成して、ViewControllerのviewDidloadで以下のコードを書いてください

- (void)viewDidLoad {
    [super viewDidLoad];
    //キャッシュディレクトリを取得する
    NSArray *cachesArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSLocalDomainMask | NSUserDomainMask | NSNetworkDomainMask | NSSystemDomainMask , YES);
    NSLog(@"キャッシュディレクトリ配列:%@", cachesArray);
}

NSSearchPathForDirectoriesInDomains関数の第一引数には検索するディレクトリを入れます。
今回はNSCachesDirectoryを指定してキャッシュディレクトリを取得します。
第二引数はドメインマスクを指定します。今回はNSLocalDomainMask | NSUserDomainMask | NSNetworkDomainMask | NSSystemDomainMaskとor演算をして、全て選択します。

これを実行するとこんな結果が得られると思います。

キャッシュディレクトリ配列:(
    "/Users/user/Library/Developer/CoreSimulator/Devices/C89BA657-CB47-4142-ADAD-0278E32047CF/data/Containers/Data/Application/D0584736-5F37-4A87-87E4-83F29064D0E9/Library/Caches",
    "/Library/Caches",
    "/System/Library/Caches"
)


NSLocalDomainMaskとして"/Users/user/Library/Developer/CoreSimulator/Devices/C89BA657-CB47-4142-ADAD-0278E32047CF/data/Containers/Data/Application/D0584736-5F37-4A87-87E4-83F29064D0E9/Library/Caches"
NSUserDomainMaskとして"/Library/Caches"
NSSystemDomainMaskとして"/System/Library/Caches"
の3つのディレクトリが取得できました。

さて、先程のソースのNSUserDomainMaskにカーソル当てて⌘クリックするとこんな定義に飛びます。

//NSPathUtilities.h
typedef NS_OPTIONS(NSUInteger, NSSearchPathDomainMask) {
    NSUserDomainMask = 1,       // user's home directory --- place to install user's personal items (~)
    NSLocalDomainMask = 2,      // local to the current machine --- place to install items available to everyone on this machine (/Library)
    NSNetworkDomainMask = 4,    // publically available location in the local area network --- place to install items available on the network (/Network)
    NSSystemDomainMask = 8,     // provided by Apple, unmodifiable (/System)
    NSAllDomainsMask = 0x0ffff  // all domains: all of the above and future items
};


NS_OPTIONS修飾子はObjective-CとSwiftを橋渡しする修飾子で、文法的にはC言語のenumになります。
(Objective-Cという言語は[]で囲われていない部分はC言語の文法で動く言語です。)
C言語のenumは数値に名前をつけられるものです。上記のソースでは「1という数値にNSUserDomainMaskという名前を2という数値にNSLocalDomainMaskを...以下略」としています。
なぜ2の階乗ごとの数値になっているかというと2進数で表した時に都合がいいからです。
この数値をビットマスクすることで複数のディレクトリを選択することができます。
例えば、最終的なNSSearchPathDomainMaskの値が2進数で

1001(イチゼロゼロイチ)

ならばNSUserDomainMask(2進法で1桁目。10進法で1の数字)とNSSystemDomainMask(2進法で4桁目。10進法で8の数値)が選択されていることがわかります。

2進数で各位に1があればそれが選択されているということが分かるのがビット演算で、NSSearchPathDomainMaskはそのようにしてディレクトリを選択しています。

因みに以下のように数値を直に記入しても同じ結果が得られると思います。C言語のenumは数値を置き換えたものだからです。

    //キャッシュディレクトリを取得する
    NSArray *cachesArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, 1 | 2 | 4 | 8 , YES);//第二引数を1 | 2 | 4 | 8 にした。
    NSLog(@"キャッシュディレクトリ配列:%@", cachesArray);

話をSwiftに戻します。
Swift2からOptionSetType(Swift3でOptionSetに改名)が追加されてこのビットマスク操作をインスタンスのメソッドによる操作でできるようになりました。

上記のObjective-CのコードをSwiftに置き換えてみます。

        var useMask = FileManager.SearchPathDomainMask.localDomainMask
        useMask.insert(.userDomainMask)
        useMask.insert(.networkDomainMask)
        useMask.insert(.systemDomainMask)

        let cachesArray = NSSearchPathForDirectoriesInDomains(.cachesDirectory, useMask, true)
        print(cachesArray)


FileManager.SearchPathDomainMask.localDomainMaskで変数useMaskを作成し、insertメソッドで追加をしています。ビット演算は使っていません。
ビット演算を直接やるかOptionSetを採用してインスタンスによるメソッド操作に書き方にするかどちらがいいのかは議論があるところですが、少なくともAppleのFoundation開発者は「インスタンスによるメソッド操作に書き方」がいいと思ってOptionSetで定義しているのだと思います。

SearchPathDomainMaskとは関係ないので完全に余談ですが、Swift3から「Swift2までC言語の関数をブリッチして呼び出していたものをインスタンスのメソッドによる操作に置き換える」方向でアップデートされました。
「インスタンスによるメソッド操作に書き方」の方が受け入れられつつあります。

[iOS][Swift] Swift 3.0の変更点まとめ
http://dev.classmethod.jp/smartphone/iphone/implemented_proposals_for_swift3/
のSE-0044: Import as Memberを参照してください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/13 20:07

    とても丁寧な説明に、感動してしまいました。ありがとうございます。

    まず、”構造体の文法の説明”ですが、おっしゃる通り、class,構造体の定義をよく理解できていませんでした。おかげさまで、整理して理解する事が出来ました。

    次に"OptionSetって何?”ですが、ビットマスクについてリンク先を参照した事で概要は理解する事が出来ました。しかし、"iOSのアプリのフォルダ指定をビットマスクによって管理する"とはどういう状態なのかよくイメージ出来ないのですが、簡単な説明を頂けると嬉しいです。

    最後に、"userDomainMask等の型指定について"ですが、"予想するに、FileManagerのextensionでプロパティを増やしたいからだと思います"以降がよく理解出来ませんでした。ただ、プロパティを追加するだけであれば、structを使わずともextentionの中にそのままcomputed propertyを追加すれば、それで良いように思ってしまいました。そして自身の型を指定している理由も、いまいち理解しきれませんでした。記載頂いた例でA.structA型になると、例えば何の利点がありますか??教えて頂けると嬉しいです。

    キャンセル

  • 2017/01/14 10:27

    "iOSのアプリのフォルダ指定をビットマスクによって管理する"について追記で補足しました。
    "userDomainMask等の型指定について"の捕捉を追記予定です。もう少々お待ち下さい。

    キャンセル

  • 2017/01/14 12:34

    "userDomainMask等の型指定について"にて、extentionのプロパティ追加方法での疑問を別回答で追記しました。(わかりやすいように書いていたら文字数制限を超えてしまいました。ごめんなさい。)ご確認ください!

    キャンセル

0

日本語訳の Appleリファレンスにかなり詳しい詳細が記載されています。
Appleリファレンス

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/13 20:09

    リンクを頂きありがとうございます。

    キャンセル

0

まず、SearchPathDomainMaskという構造体は、OptionSet型なのでしょうか??

プロトコルの実装です。

そして、public staticで宣言されている変数達の型はこの構造体自身の型になっている?? 

それが何か?
例えばInt32型の最小値:minプロパティはやっぱりInt32型です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

プロトコルはそのままだと思いますが、
Int32の値は4バイトですから、最小値のバイト数を求める場合はInt8の1バイトだと思います。
public staticで宣言されている変数達の型はこの構造体自身の型になっている?? 
ことに関して、モデルの構造体ではこのようにIntを宣言して、rawValueを使用しています。
この宣言を自分の用途に応じて対応すればよろしいかと。

let rawValue: Int32のような形で。

    struct ShippingOptions: OptionSet {
      →  let rawValue: Intlet rawValue: Int32 にする。

        static let nextDay    = ShippingOptions(rawValue: 1 << 0)
        static let secondDay  = ShippingOptions(rawValue: 1 << 1)
        static let priority   = ShippingOptions(rawValue: 1 << 2)
        static let standard   = ShippingOptions(rawValue: 1 << 3)

        static let express: ShippingOptions = [.nextDay, .secondDay]
        static let all: ShippingOptions = [.express, .priority, .standard]
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/13 20:13 編集

    コメントありがとうございます。
    すみません、勉強不足で説明についていけませんでした。今回質問のuserDomainMaskとどう対応するのか初心者向けに説明頂けると嬉しいです。

    キャンセル

0

こちらのリンク内の記事を読むことをお勧めしますが、読んでばかりいると、プログラムソースをかけなくなるので、
まず動かしてみることも必要かと思いました。

Swift2でのQita参考記事

Github_Xcode8.21でのソース

参考記事Swift3

プログラムを読む、プログラムを考える、プログラムを動かす、バランスですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

回答が文字数制限を超えてしまったため、別枠で回答します。ごめんなさい

【追記】なぜextensinoでプロパティ追加にわざわざ構造体SearchPathDomainMaskを定義したのか?

Foundationの開発者がなぜわざわざpublic struct SearchPathDomainMask : OptionSet{}とFileManagerクラスに構造体SearchPathDomainMaskをネストする形で定義したのかですが、
「可読性を上げる」が考えられると思います。

@hirddさんがおっしゃるように、extensinoではコンピュートプロパティでプロパティは追加できるので、以下のようにuserDomainMaskなどを定義することができます。

class AltFileManager {}//自分で定義したのでAltFileManagerと名前をつけました。
extension AltFileManager {//exitensinでプロパティを追加
    struct SearchPathDomainMask :OptionSet {
        let rawValue: UInt
    }
    //exitensinでプロパティを追加
    static var userDomainMask : SearchPathDomainMask {
        return SearchPathDomainMask(rawValue: 1 << 0)
    }
    //exitensinでプロパティを追加
    static var localDomainMask : SearchPathDomainMask {
        return SearchPathDomainMask(rawValue: 1 << 1)
    }
    //exitensinでプロパティを追加
    static var networkDomainMask : SearchPathDomainMask {
        return SearchPathDomainMask(rawValue: 1 << 2)
    }
    //exitensinでプロパティを追加
    static var systemDomainMask : SearchPathDomainMask {
        return SearchPathDomainMask(rawValue: 1 << 3)
    }
}
//使用例
var loalDomain = AltFileManager.localDomainMask
//追加もできる
loalDomain.insert(AltFileManager.networkDomainMask)


今回は、AltFileManagerというクラスに構造体でSearchPathDomainMaskをOptionSetを採用する形で定義し、コンピュートプロパティとしてuserDomainMask、localDomainMask、networkDomainMask、systemDomainMaskを定義しました。
使用する場合は、AltFileManager.localDomainMaskなどで各ドメインマスクを取得できます。
コンパイルも通ります。

動いてるならいいじゃないかと思いますが、ここはFoundationというiOSの根幹をなすライブラリーです。
利用する開発者が迷わないように定義するのが重要になってきます。

その考えて行くと、ドメインマスクがAltFileManager.localDomainMaskとFileManagerの直下にバラバラにドメインマスクがあるのは読みにくいです。 
なぜなら、userDomainMask、localDomainMask、networkDomainMask、systemDomainMaskは4つで1つのビット演算をしようとしているからです。

ビットマスクで「2進数で4桁の数値を設定して1がある位を選択状態とみなす」と考えた時にバラバラのプロパティを定義して「userDomainMaskは2進数の1桁目を表します。localDomainMaskは2進数の2桁目を表します」とドキュメントに書くよりは、「SearchPathDomainMaskという構造体を定義し範囲の中でlocalDomainMask、userDomainMaskを定義」するほうがSearchPathDomainMaskというグループに区切ることができるので読みやすくなります。

userDomainMask、localDomainMask、networkDomainMask、systemDomainMaskは意味的にドメインマスクという同じグループに属しているので、それをまとめるSearchPathDomainMask構造体を定義しているのだと思います。

因みにObjective-Cの定義をもう一度確認しても、NSSearchPathDomainMaskの下に各ドメインマスクがあるという定義になっています。
NSSearchPathDomainMaskが各ドメインをまとめるものとして表現されています。

//NSPathUtilities.h
typedef NS_OPTIONS(NSUInteger, NSSearchPathDomainMask) {
    NSUserDomainMask = 1,       // user's home directory --- place to install user's personal items (~)
    NSLocalDomainMask = 2,      // local to the current machine --- place to install items available to everyone on this machine (/Library)
    NSNetworkDomainMask = 4,    // publically available location in the local area network --- place to install items available on the network (/Network)
    NSSystemDomainMask = 8,     // provided by Apple, unmodifiable (/System)
    NSAllDomainsMask = 0x0ffff  // all domains: all of the above and future items
};

SwiftではSwift2までObjective-Cの定義をブリッチしていましたがSwift3では、ブリッチの方法を見直し、よりSwiftらしい書き方ができるように変更されています。

ということでSwift2での定義も確認してみました。

public struct NSSearchPathDomainMask : OptionSetType {
    public init(rawValue: UInt)

    public static var UserDomainMask: NSSearchPathDomainMask { get } // user's home directory --- place to install user's personal items (~)
    public static var LocalDomainMask: NSSearchPathDomainMask { get } // local to the current machine --- place to install items available to everyone on this machine (/Library)
    public static var NetworkDomainMask: NSSearchPathDomainMask { get } // publically available location in the local area network --- place to install items available on the network (/Network)
    public static var SystemDomainMask: NSSearchPathDomainMask { get } // provided by Apple, unmodifiable (/System)
    public static var AllDomainsMask: NSSearchPathDomainMask { get } // all domains: all of the above and future items
}

Swift2ではpublic struct NSSearchPathDomainMask : OptionSetTypeとグローバルな構造体としてNSSearchPathDomainMask(swift3でSearchPathDomainMaskに改名)が定義されてました。(どこにもextensionされていないグローバルな構造体です。)

NSSearchPathDomainMaskの下にUserDomainMaskなどの各ドメインマスクが定義されてます。
NSSearchPathDomainMask > UserDomainMaskのツリー構造になっています。

Swift3でよりよくリファクタリングしようとしたときにこのツリー構造は壊したくないです。

そしてどのように変更されたのかを見ると

FileManager > SearchPathDomainMask > UserDomainMask

というように、FileManagerをトップとしてその下にSearchPathDomainMask、その下にUserDomainMaskとする構造に変更されました。

考えてみれば、SearchPathDomainMaskはファイルを扱う時に使用するので、グローバルで定義するよりFileManagerの下にあった方がわかりやすいです。

ここで質問の答えをしたいと思います。
「extensionでプロパティを増やしたいならなぜわざわざ構造体を定義したのか?コンピュートプロパティなど他のやり方があるのになぜ?」という質問には
「昔からSearchPathDomainMask > UserDomainMaskのツリー構造でObjcもSwift2も定義されていたので、バラバラに定義するのは不合理。Swift3でSearchPathDomainMaskがFileManagerの配下になり、FileManager > SearchPathDomainMask > UserDomainMaskというツリー構造になった。わざわざ構造体を定義した理由はFileManagerというファイルを扱うものの下にSearchPathDomainMaskを定義することで、構造を明確化し可読性を上げるため」
とお答えします。

追記 OptionSetの使い方

公式サイトにoptionsetの使い方が書かれていました。
https://developer.apple.com/reference/swift/optionset

ECサイトなどで購入者の商品配送方法をオプションセットで表す例です。

struct ShippingOptions: OptionSet {
    let rawValue: Int

    static let nextDay    = ShippingOptions(rawValue: 1 << 0)//次の日
    static let secondDay  = ShippingOptions(rawValue: 1 << 1)//二日後
    static let priority   = ShippingOptions(rawValue: 1 << 2)//優先的に
    static let standard   = ShippingOptions(rawValue: 1 << 3)//標準

    static let express: ShippingOptions = [.nextDay, .secondDay]//特急オプション
    static let all: ShippingOptions = [.express, .priority, .standard]//全部入り
}


nextDayなどオプションをstaticで保持して、型ShippingOptionsになっているところ、SearchPathDomainMaskと同じですね。プロパティが自身の型になっているところが。staticで型プロパティにしているからできるんだと思います。
OptionSetはこんなふうに使うんですね。
私も勉強になりました。

参考にしてください!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7448questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています