What am I missing ? (IBActions and selectors)

Discussion in 'iOS Programming' started by Nekbeth, Apr 25, 2011.

  1. macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #1
    I get crashed if I use this code: (trying to create an outlet for a button with a selector to a method that invalidates the Time).


    Code:
    - (IBAction) cancelTime: (id) sender
    {
        [self performSelector:@selector(cancelIt:) withObject:nil];
    
    }
    
    
    - (void) cancelIt:(NSTimer*)timer    
    
    {
        
        [timer invalidate];
        timer = nil;
        
        
    }
    thanks
     
  2. macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #2
    What is "timer" set as and where does it come from?

    I think from there you can see where your problem is.
     
  3. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #3
    I declared timer as an instance method:

    Code:
    - (IBAction) cancelTime: (id) sender;
    - (void) cancelIt:(NSTimer*) timer;     
    
    @end
    mmm.. I think I see where this comes from. I had a similar method and it was declared in inside the (IBAction) method, like this:

    Code:
    - (IBAction) something: (id) sender;
    
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(echoIt:) userInfo:myDict repeats:YES];
    Then I would just implement echoIt.. That method works fine.

    The question is, If I do the same, I'll be creating another NSTimer won't I ?, And I just want to access the same timer. What can I do?

    Thanks
     
  4. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    No, you didn't. You declared cancelTime: and cancelIt: as instance methods, one of which happens to have a timer parameter.

    As such, I'm not sure you have a proper grasp of the fundamental concepts of Objective-C programming so I would suggest you step away from the real coding and go (re)learn those before you come back to this issue.
     
  5. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #5
    Thanks for your advice dejo, but I'm not stepping away because of lack of fundamentals. Interaction with other developers is an additional learning source (the main is all kind of documentation), of course I need to learn more about fundamentals of objective C just like you did when you had 3 months programming, but that ain't stopping me from asking help in forums. Some people help you, some don't, you just have to deal with that.

    btw, thanks for pointing my error, your right.. those are declaration for cancelTime: and cancelIt: , I got confuse with the parameter :D
     
  6. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    The reason I suggested what I suggested was that, without a good grasp of the fundamentals, you are not exactly speaking the same language as those you seek help from. This can cause continued confusion and frustration by all involved. Anyways, good luck with your issue.
     
  7. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #7
    No problem dejo, I understand.. It can be frustrating for others as well as myself and that's why some people tell you to go read all Apple's documentation for a simple question and some others help you no matter what. Speaking a language fluidly could take years, I can hardly speak French myself but that is not stoping me from going to France & ask for coffee in their language. (even if they get upset cause I talk awful, which some do, but some others like it :p).

    About my issue, I think I solve it. I was able to show up an alarm with using that method after I declare it appropriately.

    I now have some thing like this :

    Code:
    - (IBAction) cancelTime: (id) sender
    {
        
        [NSTimer scheduledTimerWithTimeInterval:0
                                         target:self 
                                       selector:@selector(cancelIt:) 
                                       userInfo:nil 
                                        repeats:NO];
    
    
    }
    
    
    - (void) cancelIt:(NSTimer*)timer    
    
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"An Alert!" 
                                                       delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];
    
        
    }
    I'll now try to add the invalidate method to the timer, see what happens
     
  8. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    What makes you think that cancelIt: is being passed an NSTimer object?
     
  9. Nekbeth, Apr 25, 2011
    Last edited by a moderator: Apr 25, 2011

    thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #9
    Because I have a button that receives the action "cancelTime" in IB. I wonder if I need to add something to userInfo parameter in the cancelTime method. Please correct me if I'm missing something.

    EDIT:

    UPdate !!,

    Just to confirm that I was not able to access the Timer, only it's window. My guess is that I need to add some userInfo to access it.
     
  10. macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #10
    The point dejo was trying to make, is that you are missing a VERY basic Objective C (well, any language really) fundamental.

    This:

    Code:
    - (void) cancelIt:(NSTimer*)timer
    
    does NOT create an object.

    It's simply a map to say "When I call this method, I will pass in an existing timer object". It is still your responsibility to allocate/initialize a timer and then pass that into your method. Simply using the selector as you are doing wouldn't accomplish this.

    At some point you would have to do something like:

    Code:
    [self cancelIt:MyExistingAndValidTimerObject];
    
     
  11. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #11
    I'm aware of that ulbador, and my point is that like any other language.. you get better with time & practice. Nobody FORCES you or dejo to read my threads, or answer them. If you see lack of objective-C fundamentals, just go to another thread (for Pros), is that simple. Some people like to help, others laugh, others ignore you or get frustrated because they can't read ... who cares man, if you don't like the thread just go to another one but never try to discourage a person who's starting to learn, that I'm against.


    (about the code) Thanks for pointing that out, I needed a variable, after that I created a timer appropriately and used the variable as a reference to trigger my cancel methods (invalidate).
     
  12. macrumors 6502

    Joined:
    Feb 7, 2008
    #12
    Have you read the documentation for NSTimer?
    Code:
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds invocation:(NSInvocation *)invocation repeats:(BOOL)repeats
    
    The above line has your answer.
     
  13. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #13
    I got it wlh99, thanks. I have two timer working fine (finally :) , I was told that you can't reuse the same timer, hence the 2nd timer. There is one Start button and one Cancel button

    Now I'm trying to find a logic to turn the 1st timer ON while the 2nd is OFF, then if you press Cancel you invalidate that 1st timer.

    I have both timers starting at the same time. So, i'm sure I could work it out using an if /condition statement.. something like :

    // *myTimer is the 1st timer
    // *newTimer is the 2nd timer


    if (myTimer != newTimer) {

    // Code to start new Timer
    }

    Any idea would be great, thanks
     
  14. macrumors 6502

    Joined:
    Feb 7, 2008
    #14
    Do you understand pointers, and that myTImer and newTimer are both pointers to NSTimer objects? If not, then step back and learn some Objective-C basics.

    What do you mean by "ON" and "OFF"?

    If you read the NSTimer documentation, it will tell you how to find out information about it, for example if it is Valid, or what the next fire date/time is.

    Your if statement will confirm that the two pointers don't point to the same single timer object. I don't know what you want to do from reading your post, but I'm sure it isn't that.

    So first thing first, what do you want to do?
     
  15. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #15
    Careful. The OP doesn't like to hear that. :)
     
  16. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #16
    Easy fellows.. :) .. those are not pointers ... they have "//" to indicate it's a comment.(you should both know this) I usually use ** as comments. It's an obvious miss understanding. They are just there to indicate you that Timer1 is the 1st Timer, ITS NOT PART OF THE CODE.

    I lack fundamentals, but not that much.. so hold your horses. dejo, please stay out of it, go to check some Pro Forums and cut some slack, what I don't like to hear is people trying to discourage new developers to stay off real code cause they miss a fundamental.

    wlh99, I'll step back when ever I want to, this is a public Forum and people are here to discuss and learn new stuff.

    Any way.. if you guys can't help me, just go to another thread.
     
  17. macrumors 6502

    Joined:
    Feb 7, 2008
    #17
    I'm more than happy to help, which is why I asked what you meant by "ON" and "OFF" and what exactly you want to do. Because I don't know. Timers are not "ON" or "OFF" so I need to know what you mean.

    I was referring to the "if" statement, not the comment. How and where do you declare myTimer and newTimer? Where are they assigned a value? Post that code. My assumption was (possibly incorrect) that they were assigned as the return value from when you created the timers.

    In which case, they are pointers. If you declared them as a primitive type and assigned them a value not related to the timer objects, then they are not pointers. If that is the case, I am even more confused as to what you want the program to do.

    Post your code, and let us know what you are trying to accomplish.
     
  18. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #18
    Nekbeth, I'm not sure if you follow other threads in this forum but if you do, you'll find that I have been quite helpful to a number other beginners out there. I am not trying to discourage new developers; I am just trying to help you help yourself so that you have a better chance of getting the answers you seek when you can ask questions using the same terminology as everyone else.

    But if you don't want my help, I'm happy to oblige. Good luck, though.
     
  19. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #19
    Sure, good to have that clear.

    Then yes, they are indeed pointers to timers. The timers are created inside their methods, I use those pointers to reference them and use invalidate.

    Here is part of the code:

    Code:
    .h  (declaration of timers)
    @interface ATimerViewController : UIViewController {
        
     IBOutlet UIDatePicker *timePicker;
     NSTimer *myTimer;
     NSTimer *newTimer;
        
    
    // 1st Timer 
    - (IBAction) echoTime: (id) sender;
    - (void) echoIt: (NSTimer *) timer; 
    
    
    // 2nd TIMER
    - (IBAction) newActionTimer: (id)sender;
    - (void) echoNewTimer: (NSTimer *) timer2;

    .m (method for 2nd Timer , the other is similar)

    Code:
                            ---------------- 2nd Timer -----------------
    
    
    - (IBAction) newActionTimer: (id)sender
    {
        [newTimer invalidate];
        [newTimer release];
        
        NSDate * time = timePicker.date;
        NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
        [dateFormatter setDateFormat:@"HH:MM:SS"];
        NSLog(@"date:%@", [dateFormatter stringFromDate:time]);
        NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
        NSDateComponents *comps = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:time];
        
        NSInteger hour = [comps hour];
        NSInteger minute = [comps minute];
        NSLog(@"Hour:%i", hour);
        NSLog(@"minute:%i", minute);
        NSInteger secs =hour * 60 * 60 + minute * 60;
        
        NSNumber *elapsedSeconds = [NSNumber numberWithInt:secs];
        NSDictionary *myDict2 = [NSDictionary dictionaryWithObject:elapsedSeconds forKey:@"TotalSeconds"];
        
        newTimer = [NSTimer scheduledTimerWithTimeInterval:1 
                                                    target:self 
                                                  selector:@selector(echoNewTimer:) 
                                                  userInfo:myDict2
                                                   repeats:YES];
    
        [newTimer retain];
    
    }
    
    
    
    - (void) echoNewTimer: (NSTimer *)timer2
    
    {
        
        NSNumber *num = (NSNumber *) [[timer2 userInfo] valueForKey:@"TotalSeconds"];   //elapsed
        seconds++;
        
        NSInteger secs2 = [num integerValue] - seconds;                                 //remaining
        NSLog(@"elapsed: %i, remaining: %i", seconds, secs2);
        
        if (secs2 <= 0)
        {
            [timer2 invalidate];
            timer2 = nil;
            
        }
        
        label4.text = [NSString stringWithFormat:@"NEW TIMER: %i", secs2];
    }
    
    After that I implement a Cancel method pointing to sender (button)

    So, my goal is to use 1 start button and 1 cancel button.. and just do their actions. I have set up a the start button to start both timers, obviously both start their countdown at the same time which is not good.

    I want to tell one timer to start and if I press cancel, invalidate it. Then If I press start again, call the second timer. (I do this because I read that you can't reuse a timer after you invalidate it).

    Some people have suggested to use Booleans like true or false, or conditions. What do you think?
     
  20. Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #20
    Nekbeth, let me suggest that you take some time to read over http://whathaveyoutried.com and http://mikeash.com/getting_answers.html.

    dejo, ulbador and wlh99 are genuinely trying to help you, but you have not defined the problem or given them (or anyone else) enough information to work with in order to be able to help you.

    Part of the problem, which dejo already alluded to, is that without a common understanding of fundamental assumptions you both end up frustrated. You might well be able to ask for a coffee in French, but if you are in a dentist's office in Austria that might not lead to satisfaction all around. Your assumptions aren't in sync.

    B
     
  21. thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #21
    Of course I like help Dejo and I know you have help a lot people, you have even helped me before this thread and I appreciate it a lot. I said that because so many seasoned developers just throw that bomb at newbies so often when they try to find answers in forums (not just this one), it happens not only in Programming but in many other professional environments, people just shoot to kill when some new guy makes a basic mistake, but luckily not all, some people do like to help (or enjoy) and have the patience to explain even the dumbest detail. But hey, it's cool.. We're all here to share and learn after all. I'll be glad to see you contribute to my threads, but you know.. that is up to you.
     
  22. balamw, Apr 26, 2011
    Last edited by a moderator: Apr 26, 2011

    Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #22
    Please take the time to read the two guides I linked in my response a few posts back.

    This:
    is exactly what they seek to avoid.

    Help us help you.

    You take it as a "bomb" when in fact it is a request to get on the same page.

    B

    So this will effectively be a stopwatch that can only by started and stopped twice?

    Is that the intent?

    EDIT: Have a look at this tutorial: http://www.apptite.be/blog/ios/sample-ios-application-stopwatch/ Do you understand why it doesn't need to define two timers?

    B
     
  23. macrumors Pentium

    KnightWRX

    Joined:
    Jan 28, 2009
    Location:
    Quebec, Canada
    #23
    You don't need to do this. You can use the same NSTimer * pointer multiple times, you will just need to assign a new NSTimer object to it after you invalidated your first NSTimer object (or 2nd, or 3rd, etc..).

    Basically, you only need 1 NSTimer object pointer, setup as an instance variable and your various IBActions :

    (now, sorry for any syntax/compile error, I'm not opening Xcode here, just typing it out)

    Code:
    @interface ATimerViewController: UIViewController {
            NSTimer * atimer;
    }  
    
    -(IBAction)setAndStartTimer:(id) sender;
    -(IBAction)cancelTimer:(id) sender;
    
    
    This is basically all you would need. Pressing the start button would call the first method, clicking the cancel button would call the second.

    Did you read the NSTimer class reference ? It explains what [atimer invalidate] does (also its pitfalls). It also explains how to create timer objects.
     
  24. macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #24
    The OP is shockingly confused. When it says that you can't reuse an invalidated NSTimer, that just means you have to create a new instance. You can reuse that pointer as much as you want once you invalidate and release it.
     
  25. Nekbeth, Apr 26, 2011
    Last edited: Apr 26, 2011

    thread starter macrumors member

    Nekbeth

    Joined:
    Feb 20, 2011
    Location:
    Vatican City
    #25
    is that last code enough info balamw?

    Satisfying?, well that's pretty much impossible if you ask me. People have their own standards, some are satisfied with you understanding the basic language, some others just want to read perfect code or hear perfect English and can't tolerate a miss step.

    I say show what you got (even it's a poor language) and follow your needs because you can never satisfy people expectations. Soon or later, you'll talk as good or better than them. It's only matter of will, time and patience.

    I know they are all trying to help, but there are ways to tell people what they lack, and those ways are what make all the difference.

    You can point out an error and give solution (sorry, "find solutions") or you can tell that person to quit what he's doing because he has no idea. It's a lot easier to say, go read Apples documentation than to point out an error and explain it yourself.
     

Share This Page