Why is there a memory leak at String creation in swift?
I tested your code and gone through few threads and my understanding is that you have to optional binding if let
clause, when using string interpolation instead of using optional variables directly. For String concatenation, if we use optionals directly there is no problem. The problem is with interpolation.
var description: String {
if let id = self.id, let name = self.name {
return "(\(id)) \(name)"
}
return "NO AVAILABLE DESCRIPTION"
}
You may get more info here memory leak in Swift String interpolation.
Seems like a bug and may be in future release it will be solved.
Why storing substrings may lead to memory leak in Swift?
Swift Arrays, Sets, Dictionaries and Strings have value semantics, but they're actually copy-on-write wrappers for reference types. In other words, they're all struct
wrappers around a class
. This allows the following to work without making a copy:
let foo = "ABCDEFG"
let bar = foo
When you write to a String
, it uses the standard library function isUniquelyReferencedNonObjC
(unless it's been renamed again) to check if there are multiple references to the backing object. If so, it creates a copy before modifying it.
var foo = "ABCDEFG"
var bar = foo // no copy (yet)
bar += "HIJK" // backing object copied to keep foo and bar independent
When you use a Substring (or array slice), you get a reference to the entire backing object rather than just the bit that you want. This means that if you have a very large string and you have a substring of just 4 characters, as long as the substring is live, you're holding the entire string backing buffer in memory. This is the leak that this warns you about.
Swift - iterating through characters in string causes memory leak
It's instruments bug(there is a lot of issues). Your code is OK.
Memory leaks when using optionals in string interpolation
Answering my own question...
It seems conditional binding is the right way to go when using string interpolation, rather than using the optionals directly. Not sure why the compiler even allows that.
Note: If someone has a better answer or better explanation, please add a new answer.
init(boundHost: String?, port: UInt16)
{
if boundHost {
self.boundHost = boundHost!
}
self.port = port
if let constBoundHost = self.boundHost
{
println("Server created with host: \(constBoundHost) and port: \(self.port).")
}
else
{
println("Server created with host: * and port: \(self.port).")
}
}
Memory leak on [String] constant
I did as @werediver mentioned, added a huge loop calling this method, and the heap didn't move, nor the number of leaks, so as he mentioned, this was a misleading diagnostic. No action needed about it.
Memory leaks when assigning text to UILabel (iOS, Swift 4, Xcode 9)
Maybe I am wrong, but I think this:
Weak will not increase the reference counter. Therefore, assigning a object label to a weak var label, does not make sense. This is because weak var label will be nil, because the object you created does not have any reference (and therefore it will deinitialize)
Let's count how many reference you have in your code to your created object Label.
label = UILabel() // 1
view.addSubview(label!) // 2
var textForLabel: String? = "Hello"
label?.text = textForLabel
//attempt to free the memory
textForLabel = nil
label = nil // 1
You have 1 reference left in your view to your object Label. Before you do label = nil, call label?.removeFromSuperview(). I think than you have 0 references -> it will deinit.
edit:
Add below subclass of UILabel into your code:
class MyLabel: UILabel {
deinit {
print("I am gone!")
}
}
Change var label: UILabel?
to var label: MyLabel?
And
label = UILabel()
to label = MyLabel()
And check to logs. Do you see the print "I am gone!"?
Edit2: this prints "I am gone!" in a empty project with this only as code:
import UIKit
class ViewController: UIViewController {
var label: MyLabel?
override func viewDidLoad() {
super.viewDidLoad()
label = MyLabel()
view.addSubview(label!)
let textForLabel: String? = "Hello"
label?.text = textForLabel
//EDIT: added after @J.Doe and @Sh-Khan answers, but it's still leaking
label?.removeFromSuperview()
label = nil
}
}
class MyLabel: UILabel {
deinit {
print("I am gone!")
}
}
Related Topics
Swift: Uicollectionview Selecting Cell Indexpath Issues
Check Availability in Switch Statement
Enumerateobjectsusingblock in Swift
Why Does Filters in Swift Iterate the Collection Twice
How to Add Auto-Complete Comment in Xcode (Swift)
Swiftui - How to Set the Title of a Navigationview to Large Title (Or Small)
Cannot Assign to Property: 'Self' Is Immutable, I Know How to Fix But Needs Understanding
How to Mock Uiapplication in Swift
Skaction Runaction Does Not Execute Completion Block
How to Recognize Continuous Touch in Swift
What's the Difference Between a Required Initializer and a Designated Initializer
How in Swift to Convert Int16 to Two Uint8 Bytes
Combining Two Conditions in Nspredicate
Synchronize Properties in Swift 3 Using Gcd
Is Swift Inout Parameter a Variable or a Pointer
Using Cocoa Nssavepanel in Sandbox Causes Assertion Failure
An Nsmanagedobject of Class 'Classname' Must Have a Valid Nsentitydescription.' Error