I'm using NSObject
class to handle a few server methods.
One of the methods is to download images from DB (parse.com).
The problem is that the UIViewController
who present the image is loaded faster than the download process (the image always nil
), and only 2 sec after that the image is in the device.
How can I update the UIImageView
image (userProfile class) from the NSObject
class (the one with the download method)?
UIViewController
with the image is in UITabBar
I know how to detect the end of the downloading process but I don't know how to reach to the UIImageView property from the other class.
Use delegate
for your requirement. Check implement delegate or ios_delegates how it can be done.
Some understanding is given below :
Say u have delegate method in NSObject class to handle a few server methods
@protocol YouNSObjectClassDelegate <NSObject>
@required
-(void)imageDownloaded:(UIImage*)image;
@end
Add
@property (nonatomic,strong) id<YouNSObjectClassDelegate> delegate;
While allocating object any any viewcontroller , don't forgot to intialize delegate
yourNSObjectClassObject.delegate = self;
When image is downloaded in NSObject class
if ([delegate respondsToSelector:@selector(imageDownloaded:)]) {
[delegate imageDownloaded:image];
}
In UIViewController where u want to have image add these method
-(void)imageDownloaded:(UIImage*)image
{
//Set Image here
}
while you calling NSObject Class
just pass your UIImageView
with other parameters and when your image got downloaded just set new image to the UIImageView
. I guess you are using threading concept so update your UIImageView
only on Main Thread
. You can use either
dispatch_async(dispatch_get_main_queue(), ^(void){
//Set your Image to UIImageView
});
OR use
[self performSelectorOnMainThread:@selector(updateImage:) withObject:objects waitUntilDone:YES];
Or better you can write your own block
or delegate
method and pass downloaded image when image got downloaded.
In the tableView's cellForRowAtIndexPath
method, rather than setting the image directly, use GCD async and a completion block.
In your download class header declare a new method with completion block:
- (void)downloadImagesWithCompletion:(void (^)(void))completion;
And the implementation:
- (void)downloadImagesWithCompletion:(void (^)(void))completion {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, NO), ^(void){
// Run your downloading here, and once your operation is complete...
dispatch_async(dispatch_get_main_queue(), ^(void){
completion();
});
});
}
In your view controller's handling method, call it like this:
[downloader downloadImagesWithCompletion:^(void) {
{
// your downloader is now complete, run your UI updates
}];
Note: this example doesn't include any return values in the completion block, but you can easily do that as well .
You'd better to think as UIViewController is a boss. That means UIViewController starts downloading a image, handle the completion, and set Tabbar image. The class of download image process is just a worker. The worker delegates a boss to important decisions.
The class of download image process tries to set Tabbar image directly is not a good idea. It's a good idea to design the class has a delegate protocol or a block function to tell 'someone' to complete the download of image.
You'd better to use SDWebImage library. The library is designed like I said.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.