Adding a deleted or invalidated object to a Realm is not permitted - swift

I am trying to delete(truncate table) object and than adding it again, but getting this exception at runtime:
Adding a deleted or invalidated object to a Realm is not permitted
My code:
let realm = try! Realm()
let objFolder = realm.objects(FolderColor.self)
do{
try realm.write {
realm.delete(objFolder)
for obj in arrFolderColors {
realm.add(obj)
}
}
}
catch{}

I like the other answer but I think what's going on here is you have a class var
#objc dynamic var folderColorResults = Results<FolderColor>
and at some point you've populated that var with some FolderColor objects
self.folderColorResults = realm.objects(FolderColor.self).filter("color == 'blue'")
So then, when you call the code in the question, it's deleting all of the FolderColor objects from Realm - when that happens, the folderColorResults results var is also getting updated (all objects removed).
Therefore there are no objects to write back out to disk.
Remember that Realm is a live database and Results objects are always keep in sync with the actual data; change an object on one place, it changes it everywhere that object is being used.
A suggested fix is to cast the folderColorResults to an Array.
let myArray = Array(self.folderColorResults)
which disconnects those objects from Realm and they will not be updated.
Of course, I could be totally wrong on this assumption so I can update further if more information is provided.

Realm objects are simply pointers to their data in the Realm database. When you call realm.delete, you completely delete the contents from memory and disk. The Realm object itself is still in memory, but you can’t call any properties or try and re-add it.
There’s a object.invalidated property you can use to check if an object has been deleted before you try and add it to Realm to avoid accidentally triggering that exception.
I’d recommend you rethink your logic to not need to call ‘realm.delete’. If it’s in an array, you can just remove it from the array but keep it in the database.

Related

My core data fetch is not recognizing context

In my swift code below I am trying to fetch all of my names in core data to print. I am getting a compile error on context saying it can't be found in scope. I have attached a photo as well so you can see what is in my core data.
#objc func pressRight(){
var locations = [Place]() // Where Locations = your NSManaged Class
var fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "name")
locations = context.executeFetchRequest(fetchRequest, error: nil) as [Place]
// Then you can use your properties.
for location in locations {
print(location.name)
}
}
This isn't a Core Data problem, it's a Swift problem. All variables and properties in Swift have to be declared before you can use them. For example you can't just write
i = 5
Unless somewhere you already have something like
var i: Int
In your code you're using something called context that was never declared. Swift doesn't know what it is, which is what it's telling you.
Since you're using Core Data it looks like you want context to be an instance of NSManagedObjectContext. If your app already has an NSPersistentContainer somewhere, you can get a context from it, using either viewContext or newBackgroundContext (which one depends on exactly how you're using it; here it's probably viewContext).
If you don't already have an NSPersistentContainer somewhere in your app, you may want to read up a little on how to use Core Data. You can't just declare the context; it needs to be configured correctly with the container before use.

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

Cache that can purge unused objects by demand

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
}
}
}

How do I correctly release memory in Swift?

UserManagerViewController is a class that manages user objects (creates/release) for the rest of my view controllers (so that I don't create multiple User objects), I have:
var resources = Dictionary<Int, T>()
Whenever I need a resource, I do this:
let id = data["id"].intValue
self.resources[id] = User(data: data) //Create a User object and set it to the dictionary
I have other ViewControllers that "hang on" to this object when it wants to use it:
var users = [User]()
users.insert(<The pointer to resources[id]>, atIndex: 99)
//later on...
users.removeAtIndex(99) //this should release its hold
Later, when I need to release the final created object, I do this:
resources.removeValueForKey(id)
Will this method correctly ensure that the User instance simply goes away, since both its parents released it?
Yes, the user instance goes away. Swift uses automatic reference counting to manage memory. In your case, when you insert a user into a resource dict, the dict holds a reference to that user. When you later add user into users list, it also holds a reference to the user. It has two references to the same instance, therefore, when you remove user from those data structure, you have no reference to the instance, which means the user instance will be removed.

'CGImageSource' does not have a member named 'takeUnretainedValue'

A lot of posts on the internet say I can return an unretained image source with the following code:
let imageData1 = image.TIFFRepresentation
let source1 = CGImageSourceCreateWithData(imageData1 as CFDataRef, nil).takeUnretainedValue()
let maskRef1 = CGImageSourceCreateImageAtIndex(source1, UInt(0), nil)
However, I get the following compile time error:
'CGImageSource' does not have a member named 'takeUnretainedValue'
Am I doing something wrong? or has this method been removed in favour of something else?
You only use takeUnretainedValue or takeRetainedValue when dealing with an unmanaged object (e.g. some function that returns a Unmanaged<AnyObject>! or something like that). In this case, this isn't an unmanaged object, so this is not needed.
By the way, when returning a object from a Core Foundation function with Create or Copy in the name, the ownership of this object has been transferred to you, and you are responsible for releasing it (see the Create Rule). In these cases, you almost always want to use takeRetainedValue, so that the memory management of this object is managed automatically by Swift's ARC implementation. If you use takeUnretainedValue, you will leak memory unless you manually release the memory associated with this object that was obtained via a method conforming to the Create Rule.