NSMutableDictionary remains empty after using nsoperation to load images
So I first coded all my methods in a viewcontroller with an NSOperationQueue. After doing some research and a lot of reading I realized i had to subclass my loadImage operation so that I may use isCancelled and cancelAllOperations. So I went ahead and created an nsoperation class and called it from my viewcontroller. ALl the methods are called, even the imageLoaded, but the NSMutableDictionary remains empty. I use the dictionary to populate my tableviewcells using the url as the Key. Also be aware that the operation call in the viewcontroller is within a method which is called by an NSInvocationOperation when the view loads.
You're creating a new StoriesTableViewController for each operation; that's probably not what you want. You need a singleton there (a thread safe one!) or you need to pass in the StoriesTableViewController when you create the NSOperation.
Otherwise I'm not sure why tempDict / filteredImagesDict is empty; did you try to log tempDict / filteredImagesDict to make sure it's not nil?
You're also adding items to the dictionary from multiple threads with no synchronization. NSMutableDictionary is not thread safe, so you could easily crash or lose data here. You need to synchronize your access:
Lastly, you're using UIKit classes on a background thread. You should probably switch back to the main thread after you get your data; the docs say UIKit is not thread safe.
Multithreading is hard, and IMO should be avoided unless you have no other choice. Cocoa has some great features to make it easier, but it's still tricky and not something to be entered into lightly.
ThAnks fir your response. I log the count of filteredimagesdict after every operation a d it remains 0. Is there an easier way of calling iscancelled within an nsinvocationoperation without subclassing? If not how can I pass multiple arguments to my nsoperation. I tried and the current init had me confused.
You're creating a new StoriesTableViewController for each operation; that's probably not what you want. You need a singleton there (a thread safe one!) or you need to pass in the StoriesTableViewController when you create the NSOperation.
Otherwise I'm not sure why tempDict / filteredImagesDict is empty; did you try to log tempDict / filteredImagesDict to make sure it's not nil?
You're also adding items to the dictionary from multiple threads with no synchronization. NSMutableDictionary is not thread safe, so you could easily crash or lose data here. You need to synchronize your access:
Lastly, you're using UIKit classes on a background thread. You should probably switch back to the main thread after you get your data; the docs say UIKit is not thread safe.
Multithreading is hard, and IMO should be avoided unless you have no other choice. Cocos has some great features to make it easier, but it's still tricky and not something to be entered into lightly.
The dictionary is created in the viewcontroller. Now if I could pass 2 variables in and send 2 variables out in the imageloaded method it would probably fix some issues. I would have to send out the URL and the image and the. I could add the image to he dictionary in the controller
here you go but i doubt this is the issue. the dictionary is working just fine when I use only the NSInvocationOperation and don't have a separate NSOperation to load the image.
this is within the view controller, it includes the creation to the NSOperation below.
When you log the count of a collection and get 0, there are 2 possibilities:
1. The collection doesn't actually exist
2. The collection has no contents.
To answer #1, you should log the collection itself, as smasher suggested in his first reply. That will determine whether you need to worry about #2.
You alloc/init a new StoriesTableViewController and then immediately access the filteredImagesDict. However, you don't actually create this dictionary until loadImages is called. So, unless your init method is calling this loadImages method, the dictionary doesn't exist yet.
As a side note, it is really weird to set up a mutable collection with a capacity of zero. What's the point of that? And you really should be using properties.
Edit:
One other thing I just noticed:
Code:
NSLog(@"tempDict count: %d",tempDict.count);
count is not a property, so you can't use dot syntax for this. You have to use bracket syntax.
thank you for all your pointers. I have logged each step. I get an address for myImage, a different address for scaledImage, and then I log the count of the dictionary.
loadImages is called upon initiation, and when you re-enter the view if a certain amount of time has passed.
I tried another direction which was passing a dictionary to the imagesLoaded method with the URL and the image to then add it to filteredImagesDict in the viewcontroller. Now when I NSLog the uiimages i get addresses but how can I know if there is something actually there. is there a way of logging image memory size. After my workaround, again i was getting no image to show up, and an empty filteredImagesDict in the cellForRow method
Quote:
Originally Posted by BrianSlick
When you log the count of a collection and get 0, there are 2 possibilities:
1. The collection doesn't actually exist
2. The collection has no contents.
To answer #1, you should log the collection itself, as smasher suggested in his first reply. That will determine whether you need to worry about #2.
You alloc/init a new StoriesTableViewController and then immediately access the filteredImagesDict. However, you don't actually create this dictionary until loadImages is called. So, unless your init method is calling this loadImages method, the dictionary doesn't exist yet.
As a side note, it is really weird to set up a mutable collection with a capacity of zero. What's the point of that? And you really should be using properties.
Edit:
One other thing I just noticed:
Code:
NSLog(@"tempDict count: %d",tempDict.count);
count is not a property, so you can't use dot syntax for this. You have to use bracket syntax.
this is still unresolved for me. I went ahead and put the imageload method back in the viewcontroller. could it be that i was calling an nsoperation which was allready in a method in an nsinvocationoperation? i could try to run it on the main thread.