Passing in a function with an argument under @selector

Discussion in 'iOS Programming' started by Moon013, Sep 9, 2008.

  1. Moon013 macrumors newbie

    Joined:
    Jul 14, 2008
    #1
    Here is my codes

    -(void)deal:(UIImageView*)cardImage
    {
    [NSTimer scheduledTimerWithTimeInterval:timeTaken*10 target:self selector:mad:selector(alphaDealImage:cardImage:) userInfo:nil repeats:NO];
    }

    -(void) alphaDealImage:(UIImageView*)cardImage
    {
    cardImage.alpha = 0.0;
    }

    It crashes my program and I have searched all through the web for this problem. The bold line must be the one doing the job. Anyone knows how to write the right code for that?
     
  2. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
  3. Sbrocket macrumors 65816

    Sbrocket

    Joined:
    Jun 3, 2007
    Location:
    /dev/null
    #3
    There are a few things that are wrong. First of all, the method you're performing must have the following syntax (as PhoneyDeveloper said):
    Code:
    -(void)myTimerFireMethod:(NSTimer*)theTimer
    The design problem this creates for you should be apparent - you need the UIImageView object that you want fade. You could solve this in one of two ways (that come to mind, there's probably infinitely many) - if you're only ever going to be starting one timer at a time, you can simply have an ivar named "imageViewToFade" or something and do this:

    Code:
    -(void)deal:(UIImageView*)cardImage {
    	imageViewToFade = cardImage;
    	[NSTimer scheduledTimerWithTimeInterval:timeTaken*10 target:self selector:@selector(alphaDealImage:) userInfo:nil repeats:NO];
    }
    
    -(void)alphaDealImage:(NSTimer*)timer {
    	imageViewToFade.alpha = 0.0;
    }
    
    Or, you could opt to use NSInvocation and avoid the imageViewToFade (which I personally think is 'messy', but that's just me). This would also be necessary if you're starting multiple fade timers.

    N.B. - I don't use NSInvocation much, so make sure to check this code.

    Code:
    -(void)deal:(UIImageView*)cardImage {
    	NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:[UIImageView instanceMethodSignatureForSelector:@selector(setAlpha:)];
    	[invoc setTarget:cardImage];
    	[invoc setSelector:@selector(setAlpha:)];
    	[invoc setArgument:0.0 atIndex:2];
    	[NSTimer scheduledTimeWithTimeInterval:timeTaken*10 invocation:invoc repeats:NO];
    }
    
     
  4. Moon013 thread starter macrumors newbie

    Joined:
    Jul 14, 2008
    #4
    Thanks guys for helping!

    Sbrocket, i used the simpler matter you had suggested being messy, and it works, thanks. I didn't believe I could actually missed that.

    Going to try out your second method when I have time, been rushing all these days.

    Between, till now i don't understand this:

    -(void)alphaDealImage:(NSTimer*)timer {}

    Why must the function has (NSTimer*)timer? I done all my timers which will trigger functions that do not need that. My english must be really bad, I don't understand what it is used for...
     
  5. Sbrocket macrumors 65816

    Sbrocket

    Joined:
    Jun 3, 2007
    Location:
    /dev/null
    #5
    Please see the documentation. It says that the method you give in the selector must follow that pattern.

    http://developer.apple.com/document...imeInterval:target:selector:userInfo:repeats:

    Oh, and I forgot the easiest solution out of them all. Wow I feel silly now. This is how I would do it - no silly NSInvocation use or instance variable needed.

    Code:
    -(void)deal:(UIImageView*)cardImage {
    	[NSTimer scheduledTimerWithTimeInterval:timeTaken*10 target:self selector:@selector(alphaDealImage:) userInfo:cardImage repeats:NO];
    }
    
    -(void)alphaDealImage:(NSTimer*)timer {
    	((UIImageView*)timer.userInfo).alpha = 0.0;
    }
    
    There you go! Much cleaner. :)
     
  6. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #6
    I'm 99% certain that your timer method does not have to receive the NSTimer if it does not want to - just make sure your @selector is correct:

    Code:
    -(void)deal:(UIImageView*)cardImage {
    	[NSTimer scheduledTimerWithTimeInterval:timeTaken*10 target:self selector:@selector(alphaDealImage) userInfo:cardImage repeats:NO];
    }
    
    -(void)alphaDealImage {
    	// do something
    }
    
    The above will work - the important thing is to make sure that the selector has no trailing colon, which implies it takes an argument.

    Of course, if you're method relies on the user info, you will need to receive the NSTimer. :)
     
  7. itgiawa macrumors newbie

    Joined:
    Sep 4, 2008
    #7
    In the solution where you make an instance variable, where and how do you declare it?

    For whatever reason I always get an EXC_BAD_ACCESS when I try to call a method on the ivar, unless I pass it in as a userInfo.

    But I cant use the userInfo method because other functions need to access this variable too.
     

Share This Page