Change image from another ViewController?

Discussion in 'iOS Development' started by Just_For_Now, Jul 18, 2010.

  1. Just_For_Now

    Just_For_Now Active Member

    Joined:
    Mar 21, 2009
    Messages:
    1,898
    Likes Received:
    1
    Device:
    4G iPod touch
    Im making this app to download an image from web and set the image in the MainViewController when done. But how to implement the Imageview? Heres my code.

    DownloadViewController.h
    [OBJC]@class MainViewController;
    @interface DownloadViewController : UIViewController {
    IBOutlet UIWebView *downloadsView;
    MainViewController *myBackground;
    }
    @property(nonatomic,retain) MainViewController *myBackground;

    -(IBAction)dlBG1;

    [/OBJC]

    DownloadViewController.m
    [OBJC]#import "DownloadViewController.h"
    #import "MainViewController.h"

    @implementation DownloadViewController
    @synthesize myBackground;
    -(IBAction)dlBG1{

    //Create Your URL

    NSURL *url = [NSURL URLWithString

    Please Register or Log in to view images

    "https://dl.dropbox.com/u/4733970/Web/files/page0-1000-full.jpg"];

    //NSData of URL
    NSData *webData = [NSData dataWithContentsOfURL:url];

    //Create UIImage of NSData
    //UIImage *img = [UIImage imageWithData:webData];

    // Display the image in UIImage View
    //[anImageView setImage:img];

    // Copy Image Data to ur location using FileManager
    if([webData writeToFile:[NSHomeDirectory() stringByAppendingString

    Please Register or Log in to view images

    "/Documents/BG1.png"] atomically:YES])
    {

    NSLog(@"DONE COPYING");

    NSArray *anArray = [[NSFileManager defaultManager]directoryContentsAtPath:[NSHomeDirectory() stringByAppendingString

    Please Register or Log in to view images

    "/Documents/"]];

    for(id element in anArray)
    {
    NSLog(@"Contains: %@",element);

    }

    //Form UIImage from contents of Directory

    UIImage *testImage = [[UIImage alloc]initWithContentsOfFile:[[NSHomeDirectory() stringByAppendingString

    Please Register or Log in to view images

    "/Documents/"] stringByAppendingString:[anArray objectAtIndex:0]]];

    //Display Image in UIImageView
    [myBackground setImage:testImage];
    [myBackground release];

    }
    [/OBJC]

    Im getting 2 warnings.

    [OBJC]NSArray *anArray = [[NSFileManager defaultManager]directoryContentsAtPath:[NSHomeDirectory() stringByAppendingString

    Please Register or Log in to view images

    "/Documents/"]];
    [/OBJC]
    Warning - "directoryContentsAtPath:" is deprecated

    [OBJC][myBackground setImage:testImage];
    [myBackground release];[/OBJC]
    Warning - "MainViewController" may not respond to "-setImage:"

    How do i do it then?
  2. Axis

    Axis Super Moderator Staff Member

    Joined:
    Dec 2, 2007
    Messages:
    6,288
    Likes Received:
    133
    Device:
    iPhone 4S (White)
    1.) The dataWithContentsOfURL method is synchronous; it will block the main thread, leaving your app unresponsive to UI events. Use NSURLConnection to send an asynchronous request.

    2.) There was quite a discussion here about getting the documents directory. What you have right now is fairly wasteful (if the path needs to be accessed more than once).

    3.) Please learn about the Model-View-Controller paradigm which Apple encourages and is used in the vast majority of well-made apps. Naming a controller variable "myBackground" suggests that you don't know how view controllers work, or what their purpose is.

    4.) I assume class MainViewController has an ivar that is a UIImageView reference. If you send an unrecognized message to an object, an exception will be thrown and your app will crash unless it's caught. You do not want to call the -[setImage:] method on the MainViewController instance; you need to call it on the ivar of type UIImageView *. To access that ivar, call the accessor method you wrote, or instructed the compiler to generate.

    edit: a quick trip to the documentation would have revealed that -[directoryContentsAtPath:] has been deprecated due to the lack of error information provided and that -[contentsOfDirectoryAtPath:error:] should be used instead.
  3. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    We've been over this on this forum. To reiterate, either use NSNotifications, control this all via your UIApplication or UIApplicationDelegate subclass, or give the downloading view controller a pointer to the main view controller which it can use to set the image directly.

    Regardless, from the code you posted, your app is very poorly designed. Judging from what you posted, you actually have two instances of MainViewController. Anything you do to the second one, the one contained within DownloadViewController will not be reflected by the viewcontroller you see onscreen. Also, it appears you don't have a grasp of subclassing.

    I am going to advise you to seek out an Objective-C book or two before you continue any further.




    Now, how would I deal with this problem? That depends on how often the application will be downloading images.

    If the app will only be downloading once, I would download the image and save it somewhere. Once the downloading is done, I'll have the DownloadViewController send out an NSNotification which the MainViewControlelr should receive. The MainViewController will then grab the saved file and set it as the background image.

    What happens next depends on whether or not you need the same image downloaded each time the application runs. If you will be downloading different images often, then I would have the application delete the image file immediately upon setting it. If it is a file that you will be downloading each time, but the image never changes, then I would leave the saved image file cached on disk. This will save time for the user, and will save you loads of bandwidth. You can compare the md5 of the file and the image online to determine if the ondisk version needs to be redownlaoded (either it has become corrupted, or the online image has changed, requiring an update to the saved file).


    Now, if the application were downloading several images each time you run it, or if you would simply like the application a little more robust with a lot more reusable code, then you should create a DownloadController singleton object. All the downloading and managing of downloading files should be done by the DownloadController.
    [OBJC]//Something like the following where force tells the
    //download manager to download the image even if it already
    //exists on disk. and cache tells the download manager to
    //whether or not to cache the file.
    [[DownloadController sharedDownloadController] downloadFileAtURL:SomeURL force:NO cache:YES][/OBJC]

    The controller requesting the download should be set as a temporary delegate of the DownloadController and should implement a method the download controller can call when the download is complete.
    [OBJC]- (void)downloadController

    Please Register or Log in to view images

    DownloadController *)dc didDownloadFile

    Please Register or Log in to view images

    NSData *)file withError

    Please Register or Log in to view images

    NSError **)error;[/OBJC]

    The controller requesting the download, upon receiving notification can then notify the main controller to update its image using NSNotifications, UIApp methods, or even (yet less recommended) the DownloadController itself.

    Again, all file management should be handled by the DownloadController.



    For examples of NSNotifications, protocol usage, and singleton objects, download, compile, and run the project here: http://github.com/SkylarEC/ConnectSome Once you see how it works, study the source code. Yes, it's incomplete, and yes there might be errors, but the app as is runs perfectly with no warning, or leaks.
  4. Just_For_Now

    Just_For_Now Active Member

    Joined:
    Mar 21, 2009
    Messages:
    1,898
    Likes Received:
    1
    Device:
    4G iPod touch
    Ok I now see how to use the download method.
    Though i don't understand 3.) and 4.) steps.

Share This Page