2

I seem to have a pointer problem and I can't seem o fix it. Could someone help me, please?

-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
    UIImage *CompiledImage=[UIImage imageWithData:ImageData];
    SEL selector=@selector(ImageDownloadingCompleted:Image:);
    if([[self Delegate] respondsToSelector:selector]){
        [[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
    }
    else{
        if(Target){
            *Target=CompiledImage;
        }
    }
    // NSLog(@"Image Size:%i", [ImageData length]);
}

Target is a private variable of type UIImage (declared: UIImage *Target;) CompiledImage is a UIImage as well. What I want to do is set the contents of the address of target to be the Contents of CompiledTarget. This results in the following error:

Assigning to 'UIImage' from incompatible type 'UIImage *__strong'

I tried :

memccpy(__bridge Target, &CompiledImage, sizeof(Target),sizeof(Target));

and I get this error:

Expected expression

2
  • Just a piece of suggestion. Use allseeing-i.com/ASIHTTPRequest instead of NSURLConnection. This made my life easy ;) Commented Dec 9, 2012 at 14:33
  • @ACB I already did myfriend :) thank you so much for your help ! Commented Dec 11, 2012 at 1:55

3 Answers 3

5

You need to just set it as,

Target = CompiledImage;

No need of *. Since both are pointers basically you are assigning the memory address and not copying the contents if you use the above code.

On a side note, please start variable names with lowercase letters. Target normally represents a class name. As per apple coding conventions, it should be target.

As per your comment, you can do the following,

In ViewController class, declare a UIImage as @property,

@property (nonatomic, retain) UIImage *downloadedImage;

While doing URL call,

NSImageLoader *imageLoader = [[NSImageLoader alloc] init];
[imageLoader setTarget:self];//setting current viewController as target instead of UIImage

When image is downloaded,

