[Swift] Swift 반복 참조 요약

4570 단어
본문 주요 참고
  • The Swift Programming Language 중국어 버전 - 클로즈업
  • The Swift Programming Language 중국어 버전 - 클로즈업으로 인한 순환 강력 인용
  • 원vcat의 글 메모리 관리, WEAK 및 UNOWNED
  • 1. 순환 강인용


    Swift가 ARC(인용계수)로 메모리 관리를 하기 때문에 개발자는 더 이상 수동으로 메모리를 방출할 필요가 없다. 그러나 코드가 순환적인 강력한 인용을 만들어 대상의 인용 계수가 0으로 돌아가지 않으면 시스템은 자동으로 대상을 방출하지 못해 메모리 유출이 발생한다.

    1.1 대상의 순환 강한 인용


    우리는 두 클래스 1, 클래스 2를 가정하는데 이 두 클래스 모두 하나의 클래스 유형의 저장 속성이 있다.
    //  1.1
     class  1{
          var  : 2!
          init(){
            print(" 1 !")
          }
        deinit{
          print(" 1 !")
        }
      }
    class  2{
      var  : 1!
      init(){
          print(" 2 !")
      }
      deinit{
            print(" 2 !")
      }
     }
    

    그리고 우리는 두 종류에 대해 각각 두 대상을 실례화하고 이 두 대상이 서로 가지도록 한다.
    //  1.2
     var  1: 1?  =  1()
     var  2: 2? = 2()
      1?.  =  2
      2?.  =  1
    
      1 = nil
      2 = nil
    

    이렇게 하면 한 대상 간의 순환 인용을 초래할 수 있다.마지막으로 우리는 이 두 대상을 석방할 것이다.콘솔 출력 검색 결과:
     1 !
     2 !
    

    이 두 대상은 방출되지 않아 메모리 유출을 초래했다!

    1.2 클로즈업의 순환 강한 인용


    Swift에서 클립은 자동으로 변수를 포착합니다. 클립에 클래스 실례의 어떤 속성을 부여하고, 이 클립체에서 이 클래스 실례를 사용할 때.이 클립체에서 실례의 어떤 속성에 접근했거나, 클립체에서 실례의 어떤 방법을 사용했을 수도 있습니다.이 두 가지 상황 모두 클로즈업'포획'self를 초래하여 순환이 강하게 인용되었다.예를 들면 다음과 같습니다.
    //  1.3
    class  3{
     let name = " "
     lazy var  :(Void -> Void)? = {
        var name1 = self.name
        var name2 = self.getName()
        print(name1)
        print(name2)
      }
      init(){
        print(" 3 !")
      }
      func getName()->String{
          return " "
      }
      deinit{
         print(" 3 !")
      }
    }
    
    var  3: 3? =  3()
     3. !()
    
     3 = nil
    

    클래스3에서 클로즈업에서 실례적인 속성과 방법을 호출하여 클로즈업이self를 포획하고 순환적인 인용이 발생하여 메모리 유출을 초래했다.

    2. 순환이 강한 인용을 피하는 방법


    Swift에서 강력한 반복 참조를 방지하려면 다음과 같은 두 가지 방법이 있습니다.코드 현식 호출, 순환 깨기 강력한 인용 2.weak, unowned 키워드를 사용하여 약한 인용이나 주 인용이 없는 순환의 강한 인용을 깨뜨립니다

    2.1 코드 현식 호출, 순환 깨기 강력한 인용


    이런 방법은 개발자가 대상을 사용하거나 클로즈업한 후에 자신이 가지고 있는 다른 대상의 강력한 인용을 자발적으로 방출하여 순환을 깨뜨리고 시스템이 메모리를 회수하도록 해야 한다.예를 들어, 코드 1.2를 다음과 같이 수정할 수 있습니다.
    //  2.1
     var  1: 1?  =  1()
     var  2: 2? = 2()
      1?.  =  2
      2?.  =  1
    
    // 
      1?.  = nil
      2?.  = nil
      1 = nil
      2 = nil
    

    코드 1.3의 경우 객체의 클립을 사전 예방적으로 해제할 수 있습니다.
    // 2.2
    var  3: 3? =  3()
     3?. !()
    
     3?.  = nil
     3 = nil
    

    이렇게 하면 메모리 유출을 피할 수 있지만 이런 방식은 ARC 디자인의 취지에 어긋나 사용을 추천하지 않는다.

    2.2 weak, unowned 키워드를 사용하고 약한 인용이나 주 인용이 없으면 순환의 강한 인용을 깨뜨린다


    2.2.1 weak, unowned 키워드


    Swift에서 속성이나 변수를 선언할 때 앞에 weak 키워드를 붙이면 약한 참조임을 나타냅니다. 약한 참조는 참조된 인스턴스에 강한 참조를 유지하지 않고 참조 객체에 대한 참조 수를 증가시키지 않기 때문에 ARC가 참조된 인스턴스를 제거하는 것을 막지 않습니다.약한 인용은 값이 없을 수 있기 때문에, 모든 약한 인용을 선택할 수 있는 형식으로 표시해야 한다.약한 인용은 인용된 실례를 유지하지 않고 인용이 존재하더라도 실례가 소각될 수 있다.따라서 ARC는 참조된 인스턴스가 제거되면 자동으로 nil로 값을 지정합니다.다른 선택할 수 있는 값과 같이 약한 인용의 값이 존재하는지 검사할 수 있으며, 삭제된 실례의 인용에 영원히 접근하지 않을 것이다.
    weak 키워드와 유사합니다. 속성이나 변수 앞에 unowned 키워드를 붙이면 이것은 주 인용이 없고 주 인용이 없으면 인용이 없는 실례를 강 인용하지 않기 때문에 순환 강 인용이 발생하지 않습니다.그러나 weak 키워드와 달리 인용 대상이 삭제되었음에도 불구하고 주 인용이 존재하지 않습니다. 이 때 인용을 강제로 사용하면 프로그램의 붕괴를 초래할 수 있습니다.이 두 키워드의 선택에 대해 인용의 사용 과정에서 대상이 항상 존재하도록 확보할 수 있다면 unowned를 사용하십시오. 그렇지 않으면 더욱 안전한 weak 키워드를 사용하는 것을 권장합니다.

    2.2.2 weak, unowned 키워드의 속성 또는 변수 사용


    weak, unowned 키워드는 속성 또는 변수에서 다음과 같은 간단한 코드를 사용합니다.
    //  2.3
    //weak 
    class  1{
      weak var  : 2!
      init(){
         print(" 1  !")
      }
      deinit{
        print(" 1  !")
      }
     }
    // unowned 
    class  1{
      unowned var  : 2
      init( 2: 2){
            =  2
          print(" 1  !")
      }
      deinit{
          print(" 1  !")
      }  
    }
    

    2.2.3 weak, unowned 키워드 클로즈업에서의 사용


    weak, unowned 키워드는 클로즈업에서 주로 두 가지 방식을 사용한다. 첫째, 클로즈업이 정의되기 전에 weak, unowned 키워드로 대상을 인용하여 클로즈업이 약한 인용이나 주 인용 대상을 포획하여 순환적인 강한 인용이 나타나지 않도록 한다.
    class  3{
      let name = " "
      var closure:(Void -> Void)?
      init(){
        print(" 3 !")
        unowned let myself = self
        closure = {
            // myself 
            var name = myself.name
            name = myself.getName()
            print(name)
        }
      }
     }
    

    이런 방식은 비교적 번거로워서 사용하는 것을 추천하지 않는다.Swift는 캡처 목록을 사용자 정의할 수 있는 또 다른 방법을 제공합니다.개발자는 클립을 정의할 때 먼저 포획 변수 유형을 weak 또는 unowned로 정의하여 순환 인용을 방지할 수 있습니다.
    class  3{
      let name = " "
      lazy var closure:(Void -> Void)? = {
      // 
       [unowned self] in
          var name = self.name
          name = self.getName()
          print(name)
       }
     }
    

    이렇게 하면 클로즈업에서self를 다시 사용할 때 강력한 인용이 나타나지 않는다.
    주: 문장에 만약 어떤 잘못이 있으면 여러분의 비평과 시정을 바랍니다!

    좋은 웹페이지 즐겨찾기