Cache that can purge unused objects by demand - swift

I need to create a cache, that could save some objects, but then, at some point when I have memory warning or simply user wants it, I would like to purge all instances that are used only in the cache at the moment.
In other words: I need to deinit objects with ARC count == 1. The problem is that based on my googling of this project, it is not possible in pure Swift to get the retain count of an object.
From my experience I see that it is not possible by default in Swift. In objective-c I was using Proxy object, that was returned from cache, it had such overriden methods:
// Forward class checks for assertions.
-(BOOL)isKindOfClass:(Class)aClass {return [_target isKindOfClass:aClass];}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return(_target);
}
But is of course not applicable to Swift ideology.
One thought that I have is to base my cache on array of WeakBoxes, but this way unused objects will be deallocated when they become unused and that doesnt meet my requirements.
Can somebody guide me to some Swift possibilities, that I'm not aware of, to achieve such thing?

You do not need to mess with the retain count of the object. Your cache can just hold a strong reference. This guarantees that the retain count is always at least one. When you get a memory warning you just loop through every pointer in the cache and set it to nil. Assuming no one else has a strong reference this decrements the reference count to zero and the object immediately calls deinit and goes out of memory. If you really really want the object to go out of memory when the cache does a purge, make sure only the cache has a strong reference to the items being held and that everyone else takes a weak reference. I have a lazily loaded array of ViewControllers that does something similar:
fileprivate var controllers = [UIViewController?](repeating: nil, count: DashboardInfo.Category.allValues.count)
override func didReceiveMemoryWarning() {
//Release every off screen controller
for index in 0 ..< controllers.count {
if controllers[index] != currentController {
controllers[index]?.removeFromParentViewController()
controllers[index]?.view.removeFromSuperview()
controllers[index] = nil
}
}
}

Related

Swift - Capture List self clarification

After reading some articles and developer guide of apple, i'm still confused about Capture List in closure.
What does it mean "capture", how does it work behind the scene in terms of unowned self and weak self? how the closure use self without owning the object?
I thought it like making a copy of that object so when it get finished it's passed from the stack like value type, but i guess that i'm wrong.
I'm hoping that someone here can make it more easier and clear for understanding, or linked me to a good article that answering this specific question.
Thanks for advance
My understanding, and it might be a bit simplified, is that it is about ownership and holding on to an object, meaning that as long as we claim ownership of an object it can not be freed from memory even another part of the code sets it to nil or similar.
With weakwe say that it is okay to destroy the object and that we will only use it if it is still around.
So when declaring self as weak in a closure we say that if self is still around when it's time to execute the closure we do so normally otherwise the closure will silently be ignored without generating an error.
It's mainly to do with reference counting. Any instance that is used inside a closure (but was declared outside) is strongly referenced (i.e. its reference count is incremented). This can lead to retain cycles, e.g.
class MyClass {
var myClosure: (() -> Void)!
init() {
myClosure = {
self.foo()
}
}
func foo() {
}
}
In the above example the instance of MyClass retains a reference to myClosure and vice versa, meaning that the MyClass instance will stay in memory forever.
You can also have more complex/harder-to-spot retain cycles, so you need to really pay attention and if you ever have any doubts add some print calls to your class' deinit methods just to make sure (or use Instruments).
In order to avoid these issues you can mark objects being captured in closures as unowned or weak. This means that their reference count won't be increased and you can avoid these retain cycles. The above example could have either been done this way:
myClosure = { [weak self] in
self?.foo()
}
or, better yet for this example, this way:
myClosure = { [unowned self] in
self.foo()
}
While the first way is always safe and what you will more likely do, the unowned version is easy to reason in this example because you know that myClosure won't outlive self. However, if you're not 100% sure that self will always outlive the closure use weak.
Also note that you can mark how to capture multiple objects used inside the closure, just separate it by commas, e.g.
myClosure = { [weak self, unowned bar] in
self?.foo(bar)
}
If we keep in mind that captured values are strong references in closures by default, we can assume that this can create retain cycles (bad stuff).
A capture list is an array of variables you can pass into a closure. The purpose of capture lists is to change the strenght of the variables that are passed in. This is used to break retain cycles.
For instance:
// strong reference
[label = self.myLabel!] in
// weak reference
[weak label = self.myLabel!] in
// unowned reference
[unowned self] in

Array pass by value by default & thread-safety