-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
    UIImage *CompiledImage=[UIImage imageWithData:ImageData];
    SEL selector=@selector(ImageDownloadingCompleted:Image:);
    if([[self Delegate] respondsToSelector:selector]){
        [[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
    }
    else{
        if(Target){
            Target.downloadedImage = CompiledImage;//or [Target setDownloadedImage:CompiledImage];
        }
    }
    // NSLog(@"Image Size:%i", [ImageData length]);
}

In your ViewController class, now you can access image as, self.downloadedImage which will have same as in CompiledImage with same memory address pointing to the same location.

An alternative way is to declare UIImage *Target as UIImage **Target in your NSImageLoader class. And while calling setTarget method, use [imageLoader setTarget:&Target];. Inside this method you need to set target as Target = Target;

Update: Based on your comments it should be like this,

for( NSDictionary *CurrentActivity in [Profile UserActivities]) {
        ...
        UIImage *WineImage = [UIImage imageNamed:@"loader.gif"];
        NSImageLoader *loader=[[NSImageLoader alloc] initWithURLString:[NSString stringWithFormat:@"%@%@",[TempSettings URL],[CurrentActivity objectForKey:@"ImageURL"]]];
        [loader setTarget:&WineImage];
        [loader startDownloading];
        [self addSubview:Activity];
        Counter++;
    }

Then in NSImageLoader.h file @interface,

 __strong UIImage **Target; //This should be strong not autoreleasing

In NSImageLoader.m file,

- (void)setTarget:(UIImage *__strong *)iTarget{ //change here also
     Target = target; 
} 


-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
    UIImage *CompiledImage=[UIImage imageWithData:ImageData];
    SEL selector=@selector(ImageDownloadingCompleted:Image:);
    if([[self Delegate] respondsToSelector:selector]){
        [[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
    }
    else{
        if(Target){
            *Target = CompiledImage;
        }
    }
    // NSLog(@"Image Size:%i", [ImageData length]);
}

Update2:

Using the approach of passing UIImageView, you can do the following,

    for( NSDictionary *CurrentActivity in [Profile UserActivities]) {
        ...
        UIImage *WineImage = [UIImage imageNamed:@"loader.gif"];
        NSImageLoader *loader=[[NSImageLoader alloc] initWithURLString:[NSString stringWithFormat:@"%@%@",[TempSettings URL],[CurrentActivity objectForKey:@"ImageURL"]]];
        [loader setTarget:Activity];//pass imageview and let the delegate method set image
        [loader startDownloading];
        [self addSubview:Activity];
        Counter++;
    }

-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
    UIImage *CompiledImage=[UIImage imageWithData:ImageData];
    SEL selector=@selector(ImageDownloadingCompleted:Image:);
    if([[self Delegate] respondsToSelector:selector]){
        [[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
    }
    else{
        if(Target){
            Target.image = CompiledImage;
        }
    }
    // NSLog(@"Image Size:%i", [ImageData length]);
}

Here pass imageview and let the delegate method set image in that once you have downloaded the image.

Sign up to request clarification or add additional context in comments.

28 Comments

I tried your suggestion, however, it wouldn't work as this would assign the memory address of compiledimage to Target, what I want to do is the exact opposite. Target is a pointer to an object in the view controller, and this function is executed inside a class. I want to change the image in the view controller by using the Target pointer. This is why I want to copy the data to that particular memory address.
@user1889357, That is slightly confusing. How are you passing the reference to that viewcontroller to this class? Certainly the above code which you used wont work. Can you please add the declaration of Target in and how this class is called from the viewcontroller class. There should be an easier way.
Ok, so I have a class named NSImageLoader.. in the class I have a function: -(void) setTarget:(id)target{ Target=target; } in my private variables for the class I have: id Target; now in the viewcontroller, I created a UIImage variable and passed it to setTarget. what I want is when the Image is downloaded in connectionDidFinishLoading is to set the image of the view controller (which i have passed as a target in setTarget to point to the new image that has just been loaded.
@Abedjoud, In that case why dont you set your viewcontroller as the target. For eg:- when you are calling setTarget method, pass viewcontroller itself as the target and not UIImage. After that in this delegate method once you get the image, set it as target.image = CompiledImage; That is the way to do this. That will automatically assign the same memory address of UIImage as CompiledImage to viewController.UIImageObject which you have defined in that class.
I am going to mark this answer as accepted as it sheds a lot of light on pointers. To preserve reusability, I ended up just creating another class that takes a type and UIActivityView and used NSImageLoader to download the image, and then used setImage..
|
1

Make Target is pTarget? a pointer to a pointer then it makes sense *pTarget = compiledImage (as it is done with NSErrors often .. e.g. in core data)

you cant just memcpy the stuff since target has not the correct size allocated on the heap.


you cant Copy the real UIImage bytes in the memory because that isnt known to you and an implementation detail. you dont even know how big it is!

BUT you can copy the pointer to the image -- its memory address


UIImage *pointer1 = [UIImage imageWithFoo];
UUImage *pointer2 = pointer1;

now you can also declare an empty pointer and fill it later

UIImage *target = nil;
UIImage *pointer1 = [UIImage imageWithFoo];
target = pointer1;

so far so good but what if you want to PASS target to a function and THAT should fill it?

target = [self calculateImage];

but now you have it in asynchronous function

[self asyncCalculateImage:&target]; // you pass it a POINTER to the POINTER to fill :)
...
- (void)asyncCalculateImage:(UIImage**)pTarget {
    UIImage *pointer1 = [UIImage imageWithFoo];
    *pTarget = pointer1; //DEREFERENCE and fill pTarget
}

3 Comments

Can you please explain more?
Daij-Djan you're almost spot on in what I need! the problem is, i need to save the Target in a local variable using setTarget. and then when the connectiondelegate gets called, i need to do the dereferencing.. i tried: UIImage **pImage=&Target; *pImage=CompiledImage; but i get this error:/Users/abedjoud/Desktop/My Projects/iOS/CalARG/FiveCorkz/FiveCorkz/FiveCorkz/NSImageLoader.m:84:22: Pointer to non-const type 'UIImage *' with no explicit ownership
ignore it and cast it to (UIImage*) -- arc complains about a const missing
0

Why did you put * again, here CompiledImage itself is a pointer.

Simply use Target=CompiledImage;

1 Comment

Because this wont change the contents of the memory pointed to by Target, it will rather assign a new address to Target. I need to change the contents of the Target address not assign address a new pointer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.