Why does initializing this swift object produce an ARC of 2 instead of 1? - ios

I was running into a problem in my project and I realized that an object is not being deallocated as needed. I decided to test the ARC of the object and just after initialization it is 2. In this trivial example below the same is true. Why is the ARC 2 and not 1?
import SpriteKit
class LevelBuilder:SKNode{
var testNode:SKSpriteNode?
init(with color:SKColor){
super.init()
self.testNode = SKSpriteNode(color: color, size: CGSize(width: 2, height: 2))
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
let test = LevelBuilder(with: .red)
print("ARC: \(CFGetRetainCount(test))")
It prints ARC: 2

There is no such thing as "the ARC of the object." What you're thinking about is the retain count. It is hard to imagine a number more meaningless than the retain count. It is either zero (in which case the object is gone, so you'll never see that), or it is "not zero."
The retain count is the number of ownership claims that have been put on an object. Any part of the system is free to make an ownership claim at any time. Any part of the system can remove their ownership claim at any time. There's a whole thing called the autorelease pool that holds ownership claims and will automatically release those claims "at some point in the future." It is completely normal for an object to have several autorelease retains on it at any given time. That will increase the retain count, but the retain count will drop later.
If retain counts were meaningless under MRC (and they were), they're completely bonkers under ARC, where the compiler is free to optimize them out anytime it can prove it doesn't matter, and often injects extra retains when it can't prove they're not needed (particularly related to function calls). So the actual value is even more meaningless. For example, under ARC, it is completely appropriate for test to have an extra retain attached to it before calling CFGetRetainCount just to make sure that test isn't released too quickly.
If you have a memory management problem, you want to use tools like the memory graph debugger (and just looking for strong references and especially strong loops). Checking the retain count will only lie to you.
In your particular case, we can explore it a bit with swiftc -emit-sil, starting at the point that we do string interpolation (i.e. the "" in the last line):
// function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
%34 = function_ref #$SSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $#convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, #thin String.Type) -> #owned String // user: %35
%35 = apply %34(%30, %31, %32, %33) : $#convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, #thin String.Type) -> #owned String // user: %37
%36 = alloc_stack $String // users: %39, %37, %41
store %35 to %36 : $*String // id: %37
// function_ref specialized String.init<A>(stringInterpolationSegment:)
%38 = function_ref #$SSS26stringInterpolationSegmentSSx_tcs23CustomStringConvertibleRzs20TextOutputStreamableRzlufCSS_Tg5 : $#convention(method) (#owned String, #thin String.Type) -> #owned String // user: %40
%39 = load %36 : $*String // user: %40
%40 = apply %38(%39, %29) : $#convention(method) (#owned String, #thin String.Type) -> #owned String // user: %42
dealloc_stack %36 : $*String // id: %41
store %40 to %28 : $*String // id: %42
%43 = integer_literal $Builtin.Word, 1 // user: %44
%44 = index_addr %28 : $*String, %43 : $Builtin.Word // user: %58
%45 = metatype $#thin String.Type // user: %56
%46 = load %3 : $*LevelBuilder // users: %48, %47
=========
strong_retain %46 : $LevelBuilder // id: %47
%48 = init_existential_ref %46 : $LevelBuilder : $LevelBuilder, $AnyObject // user: %49
%49 = enum $Optional<AnyObject>, #Optional.some!enumelt.1, %48 : $AnyObject // users: %52, %51
// function_ref CFGetRetainCount
%50 = function_ref #CFGetRetainCount : $#convention(c) (Optional<AnyObject>) -> Int // user: %51
%51 = apply %50(%49) : $#convention(c) (Optional<AnyObject>) -> Int // user: %54
release_value %49 : $Optional<AnyObject> // id: %52
=========
I've marked the important part with === lines. A strong retain is put on test. It's then wrapped up into a AnyObject? wrapper to pass to the C function (GetRetainCount). The function is called. And then the value of the Optional (i.e. test) is released. So you should expect one extra retain when you call GetRetainCount.
But if you re-compile this with -O, you'll notice that there is no strong_retain instruction. ARC sees that the extra retain isn't actually necessary and removes it. So that suggests that with optimization the retain count will be 1. I wonder if that's true:
$ swiftc main.swift
$ ./main
ARC: 2
$ swiftc -O main.swift
$ ./main
ARC: 1
Sure enough.

Maybe because you initialize your testNode which is a SKSpriteNode which might as well be referencing to SKNode under the hood. So you have first reference from your LevelBuilder class and the second one comes from the testNode.

Related

Can someone explain to me how this code works? Closure in Dart

I can't understand how the closure works in Dart. Why does BMW stay? This explanation causes my neurons to overheat. A lexical closure is a functional object that has access to variables from its lexical domain. Even if it is used outside of its original scope.
`void main() {
var car = makeCar('BMW');
print(makeCar);
print(car);
print(makeCar('Tesla'));
print(car('Audi'));
print(car('Nissan'));
print(car('Toyota'));
}
String Function(String) makeCar(String make) {
var ingane = '4.4';
return (model) => '$model,$ingane,$make';
}`
Console
Closure 'makeCar'
Closure 'makeCar_closure'
Closure 'makeCar_closure'
Audi,4.4,BMW
Nissan,4.4,BMW
Toyota,4.4,BMW
Calling car('Audi') is equal to calling (makeCar('BMW'))('Audi');
A lexical closure is a functional object that has access to variables from its lexical domain. Even if it is used outside of its original scope.
in simple english:
String make will stay valid as long as the returned function is not out of scope because the returned function has reference to String make.
In essence, you "inject" information needed for the newly created function. Your car knows that make is "BMW"
I think I figured it out. Here is an example where I left comments. Maybe it will help someone.
void main() {
var pr = funkOut(10); // assign a reference to an object instance
// of the Function class to the pr variable. pr is a closure because
// it is assigned a reference to an instance that contains a lexical
// environment (int a) and an anonymous function from this environment.
// 10 transfer to a
print(pr(5)); // 5 transfer to b //15
print(pr(10)); // 10 transfer to b //20
pr = funkOut(20);// 20 transfer to a
print(pr(5)); // 5 transfer to b //25
print(pr); // Closure: (int) => int
}
Function funkOut(int a) {
return (int b) => a + b;
}

Hash value of String that would be stable across iOS releases?

In documentation String.hash for iOS it says:
You should not rely on this property having the same hash value across
releases of OS X.
(strange why they speak of OS X in iOS documentation)
Well, I need a hasshing function that will not change with iOS releases. It can be simple I do not need anything like SHA. Is there some library for that?
There is another question about this here but the accepted (and only) answer there simply states that we should respect the note in documentation.
Here is a non-crypto hash, for Swift 3:
func strHash(_ str: String) -> UInt64 {
var result = UInt64 (5381)
let buf = [UInt8](str.utf8)
for b in buf {
result = 127 * (result & 0x00ffffffffffffff) + UInt64(b)
}
return result
}
It was derived somewhat from a C++11 constexpr
constexpr uint64_t str2int(char const *input) {
return *input // test for null terminator
? (static_cast<uint64_t>(*input) + // add char to end
127 * ((str2int(input + 1) // prime 127 shifts left almost 7 bits
& 0x00ffffffffffffff))) // mask right 56 bits
: 5381; // start with prime number 5381
}
Unfortunately, the two don't yield the same hash. To do that you'd need to reverse the iterator order in strHash:
for b in buf.reversed() {...}
But that will run 13x slower, somewhat comparable to the djb2hash String extension that I got from https://useyourloaf.com/blog/swift-hashable/
Here are some benchmarks, for a million iterations:
hashValue execution time: 0.147760987281799
strHash execution time: 1.45974600315094
strHashReversed time: 18.7755110263824
djb2hash execution time: 16.0091370344162
sdbmhash crashed
For C++, the str2Int is roughly as fast as Swift 3's hashValue:
str2int execution time: 0.136421

Swift : Recursively calling a function with an enum type as a parameter

I found this code at apple swift documentation
indirect enum ArithmeticExpression {
case Number(Int)
case Addition(ArithmeticExpression, ArithmeticExpression)
case Multiplication(ArithmeticExpression, ArithmeticExpression)
}
func evaluate(expression: ArithmeticExpression) -> Int {
switch expression {
case .Number(let value):
return value
case .Addition(let left, let right):
return evaluate(left) + evaluate(right)
case .Multiplication(let left, let right):
return evaluate(left) * evaluate(right)
}
}
// evaluate (5 + 4) * 2
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.Addition(five, four)
let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2))
print(evaluate(product))
// prints "18"
i don't quit understand how the recursion is happening in here and why a constant declaration is being declared as a parameter in the return statement in the returning line ?
Think of it as a tree. Nodes=Expressions. Constants=Leaves.
(image source ruslanspivak.com)
While traversing it - you examine each of the two operands. If it's an expression, you need to compute it, so you call on 'evaluate' with this operand. If it's a constant, think of it like a result - it's just a number, so no more calculations are needed.
In the end, we ALWAYS get to a constants (=leaves) it is then when the the stack starts to fold and the values results return "up" in the tree to add up to the total result.
For more diving into the subject I recommend googling "binary expression tree".
(By the way, the code example does not tend for priorities. The multiplication is computed before the addition only because the order of calls.
If we really wanted to take care of priorities : e.g. "(", ")" over "*" , "/", a stack for operations would have been needed here.)