Say I have a class which has an Array of object Photo:
class PhotoManager {
fileprivate var _photos: [Photo] = []
var photos: [Photo] {
return _photos
}
}
I read one article which says the following:
By default in Swift class instances are passed by reference and
structs passed by value. Swift’s built-in data types like Array and
Dictionary, are implemented as structs.
Meaning that the above getter returns a copy of [Photo] array.
Then, that same article tries to make the getter thread-safe by refactoring the code to:
fileprivate let concurrentPhotoQueue = DispatchQueue(label: "com.raywenderlich.GooglyPuff.photoQueue",
attributes: .concurrent)
fileprivate var _photos: [Photo] = []
var photos: [Photo] {
var photosCopy: [Photo]!
concurrentPhotoQueue.sync {
photosCopy = self._photos
}
return photosCopy
}
The above code explictly make a copy of self._photos in getter.
My questions are:
If by default swift already return an copy (pass by value) like the article said in the first place, why the article copy again to photosCopy to make it thread-safe? I feel myself do not fully understand these two parts mentioned in that article.
Does Swift3 really pass by value by default for Array instance like the article says?
Could someone please clarify it for me? Thanks!
I'll address your questions in reverse:
Does Swift3 really pass by value by default for Array instance like the article says?
Simple Answer: Yes
But I'm guessing that is not what your concern is when asking "Does Swift3 really pass by value". Swift behaves as if the array is copied in its entirety but behind the scenes it optimises the operation and the whole array is not copied until, and if, it needs to be. Swift uses an optimisation known as copy-on-write (COW).
However for the Swift programmer how the copy is done is not so important as the semantics of the operation - which is that after an assignment/copy the two arrays are independent and mutating one does not effect the other.
If by default swift already return an copy (pass by value) like the article said in the first place, why the article copy again to photosCopy to make it thread-safe? I feel myself do not fully understand these two parts mentioned in that article.
What this code is doing is insuring that the copy is done in a thread-safe way.
An array is not a trivial value, it is implemented as multi-field struct and some of those fields reference other structs and/or objects - this is needed to support an arrays ability to grow in size, etc.
In a multi-threaded system one thread could try to copy the array while another thread is trying to change the array. If these are allowed to happen at the same time then things easily can go wrong, e.g. the array could change while the copy is in progress, resulting in an invalid copy - part old value, part new value.
Swift per se is not thread safe; and in particular it will not prevent an array from being changed while a copy is being performed. The code you have addresses this by using a GCD queue so that during any alteration to the array by one thread all other writes or reads to the array in any other thread are blocked until the alteration is complete.
You might also be concerned that their are multiple copies going on here, self._photos to photoCopy, then photoCopy to the return value. While semantically this is what happens in practice there will probably only be one complex copy (and that will be thread safe) as the Swift system will optimise.
HTH
1) In code example what you provided will be returned copy of _photos.
As wrote in article:
The getter for this property is termed a read method as it’s reading
the mutable array. The caller gets a copy of the array and is protected
against mutating the original array inappropriately.
that's mean what you can access to _photos from outside of class, but you can't change them from there. Values of photos could be changed only inside class what make this array protected from it accidental changing.
2)Yes, Array is a value-type struct and it will be passed by value. You can easily check it in Playground
let arrayA = [1, 2, 3]
var arrayB = arrayA
arrayB[1] = 4 //change second value of arrayB
print(arrayA) //but arrayA didn't change
UPD #1
In article they have method func addPhoto(_ photo: Photo) what add new photo to _photos array what makes access to this property not thread-safe. That's mean what value of _photos could be changed on few thread in same time what will lead to issues.
They fixed it by writing photos on concurrentQueue with .barrier what make it thread-safely, _photos array will changed once per time
func addPhoto(_ photo: Photo) {
concurrentPhotoQueue.async(flags: .barrier) { // 1
self._photos.append(photo) // 2
DispatchQueue.main.async { // 3
self.postContentAddedNotification()
}
}
}
Now for ensure thread safety you need to read of _photos array on same queue. That's only reason why they refactored read method

When constructing a Swift UnsafeMutablePointer manually, is destroy/dealloc obligatory after alloc?

