Use of `self` - Confusion

Hi,

I'm using Apples API (Connect), which makes use of 'self'. I've created the below class, however i get a couple of errors:

'Cannot assign to value: 'self' is immutable' and Cannot assign value of type 'URL' to type 'AppleConnectModel.Links'

code:

class Links: ObservableObject, Codable {
    @Published var `self`: URL
     
    required init(from decoder: Decoder) throws {
      let container = try decoder.container(keyedBy: CodingKeys.self)
       
      `self` = try container.decode(URL.self, forKey: .`self`)
       
    }
     
    private enum CodingKeys: String, CodingKey {
      case `self`
    }
     
    func encode(to encoder: Encoder) throws {
      var container = encoder.container(keyedBy: CodingKeys.self)
      try container.encode(`self`, forKey: .`self`)
    }
  }

I'm not sure what i'm going wrong. To make use of a keyword i use backticks `` i.e. self.

Any pointers/help would be appreciated.

I figured out what the issue is.

i had ``self = try container.decode(URL.self, forKey: .self)

but it should be self.self = try container.decode(URL.self, forKey: .self)

I figured out what the issue is.

i had

`self` = try container.decode(URL.self, forKey: .`self`)

but it should be

self.`self` = try container.decode(URL.self, forKey: .`self`)

Which has fixed the problem.

It seems Swift does not appreciate the use of self between ticks.

I tested with another reverved keyword (var)

class Links: ObservableObject, Codable {
     @Published var `self`: URL
     @Published var `var`: URL
     
     required init(from decoder: Decoder) throws {
          let container = try decoder.container(keyedBy: CodingKeys.self)
          
          `self` = try container.decode(URL.self, forKey: .`self`)
          `var` = try container.decode(URL.self, forKey: .`var`)
          
     }
     
     private enum CodingKeys: String, CodingKey {
          case `self`
          case `var`
     }
     
     func encode(to encoder: Encoder) throws {
          var container = encoder.container(keyedBy: CodingKeys.self)
          try container.encode(`self`, forKey: .`self`)
          try container.encode(`var`, forKey: .`var`)
     }
}

No error on var, only on self.

You should post the question on Swift.org. There may be a specific limitation for self ?

Note: in anycase, using such keywords may not be the best way to go…

The backticks don't have any direct relevance to the error messages you're seeing. If xxx is a declared property name known to the compiler, then both of the following:

    xxx
    `xxx`

refer to that same property name. You only need the backticks when the compiler can't tell whether you mean the variable name or some Swift keyword.

If you wrote this, therefore:

      `self` = try container.decode(URL.self, forKey: .`self`)

you'd be writing the same thing as:

      self = try container.decode(URL.self, forKey: .`self`)

That is, the compiler thinks you're trying to replace the object of type Links with a different one. Since you're not allowed to do that in a designated initializer, the compiler gives an error. (You can replace self in a convenience initializer, but that's a different discussion.)

The compiler didn't know that you were trying to replace the self property of the self object. To do that, you must be explicit by saying it is the self property of the self object! You would expect to be able to write this as:

      self.self = try container.decode(URL.self, forKey: .`self`)

However, for historical reasons, the compiler treats self.self as simply self, so that doesn't do what you want. To tell the compiler that you mean your self property, you have to disambiguate with more backticks:

      self.`self` = try container.decode(URL.self, forKey: .`self`)

As Claude says, a less confusing option here would be to use a different property name instead of self. You can specify a different property name from the encoding key name, ending up with something a bit more readable:

class Links: ObservableObject, Codable {
    @Published var myself: URL
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        myself = try container.decode(URL.self, forKey: .myself)
    }
    
    private enum CodingKeys: String, CodingKey {
        case myself = "self"
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(myself, forKey: .myself)
    }
}

Thank you! for the suggestion on renaming the variable. I'm afraid i'm new to Swift and didn't know i could map it to another name. I would rather do that. Incidentally i did manage to get this working by using self.self.

Use of `self` - Confusion
 
 
Q