0

Do any of you know if it is possible to cancel a viewDidAppear?

When i load a new view, the viewDidAppear is loading, and in that time i can't do things as switching views.

Here's the viewDidAppear code:

- (void)viewDidAppear:(BOOL)animated{
    NSURL * imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",Username]];
    NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
    UIImage * image = [UIImage imageWithData:imageData];
    if (image) {
        UsersProfilpic.image = image;
    }

    imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",FriendsName]];
    imageData = [NSData dataWithContentsOfURL:imageURL];
    image = [UIImage imageWithData:imageData];
    if (image) {
        FriendsProfilpic.image = image;
    }
}

Thanks in advance. :)

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 2
    It is not possible to _cancel_ `viewDidAppear:`. You can however choose not to implement it. In your case the problem is syonchronous loading of image data from the web. You should consider the asynchronous approach - there are bunch of guides available out there... – Rok Jarc May 11 '14 at 20:31
  • AFNetworking offers a good & simple solution to your problem. Check [this answer](http://stackoverflow.com/a/19355814/653513). You just might want to add a check and not load the image if it is loaded already. – Rok Jarc May 11 '14 at 20:46

5 Answers5

2

While technically you could just return from within viewDidAppear, that would be sort of crazy and you shouldn't need to do so in the first place. If something in that method is slowing things down, then it is not the right place for doing it.

For example, if you would be loading the profile pictures from some remote source (such as a web server), that would be something you might very well trigger from within viewDidAppear, but the process of obtaining the data should happen asynchronously.

Not related to your question but important anyway: You're missing the call to super: [super viewDidAppear:animated];

Toastor
  • 8,980
  • 4
  • 50
  • 82
2

Remember to call:

[super viewDidAppear:animated]

otherwise you won't call the viewDidAppear method on the class UIViewController.

It is extremely important when you extend a class. Remember to call super to maintain the behaviour of the class that you are extending.

Matteo Gobbi
  • 17,697
  • 3
  • 27
  • 41
0

You could just surround all of the code contained in an if(boolean) and then set this boolean depending on whether you want to execute the code within viewDidAppear. I.e.

- (void)viewDidAppear:(BOOL)animated{
    if (someBoolean == true) {
        NSURL * imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",Username]];
        NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
        UIImage * image = [UIImage imageWithData:imageData];
        if (image) {
            UsersProfilpic.image = image;
        }

        imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",FriendsName]];
        imageData = [NSData dataWithContentsOfURL:imageURL];
        image = [UIImage imageWithData:imageData];
        if (image) {
            FriendsProfilpic.image = image;
        }
    }
}
Sam Heather
  • 1,493
  • 3
  • 19
  • 42
0

I am not sure what do you want exactly. But if you want to get rid off "Loading" viewDidAppear, then just put that "viewDidAppear code" in "viewDidLoad method". "viewDidLoad method" calls only one time when you come to that particular viewController, but in other hand "viewDidAppear method" calls every times when you come to that viewController. So your code would be like this:

- (void)viewDidLoad
{
    [super viewDidLoad];
NSURL * imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",Username]];
    NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
    UIImage * image = [UIImage imageWithData:imageData];
    if (image) {
        UsersProfilpic.image = image;
    }

    imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",FriendsName]];
    imageData = [NSData dataWithContentsOfURL:imageURL];
    image = [UIImage imageWithData:imageData];
    if (image) {
        FriendsProfilpic.image = image;
    }
}

You may alos take have a look in "This Discussion". Hope it helps.

Community
  • 1
  • 1
Tulon
  • 4,011
  • 6
  • 36
  • 56
0

You should NEVER EVER block the UI thread with network calls. Read about GCD.

Do it in ViewDidLoad, viewDidAppear also gets called when modals are dismissed, you don't want to download the image every time a modal is dismissed

- (void)viewDidLoad
{
   [super viewDidLoad];

    // Call it in global queue
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURL * imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",Username]];
        NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
        UIImage * image = [UIImage imageWithData:imageData];
        if (image) {
            // Update image on ui thread
            dispatch_async(dispatch_get_main_queue(), ^{
                UsersProfilpic.image = image;
            });
        }
    });

   // Call it in global queue
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"Url",FriendsName]];
        imageData = [NSData dataWithContentsOfURL:imageURL];
        image = [UIImage imageWithData:imageData];
        if (image) {

            // Update image on ui thread
            dispatch_async(dispatch_get_main_queue(), ^{
                FriendsProfilpic.image = image;
            });
        }
    });
}

Oooh also variable names should not be capitalized. Use camel notation

aryaxt
  • 76,198
  • 92
  • 293
  • 442
  • Made some changes if you have 2 different dispatch_async the two image will be downloaded asynchronously which gives you a better performance – aryaxt May 14 '14 at 15:40