Let's say that in Swift I construct a C array manually and pass it, like this:
override func drawRect(rect: CGRect) {
let c = UIGraphicsGetCurrentContext()
var arr = UnsafeMutablePointer<CGPoint>.alloc(4)
arr[0] = CGPoint(x:0,y:0)
arr[1] = CGPoint(x:50,y:50)
arr[2] = CGPoint(x:50,y:50)
arr[3] = CGPoint(x:0,y:100)
CGContextStrokeLineSegments(c, arr, 4)
}
(I know I don't have to do that, but just bear with me.) If I don't call destroy and/or dealloc on this UnsafeMutablePointer, am I leaking the memory for four CGPoints?
The documentation for UnsafeMutablePointer is pretty clear:
/// This type provides no automated
/// memory management, and therefore the user must take care to allocate
/// and free memory appropriately.
So if you allocate but don’t deallocate, you will leak memory. There’s no auto-deallocation on destruction of the pointer object.
Re whether you should destroy before deallocating, it’s also pretty clear:
/// The pointer can be in one of the following states:
///
/// - memory is not allocated (for example, pointer is null, or memory has
/// been deallocated previously);
///
/// - memory is allocated, but value has not been initialized;
///
/// - memory is allocated and value is initialized.
But bear in mind you can transition back and forth between these states. So after allocating then initializing then de-initialzing (aka destroying) the objects, the memory is no longer in the “initialized” state, so you can either re-initialize or deallocate it. You can also allocate, then deallocate, without ever initializing.
And when calling dealloc:
/// Deallocate `num` objects.
...
/// Precondition: the memory is not initialized.
///
/// Postcondition: the memory has been deallocated.
Therefore you must call destroy on any initialized objects before calling dealloc. You are probably right in that since something like CGPoint is totally inert (just a struct of two floating point nums) it probably doesn’t do any harm not to call destroy before you call dealloc but you can’t be certain without knowing the implementation (of both the pointer struct and the compiler probably, since the standard lib is a quasi-part of the language there could be some baked-in optimizations), and generally, it’s just not a good habit to get into. Sooner or later you’ll forget to destroy a String, and then you’ll be sorry.
(none of this accounts for the move operations btw which combine initializing new memory with destroying old memory)
If you were hoping for some kind of automated self-cleanup of memory by UnsafePointer, I don’t think this would be possible as a) it’s a struct, so can’t implement a deinit to auto-deallocate when going out of scope, and b) it doesn’t track it’s own size – you have to track how much you allocate, and supply that back explicitly in the call to deallocate.
There is something in the standard library that does auto-deallocate memory without you having to do it yourself – HeapBufferStorage, the one and only class in the standard library. Presumably it’s a class specifically to benefit from an implementation of deinit. There’s also HeapBuffer to manage it with, and this has a handy isUniquelyReferenced() function that allows you to tell if it’s been copied (even though it’s a struct) and so would allow you to implement copy-on-write capability similar to arrays and strings.
In Swift 2 UnsafeMutablePointer can be made a bit less frustrating by pairing alloc/dealloc with the new defer keyword:
let ptr = UnsafeMutablePointer<T>.alloc(1)
defer { ptr.dealloc(1) }
This is for others like me who found this question/answer thread by searching CGContextStrokeLineSegments. If your purpose is to call this function in Swift, you don't have to construct a C array pointer even though the function's second parameter is an UnsafeMutablePointer. You can directly pass a Swift array into it, even a non-mutable one, instead of a C pointer with its allocation and deallocation. For example:
override func drawRect(rect: CGRect) {
if let c = UIGraphicsGetCurrentContext()
{
let arr = [CGPoint(x:0,y:0), CGPoint(x:50,y:50), CGPoint(x:50,y:50), CGPoint(x:0,y:100)]
CGContextStrokeLineSegments(c, arr, 4)
}
}

Using weak reference to check if object is deallocated, in Objective-C