Swift In-Out Parameters - use case

I recently learn about "In-Out Parameters" in Swift and I have question to you.
What are use case when "In-Out Parameters" is better than e.x. func that return value that you can assign to var?
Thank you for help.
I think a good use case for inout parameters is the swapTwoInts function provided by The Swift Programming Language.
func​ ​swapTwoInts​(​inout​ ​a​: ​Int​, ​inout​ ​b​: ​Int​) {
​ ​let​ ​temporaryA​ = ​a
​ ​a​ = ​b
​ ​b​ = ​temporaryA
​}
Given
var a = 0
var b = 1
you can easily call
swapTwoInt(&a, b: &b)
Scenario 2: without inout params
On the other hand, without inout parameters the function should be written as follow (more compact actually)
func swapTwoInt(a: Int, b: Int) -> (a:Int, b:Int) {
return (a:b, b:a)
}
but the use would require 3 lines of code instead of 1:
let swapped = swapTwoInt(a, b: b)
a = swapped.a // was swapped.b, fixed as suggested by Martin R
b = swapped.b
Considerations
As you can see, in Scenario 2 part of the logic of the function needs to be written outside of the function itself. This is not good because it creates an overhead of code to be written each time the function is called.

objc_setAssociatedObject retain atomic or nonatomic

When I use objc_setAssociatedObject, I know whether to use retain or assign, but I don't know how to decide between OBJC_ASSOCIATION_RETAIN and OBJC_ASSOCIATION_RETAIN_NONATOMIC. When should one or the other be used?
Executive summary: You must use OBJC_ASSOCIATION_RETAIN if you might call objc_setAssociatedObject on one thread, and objc_getAssociatedObject on another thread, simultaneously, with the same object and key arguments.
Gory details:
You can look at the implementation of objc_setAssociatedObject in objc-references.mm. But actually the difference between OBJC_ASSOCIATION_RETAIN and OBJC_ASSOCIATION_RETAIN_NONATOMIC only matters for objc_getAssociatedObject.
Here are the definitions of those constants in <objc/runtime.h>:
enum {
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
Note that 01401 is 0x0301 and 01403 is 0x0303. The source code breaks these down further:
enum {
OBJC_ASSOCIATION_SETTER_ASSIGN = 0,
OBJC_ASSOCIATION_SETTER_RETAIN = 1,
OBJC_ASSOCIATION_SETTER_COPY = 3, // NOTE: both bits are set, so we can simply test 1 bit in releaseValue below.
OBJC_ASSOCIATION_GETTER_READ = (0 << 8),
OBJC_ASSOCIATION_GETTER_RETAIN = (1 << 8),
OBJC_ASSOCIATION_GETTER_AUTORELEASE = (2 << 8)
};
So we can see that OBJC_ASSOCIATION_RETAIN_NONATOMIC is just OBJC_ASSOCIATION_SETTER_RETAIN, but OBJC_ASSOCIATION_RETAIN is actually OBJC_ASSOCIATION_SETTER_RETAIN | OBJC_ASSOCIATION_GETTER_RETAIN | OBJC_ASSOCIATION_GETTER_AUTORELEASE.
The OBJC_ASSOCIATION_GETTER_* bits are examined in _object_get_associative_reference:
id _object_get_associative_reference(id object, void *key) {
id value = nil;
uintptr_t policy = OBJC_ASSOCIATION_ASSIGN;
{
AssociationsManager manager;
AssociationsHashMap &associations(manager.associations());
disguised_ptr_t disguised_object = DISGUISE(object);
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
ObjcAssociation &entry = j->second;
value = entry.value();
policy = entry.policy();
if (policy & OBJC_ASSOCIATION_GETTER_RETAIN) ((id(*)(id, SEL))objc_msgSend)(value, SEL_retain);
}
}
}
if (value && (policy & OBJC_ASSOCIATION_GETTER_AUTORELEASE)) {
((id(*)(id, SEL))objc_msgSend)(value, SEL_autorelease);
}
return value;
}
So if you use OBJC_ASSOCIATION_RETAIN, it will retain and autorelease the associated object before returning it to you. But there's something else going on that's not obvious. Notice that the function creates a local instance of AssociationsManager (which is a C++ object stored on the stack). Here's the definition of AssociationsManager:
class AssociationsManager {
static spinlock_t _lock;
static AssociationsHashMap *_map; // associative references: object pointer -> PtrPtrHashMap.
public:
AssociationsManager() { spinlock_lock(&_lock); }
~AssociationsManager() { spinlock_unlock(&_lock); }
AssociationsHashMap &associations() {
if (_map == NULL)
_map = new AssociationsHashMap();
return *_map;
}
};
So you can see that when the function creates its AssociationsManager, it acquires a lock, which it holds until the manager is destroyed. The destruction happens after the function has retained the associated object.
The same lock is used when setting a new associated object for the key. This lock prevents a race condition, where one thread is getting the associated object while another is replacing it and causing the object to be deallocated.
If you don't prevent the race condition, then someday your multithreaded app will crash (or worse) by trying to access a deallocated object. You can use OBJC_ASSOCIATION_RETAIN to prevent the race condition, or you can ensure in some other way that you never set the association on one thread while getting it on another.
If the value you're trying to store would use the nonatomic attribute if it were a property, use OBJC_ASSOCIATION_RETAIN_NONATOMIC, otherwise use OBJC_ASSOCIATION_RETAIN.
There are little reasons to use atomicity (OBJC_ASSOCIATION_RETAIN). In most cases thread safeness cannot be accomplished by making the data access thread safe. It is a bigger subject.
For properties there is the side-effect of atomicity that the read value is autoreleased. But neither is that documented for associated objects nor it is useful in ARC times.
So my advice: Use OBJC_ASSOCIATION_RETAIN_NONATOMIC.

Resources