Search code examples
objective-cargumentsnstimernsinvocation

NSInvocation & NSTimer - Method gets called twice


I've created a small app, which has a UISegmentedControl with to segments and a UITableView. When the selected segment changes, the data in the TableView (which is download from a server) should change. Therefore I have a method

- (void)loadPlanForIndex:(int)tableIndex
{
   // Create PlanModel and get elements
   _planModel =[[PlanModel alloc] init];
   _plan = [_planModel getPlanForDayIndex:tableIndex];

   // Reload TableView data
   [self.firstTable reloadData];

   // Set SegmentedControl title
   NSString *segmentTitle = @„MyTitle“;
   [self.daySegmentedControl setTitle:segmentTitle forSegmentAtIndex:tableIndex];

   // Create NSInvocation to call method with parameters
   NSInteger objIndex = tableIndex;
   SEL selector = @selector(loadPlanForIndex:);
   NSMethodSignature *signature = [self methodSignatureForSelector:selector];
   NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
   [invocation setTarget:self];
   [invocation setSelector:selector];
   [invocation setArgument:&objIndex atIndex:2];

   NSTimeInterval timeInterval = 10;
   [NSTimer scheduledTimerWithTimeInterval:timeInterval invocation:invocation repeats:NO];
}

The tableIndex is an index to get the right data. The first two rows get the data for the tableView.

This method gets called every time the segment changes

- (IBAction)didSelectSegment:(id)sender
{
   if (self.daySegmentedControl.selectedSegmentIndex == 0)
   {
       [self loadPlanForIndex:0];
   }

   else
   {
       [self loadPlanForIndex:1];
   }
}

This is my viewDidLoad

- (void)viewDidLoad
{
   [super viewDidLoad];
   // Do any additional setup after loading the view, typically from a nib.

   // Some other setup

   [self loadPlanForIndex:1];
   [self loadPlanForIndex:0];
}

So now here is my problem: Every time the timer runs out and calls the method again, the two statements of my viewDidLoad get called (I've checked that with NSLog statements). So in the app the data for index 1 is displayed and only after that the right data (for index 0) is displayed

How can I fix this?


Solution

  • You should move the scheduling logic out off the loadPlanForIndex: method

    - (void)loadPlanForIndex:(int)tableIndex
    {
       // Create PlanModel and get elements
       _planModel =[[PlanModel alloc] init];
       _plan = [_planModel getPlanForDayIndex:tableIndex];
    
       // Reload TableView data
       [self.firstTable reloadData];
    
    - (void) scheduleAutoReload
       // Set SegmentedControl title
       NSString *segmentTitle = @„MyTitle“;
       [self.daySegmentedControl setTitle:segmentTitle forSegmentAtIndex:tableIndex];
    
       // Create NSInvocation to call method with parameters
       NSInteger objIndex = tableIndex;
       SEL selector = @selector(loadPlanForIndex:);
       NSMethodSignature *signature = [self methodSignatureForSelector:selector];
       NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
       [invocation setTarget:self];
       [invocation setSelector:selector];
       [invocation setArgument:&objIndex atIndex:2];
    
       NSTimeInterval timeInterval = 10;
       [NSTimer scheduledTimerWithTimeInterval:timeInterval invocation:invocation repeats:YES];
    }
    
    - (void)viewDidLoad
    {
       [super viewDidLoad];
       [self loadPlanForIndex:1];
       [self scheduleAutoReload];
    }
    

    Noted that NSTimer is repeats now. I cannot run this but I think it should work. Anyway you might want to keep that timer in a variable so you can stop it in viewDidDisappear or something like that.