Swift class: reference cycle - class

When I run the below program, it produces segmentation fault. Can you please help me figure out why? Thanks
class Animal:NSObject{
var name:String!
var age:UInt!
weak var spouse:Animal?
init(name:String,age:UInt){
self.name=name
self.age=age
}
func description() ->String{ //to become printable
return "name= \(name) and age=\(age) spouse=\(spouse)"
}
}
let dog=Animal(name:"Lucky",age:3)
let cat=Animal(name:"Branson",age:4)
dog.spouse=cat
cat.spouse=dog //It doesnt crash if I comment this line out
println(dog)

The problem is infinite recursion in your printing. Once you set up the full cycle, to print an animal, you print its spouse, which prints its spouse, which print’s its spouse etc. forever until you run out of stack space and crash.
You need to break that by printing out an animal’s spouse without calling the full print of that animal, something like this:
class Animal: NSObject {
// you should avoid using implicitly unwrapped optionals
// unless you absolutely have to for a specific reason that
// doesn’t appear to apply here (so remove the !s)
var name: String
var age: UInt
weak var spouse: Animal?
init(name: String, age: UInt) {
self.name = name
self.age = age
}
}
// to make something printable, you need to conform
// to the Printable protocol
extension Animal: Printable {
// And make description is a var rather than a function
override var description: String {
let spousal_status = spouse?.name ?? "None"
return "name=\(name) and age=\(age), spouse=\(spousal_status)"
}
}
let dog = Animal(name: "Lucky", age: 3)
let cat = Animal(name: "Branson", age: 4)
dog.spouse = cat
dog.description
cat.spouse = dog
println(dog) // Prints name=Lucky and age=3, spouse=Branson
Note, you have to implement Printable fully with the protocol and var to avoid this problem, otherwise you’ll get the default implementation, which will still experience the issue.
btw, Swift style convention is to put spaces between things like =, ->, before { etc. (and in fact you can occasionally cause compilation problems if you don’t). Jury’s still out on a: b vs a:b though I find the latter a bit harder to read.

Your code triggers a stack overflow. The description method contains the spouse description, which will in turn trigger the description of its spouse and so on in a never ending cycle. Try this:
func description() -> String {
return "name= \(name) and age=\(age) spouse=\(spouse?.name)"
}

Related

Extending a constrained protocol for an array argument is not possible

I'm going to explain it by an example. We have a protocol for force having firstName and lastName like:
protocol ProfileRepresentable {
var firstName: String { get }
var lastName: String { get }
}
the type we are going to use have these two, but in an optional form:
struct Profile {
var firstName: String?
var lastName: String?
}
so after conforming to the ProfileRepresentable, we will extend the ProfileRepresentable and try to return the value and a default one for nil state:
extension Profile: ProfileRepresentable { }
extension ProfileRepresentable where Self == Profile {
var firstName: String { self.firstName ?? "NoFirstName" }
var lastName: String { self.lastName ?? "NoLastName" }
}
So far so good
Now there is a similar flow for a list of Profiles.
protocol ProfilerRepresentable {
var profiles: [ProfileRepresentable] { get }
}
struct Profiler {
var profiles: [Profile]
}
First issue
conforming to ProfilerRepresentable does NOT automatically done the implementation as expected (since Profile already conforms to ProfileRepresentable)
extension Profiler: ProfilerRepresentable { }
Second Issue
Following the previous pattern, extending ProfilerRepresentable is not working as expected and it raises a warning:
⚠️ All paths through this function will call itself
extension ProfilerRepresentable where Self == Profiler {
var profiles: [ProfileRepresentable] { self.profiles }
}
How can I achieve the goal for arrays by the way ?
Here is possible solution. Tested with Xcode 12 / swift 5.3
protocol ProfilerRepresentable {
associatedtype T:ProfileRepresentable
var profiles: [T] { get }
}
extension Profiler: ProfilerRepresentable { }
struct Profiler {
var profiles: [Profile]
}
[Profile] is not a subtype of [ProfileRepresentable]. (See Swift Generics & Upcasting for a related but distinct version of this question.) It can be converted through a compiler-provided copying step when passed as a parameter or assigned to a variable, but this is provided as a special-case for those very common uses. It doesn't apply generally.
How you should address this depends on what precisely you want to do with this type.
If you have an algorithm that relies on ProfilerRepresentable, then Asperi's solution is ideal and what I recommend. But going that way won't allow you to create a variable of type ProfileRepresentable or put ProfileRepresentable in an Array.
If you need variables or arrays of ProfilerRepresentable, then you should ask yourself what these protocols are really doing. What algorithms rely on these protocols, and what other reasonable implementations of ProfileRepresentable really make sense? In many cases, ProfileRepresentable should just be replaced with a simple Profile struct, and then have different init methods for creating it in different contexts. (This is what I recommend if your real problem looks a lot like your example, and Asperi's answer doesn't work for you.)
Ultimately you can create type erasers (AnyProfile), but I suggest exploring all other options (particularly redesigning how you do composition) first. Type erasers are perfect if your goal is to erase a complicated or private type (AnyPublisher), but that generally isn't what people mean when they reach for them.
But designing this requires knowing a more concrete goal. There is no general answer that universally applies.
Looking at your comments, there no problem with having multiple types for the same entity if they represent different things. Structs are values. It's fine to have both Double and Float types, even though every Float can also be represented as a Double. So in your case it looks like you just want Profile and PartialProfile structs, and an init that lets you convert one to the other.
struct Profile {
var firstName: String
var lastName: String
}
struct PartialProfile {
var firstName: String?
var lastName: String?
}
extension Profile {
init(_ partial: PartialProfile) {
self.firstName = partial.firstName ?? "NoFirstName"
self.lastName = partial.lastName ?? "NoLastName"
}
}
extension PartialProfile {
init(_ profile: Profile) {
self.firstName = profile.firstName
self.lastName = profile.lastName
}
}
It's possible that you have a lot of these, so this could get a bit tedious. There are many ways to deal with that depending on exactly the problem you're solving. (I recommend starting by writing concrete code, even if it causes a lot of duplication, and then seeing how to remove that duplication.)
One tool that could be useful would be Partial<Wrapped> (inspired by TypeScript) that would create an "optional" version of any non-optional struct:
#dynamicMemberLookup
struct Partial<Wrapped> {
private var storage: [PartialKeyPath<Wrapped>: Any] = [:]
subscript<T>(dynamicMember member: KeyPath<Wrapped, T>) -> T? {
get { storage[member] as! T? }
set { storage[member] = newValue }
}
}
struct Profile {
var firstName: String
var lastName: String
var age: Int
}
var p = Partial<Profile>()
p.firstName = "Bob"
p.firstName // "Bob"
p.age // nil
And a similar converter:
extension Profile {
init(_ partial: Partial<Profile>) {
self.firstName = partial.firstName ?? "NoFirstName"
self.lastName = partial.lastName ?? "NoLastName"
self.age = partial.age ?? 0
}
}
Now moving on to your Array problem, switching between these is just a map.
var partials: [Partial<Profile>] = ...
let profiles = partials.map(Profile.init)
(Of course you could create an Array extension to make this a method like .asWrapped() if it were convenient.)
The other direction is slightly tedious in the simplest approach:
extension Partial where Wrapped == Profile {
init(_ profile: Profile) {
self.init()
self.firstName = profile.firstName
self.lastName = profile.lastName
self.age = profile.age
}
}
If there were a lot of types, it might be worth it to make Partial a little more complicated so you could avoid this. Here's one approach that allows Partial to still be mutable (which I expect would be valuable) while also allowing it to be trivially mapped from the wrapped instances.
#dynamicMemberLookup
struct Partial<Wrapped> {
private var storage: [PartialKeyPath<Wrapped>: Any] = [:]
private var wrapped: Wrapped?
subscript<T>(dynamicMember member: KeyPath<Wrapped, T>) -> T? {
get { storage[member] as! T? ?? wrapped?[keyPath: member] }
set { storage[member] = newValue }
}
}
extension Partial {
init(_ wrapped: Wrapped) {
self.init()
self.wrapped = wrapped
}
}
I don't love this solution; it has a weird quirk where partial.key = nil doesn't work to clear a value. But I don't have a nice fix until we get KeyPathIterable. But there are some other routes you could take depending on your precise problem. And of course things can be simpler if Partial isn't mutable.
The point is that there's no need for protocols here. Just values and structs, and convert between them when you need to. Dig into #dynamicMemberLookup. If your problems are very dynamic, then you may just want more dynamic types.

Clear way to update some nested struct from a bigger struct in place

Say we have some complex struct with multiple nested levels(for simplicity, in the example will be only one level, but there could be more).
Example. We have a data structure:
struct Company {
var employee: [Int: Employee]
}
struct Employee {
var name: String
var age: Int
}
var company = Company(employee: [
1: Employee(name: "Makr", age: 25),
2: Employee(name: "Lysa", age: 30),
3: Employee(name: "John", age: 28)
])
Now we want to create a function which updates some Employee of the company in place. We could write it using an inout param:
func setAge(_ age: Int, forEmployee employee: inout Employee) {
employee.age = age
}
setAge(26, forEmployee: &company.employees[1]!)
This works, but as you can see we need to unwrap expression 'company.employees[1]' before passing it by ref. This forced unwrap can produce runtime error if there is no such employee for the provided key.
So we need to check if the employee exists:
if company.employees[1] != nil {
setAge(26, forEmployee: &company.employees[1]!)
}
This also works, but this code is kind of ugly because we need to repeat the expression 'company.employees[1]' two times.
So the question is: Is there some way to get rid of this repetition?
I tried to use optional inout param in the modifying function but could not get it working.
Based on your comments, like
What I wanted in the first place is just to have a reference to a substructure of a bigger structure so the part of code that is dealing with the substructure could know nothing about where is this substructure located in the bigger structure.
and
It would be ideal if I just could create a local inout var. Like if var employ: inout Employee? = company.employee[1] { // make whatever I want with that employee }.
I think that what you want is a generic update function. In the community this is part of the family of utility functions referred as with (https://forums.swift.org/t/circling-back-to-with/2766)
The version that you need in this case is one that basically guards on nil, so I suggest something like
func performUpdateIfSome <T> (_ value: inout T?, update: (inout T) throws -> Void) rethrows {
guard var _value = value else { return }
try update(&_value)
value = _value
}
with this utility then what you wanted to do would be done with
performUpdateIfSome(&company.employees[1], update: { $0.age = 26 })
Note
If you want to abstract away how to access the employee but not the company, then keypaths are an option as well :)
You need to hide the implementation and let the struct handle the logic with specific error handling strategy, like throwing an error or simply return true/false depending on success or simply ignore any problems. I don't know what the Int key stands for but here I guess it's an ID of some sort, so add this to Company struct
mutating func setAge(_ age: Int, forId id: Int) -> Bool {
if employee.keys.contains(id) {
employee[id]?.age = age
return true
}
return false
}
I would simply add extension to Employee which set employee's age
extension Employee {
mutating func setAge(_ age: Int) {
self.age = age
}
}
Then you can use optional chaining for calling. So if value for key 1 doesn't exist, nothing happens and code goes on
company.employee[1]?.setAge(26)
Edit:
If your goal is just to change some property and then return object, simply create method which takes optional parameter and returns optional value
func setAge(_ age: Int, forEmployee employee: inout Employee?) -> Employee? {
employee?.age = age
return employee
}
if let employee = setAge(26, forEmployee: &company.employees[1]) { ... }

How to init a struct in swift 4.2

What I want:
To initialise a struct before use. But I really don't know how, even after a lot of trying and searching.
Example of the struct:
struct Person: Decodable {
let name: String
let age: Int
}
I want to use this struct global in my script. The way I think it would have been is like this (but it does not work, because of line 3):
import UIKit
class ViewController: UIViewController {
let personExample: Person()
func configure(person: Person) {
self.personExample = person
}
override func viewDidLoad() {
super.viewDidLoad()
print(self.personExample)
}
}
The syntax here is simply incorrect:
let personExample: Person()
What you meant was this:
let personExample: Person
Person() is the result of calling init(), which is a value, not a type, and isn't a valid initializer for this type anyway. Person is the type, which is what you want for a declaration.
However, what you've written here doesn't quite line up with the description. If you want a "global," this is actually an instance variable. What you may have meant here is the following:
var personExample = Person(name: "Bob", age: 21)
That would assign personExample to that value (and through type inference, assign the type to Person). I've used var here because configure(person:) tries to modify it.
You also may be confused about initialization of instance variables in view controllers when using storyboards. If that's your issue (for example, you're seeing errors about personExample not being set during initialization), you'll need to explain a little more about your situation and we can help you with that.
You need
var personExample: Person?
func configure(person: Person) {
self.personExample = person
}
first this let personExample: Person() is an incorrect syntax and if you changed to
var personExample: Person
it'll raise an error as it must be initated in the vc init methods , also if you don't implement coding , remove : Decodable {

Literal Convertibles in Swift

I want to know how Literal Convertibles work in Swift. The little I know is that the fact that, in var myInteger = 5, myInteger magically becomes an Int is because Int adopts a protocol, ExpressibleByIntegerLiteral and we don't have to do var myInteger = Int(5). Similarly String, Array, Dictionary etc all conform to some Literal protocols.
My Question is
Am I right in my little understanding of Literal Convertibles?
How can we implement these in our own types. For example
class Employee {
var name: String
var salary: Int
// rest of class functionality ...
}
How can I implement Literal Protocols to do var employee :Employee = "John Doe" which will automatically assign "John Doe" to employee's name property.
You are partially correct in your understanding of the various ExpressibleBy...Literal protocols. When the Swift compiler parses your source code into an Abstract Syntax Tree, it already identified what literal represents what data type: 5 is a literal of type Int, ["name": "John"] is a literal of type Dictionary, etc. Apple makes the base type conform to these protocols for the sake of completeness.
You can adopt these protocols to give your class an opportunity to be initialized from a compile-time constant. But the use case is pretty narrow and I don't see how it applies to your particular situation.
For example, if you want to make your class conform to ExpressibleByStringLiteral, add an initializer to set all your properties from a String:
class Employee: ExpressibleByStringLiteral {
typealias StringLiteralType = String
var name: String
var salary: Int
required init(stringLiteral value: StringLiteralType) {
let components = value.components(separatedBy: "|")
self.name = components[0]
self.salary = Int(components[1])!
}
}
Then you can init your class like this:
let employee1: Employee = "John Smith|50000"
But if you dream about about writing something like this, it's not allowed:
let str = "Jane Doe|60000"
let employee2: Employee = str // error
And if you pass in the wrong data type for salary, it will be a run time error instead of a compile-time error:
let employee3: Employee = "Michael Davis|x" // you won't know this until you run the app
TL, DR: it is a very bad idea to abuse these ExpressibleBy...Literal types.
This can be a scenario to work with Convertibles in custom types.
struct Employee : ExpressibleByStringLiteral {
var name: String = ""
init() {}
init(stringLiteral name: String) {
self.name = name
}
}
func reportName(_ employee: Employee) {
print("Name of employee is \(employee.name)")
}
reportName("John Doe") //Name of employee is John Doe

Weak references in Swift playground don't work as expected

I have been following the weak referencing example from the Intermediate Swift WWDC session in a Playground. I modified the code slightly as follows:
class Apartment {
let address: Int
init(address: Int) {
self.address = address
}
weak var tenant: Person?
}
class Person {
let name: String
init(name: String){
self.name = name
}
weak var home: Apartment?
func moveIn(apt: Apartment) {
self.home = apt
apt.tenant = self
}
}
var renters = ["John Appleseed": Person(name: "John Appleseed")]
var apts = [16: Apartment(address: 16)]
renters["John Appleseed"]!.moveIn(apts[16]!)
renters["John Appleseed"] = nil // memory should be released here
// then apts[16].tenant should be nil
if let tenantName = apts[16]!.tenant?.name {
// this should only execute if the Person object is still in memory
println("\(tenantName) lives at apartment number \(apts[16]!.address)")
} else {
// and this line should execute if the memory is released as we expect
println("Nobody lives at apartment number \(apts[16]!.address)")
}
// Console output in Playground: John Appleseed lives at apartment number 16
// Console output in standalone app: Nobody lives at apartment number 16
From my understanding of weak referencing, the memory allocated for the instance of Person should be released when it is removed from the renters dictionary because the only other reference to it is weak. However, the output of the programme is different if it is run as a standalone command line application vs. in a Playground (see comments).
I believe the top-level function (REPL/playground) is keeping a strong reference to facilitate interactive behavior, and cleaning up when the frame returns. This behavior eliminates memory leaks in the interactive environment.
I copied Viktor's simple example and used the xcrun swift REPL.
In REPL mode, I wrapped the logic in a function and it works as expected. If/when you care when the memory is cleaned up, I would suggest wrapping your logic in a function.
// declaration of the types
class Person {
let name: String
weak var home: Apartment?
init(pName: String){
name = pName
}
}
class Apartment {
let postalCode: Int
init(pPostalCode: Int) {
postalCode = pPostalCode
}
}
func testArc() {
// create Person object
var personJulius: Person = Person(pName: "Julius")
// create Apartment object
var apartmentBerlin: Apartment? = Apartment(pPostalCode: 10777)
// connect Apartment object and Person object
personJulius.home = apartmentBerlin
// Set only strong reference of Apartment object to nil
apartmentBerlin = nil
// Person object should now have nil as home
if personJulius.home != nil {
println("Julius does live in a destroyed apartment")
} else {
println("everything as it should")
}
}
//outputs "everything as it should"
testArc()
I guess that the Playground itself keeps a strong reference to the object, so the code behaves differently? If that's the case, this could cause some unexpected problems!
I tried an a bit less complex setup of the code.
But did have the same problem in the Playground file, but not in a real command line project.
In a command line project, the output was everything as it should, and in the playground it was Julius does live in a destroyed apartment.
import Cocoa
// declaration of the types
class Person {
let name: String
weak var home: Apartment?
init(pName: String){
name = pName
}
}
class Apartment {
let postalCode: Int
init(pPostalCode: Int) {
postalCode = pPostalCode
}
}
// create Person object
var personJulius: Person = Person(pName: "Julius")
// create Apartment object
var apartmentBerlin: Apartment? = Apartment(pPostalCode: 10777)
// connect Apartment object and Person object
personJulius.home = apartmentBerlin
// Set only strong reference of Apartment object to nil
apartmentBerlin = nil
// Person object should now have nil as home
if personJulius.home != nil {
println("Julius does live in a destroyed apartment")
} else {
println("everything as it should")
}
It is not only weak reference. In playground, the deinit does not work. Since set a variable to nil can not let deinit run, it is not the time weak reference should work.
class MyClass {
init() {
println("ready")
}
deinit {
println("OK")
}
}
var aClass: MyClass?
aClass
aClass = MyClass()
aClass = nil
Update 3: As of 11.3.1: Playground seems to be deiniting objects as expected, as far as I can tell. My original and out of date answer follows: In Xcode 10.1 Playgrounds, I can confirm that deinits are still behaving strangely and I can't use Playgrounds to test whether things are being properly deallocated. Update 1: From another similar thread, I learned that Xcode>New>Project>macOS>Command Line Tool, is a relatively lightweight way to create a generic testing environment that works fine for testing deallocation.
class Person {
let name: String
init(named name: String) { self.name = name }
var house: House?
deinit { print("\(name) is being deinitialized") }
}
class House {
let address: String
init(address: String) { self.address = address }
weak var tenant: Person?
deinit { print("House \(address) is being deinitialized") }
}
func move(_ person: Person, into house: House){
house.tenant = person
person.house = house
}
When Person and House are unconnected, deinits work properly.
However, if I move Buffy into the house, and delete Buffy, because tenant is weak, the Buffy object should be deinited and tenant set to nil. As you can see neither happens.
Even after I delete house (line 38), neither are deinited.
Weak references are behaving like strong references in the Playground.
Wrapping the Run code in a function does not change anything in this example. Update 2: In Xcode 11, As wbennet suggests above, if you wrap your run code in a func and call it, deallocations work for weak references as defined, in Playground.