简体   繁体   中英

Objective C - How to change image from another class (another UIViewController)

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)?

  • I'm not using navigation bar - but the 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM