Calling instance method during initialization in Swift

前端 未结 7 1520
别跟我提以往
别跟我提以往 2020-12-06 01:08

I am new to Swift and would like to initialize an object\'s member variable using an instance method like this:

class MyClass {
  var x: String
  var y: Stri         


        
相关标签:
7条回答
  • 2020-12-06 01:44

    see Two-Phase Initialization, and the example : https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html#ID52 at Unowned References and Implicitly Unwrapped Optional Properties

    class Country {
        let name: String
        var capitalCity: City!
        init(name: String, capitalName: String) {
            self.name = name
            self.capitalCity = City(name: capitalName, country: self)
        }  
    }
    class City {
        let name: String
        unowned let country: Country
        init(name: String, country: Country) {
            self.name = name
            self.country = country
        }
    }
    

    To set up the interdependency between the two classes, the initializer for City takes a Country instance, and stores this instance in its country property.

    The initializer for City is called from within the initializer for Country. However, the initializer for Country cannot pass self to the City initializer until a new Country instance is fully initialized, as described in Two-Phase Initialization.

    To cope with this requirement, you declare the capitalCity property of Country as an implicitly unwrapped optional property, indicated by the exclamation mark at the end of its type annotation (City!). This means that the capitalCity property has a default value of nil, like any other optional, but can be accessed without the need to unwrap its value as described in Implicitly Unwrapped Optionals.

    Because capitalCity has a default nil value, a new Country instance is considered fully initialized as soon as the Country instance sets its name property within its initializer. This means that the Country initializer can start to reference and pass around the implicit self property as soon as the name property is set. The Country initializer can therefore pass self as one of the parameters for the City initializer when the Country initializer is setting its own capitalCity property.

    so add a exclamation mark of y's type -> var y: String!

    0 讨论(0)
  • 2020-12-06 01:46

    I think the Swift way to do this is with Computed Properties (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)

    EDIT

    Instead of calling a function to modify a property on set/get, you can use computed properties:

    class MyClass {
    
        var x: String?
        var y: String? {
            get {
                return "\(x!)_test"
            }
        }
    
        init(x: String!){
           self.x = x
        }
    }
    
    let myClass = MyClass(x: "string") 
    print(myClass.y!) #=> "string_test"
    
    0 讨论(0)
  • 2020-12-06 01:49

    Convert createY() to a global or class function that accepts x as an argument and returns a y.

    func createY(x: String) -> String {
        return x + "_test" // this computation could be much more complex
    }
    

    Then just call it normally from your init.

    class MyClass {
      let x: String
      let y: String
    
      init(x: String) {
        self.x = x
        self.y = createY(x)
      }     
    }
    
    0 讨论(0)
  • 2020-12-06 01:50

    As answered here, create a class function. I've added the full code.

    class MyClass {
        var x: String
        var y: String
    
        class func createY(x: String) -> String {
             return x + "_test" // this computation could be much more complex
        }
    
        init(x: String) {
            self.x = x
            self.y = MyClass.createY(x)
        }     
    }
    
    0 讨论(0)
  • 2020-12-06 01:51

    In Swift 3, I've been using this pattern,

    class MyClass {
      var x: String?
      private(set) lazy var y: String? = self.createY()
    
      init(x: String){ self.x = x }
    
      private func createY() -> String?
      {
        return "\(x ?? "nil") test"
      }
    }
    

    The secret sauce here is the use of private(set) lazy. This way, you can label your property a var. And lazy will delay initialization until after your init function has completed. Using private(set) only allows the functions inside this class to modify that property, including the lazy keyword, but not let public interfaces change it. Of course, if you want your interface to change your property, then you can also mark it internal (the default) or public. But you need to leave it marked a lazy var

    0 讨论(0)
  • 2020-12-06 02:04

    You can use in this approach

    class MyClass: NSObject {

            let x: String
            var y: String
    
            init(x: String) {
    
                self.x = x
                self.y = self.x + "_test"
                print(self.x)
                print(self.y)
            }
    }
    
    0 讨论(0)
提交回复
热议问题