I'm using ARC.
Sometimes I wrote the following code to assert a object should be deallocated:
__weak weakVariableOrProperty = someObject;
....
someObject = nil;
// or someObject = anotherObject;
....
if (weakVariableOrProperty) {
#throw [NSException exceptionWithName:NSInternalInconsistencyException reason:#"Object not deallocated" userInfo:nil];
}
For example, I use this code to check if a view controller is deallocated before creating a new view controller.
I believe that weak variable or weak property is set to nil immediately after last strong variable or property was set to nil or another object.
And this code is working as I expected until now.
Using weak variable or property to check if object is deallocated is a technique commonly used?
Is it possible that this code will cause problem in the future?
I believe that weak variable or weak property is set to nil immediately after last strong variable or property was set to nil or another object.
This is not exactly true, because an object could be autoreleased. In this case, the last strong reference may be gone, but the reference count of the instance would remain positive. In cases like that, the __weak reference would not be nil-ed out until the autorelease process takes place.
Is using weak variable or property to check if object is deallocated a technique commonly used?
I seriously doubt that this technique has gained much popularity, because ARC is a relatively new thing to Objective C. However, the technique appears valid.
Is it possible that this code will cause problem in the future?
This is very hard to guess, because the ARC Specification does not make any specific guarantees about the timing of nil-ing out the references, and because the spec allows compilers to optimize sequences of retain and release messages that they send to ARC objects.
Your explanation code will be prone to a race condition.
The object in weakVariableOrProperty could be released (since it's only referenced by a weak reference) after the if condition has been evaluated. To avoid this, introduce an ordinary variable, set it to weakVariableOrProperty and check it for nil instead.
That said, as #dasblinkenlight says, betting on exactly when an object will be gone is tough. In a reference-counted system you don't know what else is holding onto it. It may go away just after you've checked. You should be able to constrain your environment enough that you know the system's not squirreling things away, but both autorelease and weak references complicate things.
The best way to solve this is simply to have well-defined object lifetimes: view controllers that don't live forever, that you explicitly tell to go away and so on.
So I've tried using this technique to ensure that objects are always deallocated on a background thread. The [dealloc] for some of my classes was moderately heavy weight and could take a long time (10s of ms) which would freeze the main thread ever so slightly.
I decided to add all of these heavy objects to an array before they'd be released on the main thread, and then go through that array later on a backgroundd thread to remove them from the array. The thought was that the array would keep the retainCount alive until it could be removed from the array on the background thread, and then i could guarantee the cost of the [dealloc] wouldn't happen on the main thread.
To do this, i had the code below:
while([objectsToDealloc count] && /* other conditions to prevent infinite loop */){
__weak id ref = [objectsToDealloc lastObject];
[objectsToDealloc removeLastObject];
#synchronized(ref){
// synchronising on ref will retain it if possible.
// so if its still around,that means we didn't dealloc it
// like we were asked to.
// so insert it back into our array. once the object is deallocd
// it won't be able to be synchronized, because the weak ref will
// be nil
if(ref){
[objectsToDealloc insertObject:ref atIndex:0];
}
}
}
The idea was that if the array didn't contain the last reference (or if there were pending autoreleases on the object, etc), then the weak ref wouldn't nil out. I'd then #synchronize on the object - the synchronized block will retain + release whatever object is being synchronized - which would ensure the ref would stay alive during that block. if it was nil, then it'd been dealloced. if it wasn't nil, then i should add it back to the array and check back again later.
After testing with this code over the past few weeks, I cannot recommend this strategy to check for deallocated objects. I haven't tracked down exactly why yet, but very rarely the object will dealloc but the ref won't be nil yet, so i'll be adding an invalid object back into the array.
i've only caught this in the debugger one time, though i have crash logs of it happening a few times. You can see below that "nil" ends up in my array, even though the code above should protect against it.
Again, I suggest not using this technique for detecting when/if objects deallocate, and instead focus efforts on clarifying your object graph and relationships.

Objective C, Memory Management

1) What is the reason for the use of retain?
For example, in a setter method:
- (void) setCount: (int) input {
[intCount autorelease];
intCount = [input retain];
}
2) the autorelease-Method: Is it deleting an old object or preparing the new one?
3) Why the retain-method is called at the input-object?
Would
intCount = input;
be wrong?
And why?
Retain is used to increment the retainCount of an object. NSObjects have a property called retainCount which maintains a count on the number of references that are currently held on an object. When the retainCount of an object reaches 0, the object can be released from memory. Effectively this prevents an object from being released from memory if it's still in use elsewhere.
The autorelease method does not delete an old object and does not prepare the new object. It is effectively a pre-emptive call to release the object (autorelease is much more complicated than that and you should read up on it in the Memory Management Guide.)
In your case intCount = input wouldn't be wrong because you're working with a primative. However if input were an object then you'd need to be calling retain on it. In fact you don't even need to be writing your own getters/setters for primatives (or objects), but instead should be using Declared Properties. In fact you're almost always better off using Declared Properties and if you do want to roll your own, get to know the pitfalls of doing so first.
I recommend you read this. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
The answers to your questions have been answered fairly well so let me just add that if you can use garbage collection you should. It makes everything so much easier. It isn't a panacea and you still should learn to use the retain/release mechanism but unless you are dealing in some high volume memory calls, creating and deleting lots of objects, then just use garbage collection.
It can be found under Project | Edit Project Settings | Build
Then just search for "garbage" and you'll see it.
If you are doing iOS development and cannot use garbage collection I apologize for giving unhelpful information but it still stands for non-iOS development.
To answer ur question specifically:
1). the use of retain is to declare the ownership of an object. In this case, intCount retains the ownership of input, in case the input got released somewhere else, u can still use the intCount.
2). the autorelease of intCount is to relinquish the ownership of the old value. That avoid the memory leak of the old value. If u don't release the old value, and u assign a new value to this pointer, the old object will always be there and never got released, which will cause the memory leak.
3). if u don't retain the input, and the parameter of input got released somewhere else. then if nowhere else retain this object, it will get freed. So u can't use intCount as well. That's why u need to retain it or copy it.
But i think if u do intCount = input; it should be fine. Because int is not an object, it's just a type. So I think the whole method is okay to be written like this:
- (void) setCount: (int) input {
intCount = input;
}
But if its a pointer, u should not assign the new value to the old one directly.