Detecting retain cycles and improved logging

:  ~ 45 sec read

I think adding a deinit method, with a print statement everywhere is a decent first barrier against retain cycles:

deinit {
  print("Object X has been deinitialized.")
}

This way, if you expect object x to deinit at some point, but it doesn't, you at least know you need to start searching.

Now, for the improved printing, to make this a bit cleaner and easier:

func customPrint(
  object: Any,
  function: String = #function,
  _ file: String = #file,
  _ line: UInt = #line) {
  
  #if DEBUG
    let filename = NSURL(string: file)?.lastPathComponent?
      .stringByReplacingOccurrencesOfString(".swift", withString: "") ?? ""
	print("-- \(filename).\(function) [\(line)] - \(object)")
  #endif
}

This will make sure no printing happens in production, and if we replace the print call above, the output will look like this:

deinit {
  customPrint("") 
  // ObjectX.deinit [60]
}