swift4.1システム学習二十六特性、コンパイルフラグとAPIの可用性検査

6553 ワード

/*プロパティ、コンパイルフラグ、およびAPIの可用性の確認
このセクションの内容は、コンパイル時の動作に属します.swiftはC,C++,OCと異なり,プリプロセッサという概念がないため,プリプロセッシング時の概念は存在しない.swiftソースコードの解析と処理はコンパイル時に含まれると考えられる.
拡張:前処理とは?前処理はC言語の重要な機能であり、前処理プログラムが責任を持って完成する.1つのソースファイルをコンパイルすると、システムは自動的に前処理プログラムを参照してソースプログラムの前処理部分を処理し、処理が完了すると自動的にソースプログラムのコンパイルに入る.C言語は、マクロ定義(#define)、ファイル含む(#include)、条件コンパイル(#ifdef)など、#から始まるプリコンパイル命令を主に処理する複数のプリプロセッシング機能を提供する.プリプロセッシング機能を適切に使用して作成されたプログラムは、読み取り、修正、移植、デバッグが容易であり、モジュール化されたプログラム設計にも役立ちます.*/
/*
  • swiftにおける特性
  • swift言語の特性(attribute)は、GNU C言語のsttributeと非常に類似しており、修飾されたオブジェクトの特定のコンパイル時の動作を指定するために、オブジェクト、関数、およびタイプを修飾するために使用されます.
    @attribute(args) func foo() {
    }
    swiftは複数の特性を重畳することができ、複数の特性を一般的に重畳するだけで、特性の間には前後の順序がありません.*/
    class A {
        
        
        @inline(__always)
        @available(macOS 12.0, *)
        func foo() {
            print("    ")
        }
    }
    

    //swiftでよく使われる特性を一緒に勉強する/*(1)available
    AVailableプロパティは、オブジェクト、関数、またはタイプの可用性を示すために使用されます.このプロパティはiosのバージョン番号を指定するのによく使用されます.新しいバージョンでしか使用できない方法があるので、互換性のためにプロパティIDを付けます.
    現在Appleが自社プラットフォームに使用しているSwiftは、iOS、iOSアプリケーションエクステンション、macOS、macOSApplicationExtension、watchOS、watchOSApplicationExtension、tvOS、tvOSApplicationExtension、swiftのプラットフォームをサポートしています.*
    class B {
        
        /*
         available   MyTest      iOS 10.0      ;
         macOS 10.13      
             *     ios10.0  macOS 13.0  ,               。
         */
        @available(iOS 10.0, macOS 10.13, *)
        func MyTest() {
            print("Hello china")
        }
        
        @available(swift 3.0)
        @available(iOS 10.0, macOS 10.12, *)
        struct MyStruct {
            
        }
    }
    
    let b = B()
    b.MyTest()
    
    _ = B.MyStruct()
    

    /*いくつかの一般的なパラメータ:introduced:どのバージョンから導入されますか.deprecated:どのバージョンから廃棄されますか.obsoleted:どのバージョンから削除され、削除されたエンティティは現在の環境ではアクセスできません.Message:廃棄または削除されたインタフェースを使用した場合に発生するコンパイル警告またはエラー.
    これらのパラメータは、アップルのAPIドキュメントによく表示されます.私たちがある方法を使用している間に、削除線が方法の上に表示されることがあります.この方法は廃棄として表示されているからです.*/
    class C {
        
        @available(macOS 10.10, *)
        @available(*, introduced: 10.10, deprecated: 10.12, message: "      ")
        func hello() {
            print("     ")
        }
    }
    
    let c = C()
    // 'hello()' is deprecated:       
    c.hello()
    

    /* (2) discardableResult
    このプロパティは、通常、現在の関数またはメソッドの戻り値がデフォルトであることを示すために、戻り値を持つ関数またはメソッドを修飾するために使用されます.*/
    class D {
        
        @discardableResult
        func foo(a: Int) -> Int {
            return a * 2
        }
        
        func boo() -> String {
            print("      ?")
            return "boo"
        }
    }
    
    let d = D()
    /*
         foo,         ,       
     */
    d.foo(a: 10)
    //   boo,      :
    // Result of call to 'boo()' is unused
    d.boo()
    

    /* (3) objc
    この特性はAppleの自社プラットフォームにしか使用できません.1つのタイプまたはメソッドがOCの関連するタイプまたはメソッドで表すことができることを示す.実はこの特性はよく使われていますが、特に#selector()イベントの方法の外にはobjcタグが付けられています.*/
    @objc
    protocol MyProt {
        //        
        func method()
        
        //           
        @objc
        optional func foo()
    }
    
    class E: MyProt {
        
        //           
        func method() {
            print("  ")
        }
    }
    

    /* (4) autoclosure
    このプロパティにより、式をパラメータなしの閉パッケージに自動的にカプセル化できます.*/
    /* (5)convention
    このプロパティは、関数オブジェクトのタイプを修飾して呼び出し規則を指定するために使用します.swiftには、3つの呼び出し規則があります.1」swift:この関数オブジェクトがswift関数の参照であることを示します.2』block:この関数がOCのBlock参照と互換性があることを示す.3)c:この関数オブジェクトがC関数であることを示す参照.つまり、この関数参照は実行コンテキストを持たず、C言語の関数呼び出し規則を直接使用します.*/
    class F {
        
        func test() {
            var x = 100
            
            ///                  
            let ref1: @convention(swift)(Int) -> Void  = {
                (a: Int) -> Void in
                
                x += a
            }
            
            /// ref2  block    ,     OC  Block    ,     OC     
            let ref2: @convention(block) (Int) -> Void  = {
                (a: Int) -> Void in
                x -= a
            }
            
            let ref3: @convention(c) (Int) -> Void = {
                (a: Int) -> Void in
                print("a = \(a)")
            }
            
            ref1(10)
            ref2(5)
            ref3(1)
            
            print("x = \(x)")
        }
    }
    
    let f = F()
    f.test()
    

    /* (6) escaping
    このプロパティは、関数またはメソッドのパラメータタイプを修飾するために使用され、後で実行されるので保存されることを示します.これは、この関数またはメソッド呼び出しが終了しても、パラメータのライフサイクルが消えないことを意味します.*/
    /* (7). inline
    inline特性は、関数またはメソッドがインラインまたはインラインされないことを示唆する.修飾された関数またはメソッドがインライン可能かどうかを示すパラメータがあります.Always:いつもインラインされています.never:この関数はいつでもインラインされるべきではないことを示します.
    インラインとは?関数の実装は、別の関数の内部にあります.*/
    class G {
        
        @inline(never)
        func noInlineFunc() {
            print("    ")
        }
        
        @inline(__always)
        func alwaysInlineFunc() {
            print("       ")
        }
        
        /*
           :
              ,swift                       ,          @inline(__always)。
         */
    }
    

    /* (8). _silgen_name
    _silgen_nameプロパティは、現在参照されている関数がC言語標準APIに従う関数であることを示すために使用することができる.このプロパティでは、ブリッジファイルで宣言されていない場合でも、外部リンクを持つグローバルC関数をswiftで直接参照できます.*/
    /*swiftの特性部分については、もうほとんど勉強していないので、本当にたくさんの特性を持っていますね.これらの特性は小さな知識点に属し、比較的細かく、記憶しにくい.しかし、イメージさえあれば、ある状況で必要なときに、振り返ってこれらの特性の運用を見つけることができます.*/
    /*
  • コンパイルフラグ
  • swiftコンパイラはC言語コンパイラと同様に、いくつかのコンパイルオプションを設定できます.
    if ... #else ... #endif
    注意:swiftのコンパイルフラグには、C言語のように「-D FLAG=1」を付けることはできません.swiftが#ifで判定されると、各フラグがブールタイプであると仮定しているからです.このフラグが定義されている限りtrueであり、逆にfalseである.
    コンパイルフラグを定義するのは、xcodeのBuild Settings--』Swift Compiler-Custom Flags--』Other Swift Flagsで設定します.フォーマットは「-D」「識別名」
    これもプロジェクトでよく使われていますが、debugモードでの印刷はreleaseとは異なり、よく設定されています.*/
    @inline(__always)
    func debug_log(str: String) {
        
        #if DEBUG
           print("      ")
        #else
           print(str)
        #endif
    }
    
    debug_log(str: "    ")
    

    /*
  • APIの可用性を確認する
  • swiftは静的コンパイルに傾くプログラミング言語であり,実行も解釈できるが,設計上OCのように多くの動的特性を持たない.これにより、実行時に効率的になります.
    */
    class H: NSObject {
        
        override init() {
            super.init()
            
            Timer.scheduledTimer(timeInterval: 1.0,
                                 target: self,
                                 selector: #selector(timerHandler(timer:)),
                                 userInfo: nil,
                                 repeats: false)
        }
        
        @objc func timerHandler(timer: Timer) {
            print("        ")
        }
    }
    
    if #available(iOS 10, macOS 10.12, *) {
        
        /*
         Timer         iOS10.0  macOS 10.12     
         */
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { (timer) in
            print("     ")
        }
    } else {
        
        _ = H()
    }