Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force NSView to redraw programmatically

My app has two different states, and every state will be representing with a NSView.

so there is only one view showed at a time, the problem is when I switched between the views the app doesn't show the new state until I resize the window manually!

I searched about this problem and come with more than one solution but nothing worked with me:

[myView setNeedsDisplay:YES];
[myView display];
[[myView.window contentView] setNeedsDisplay:YES];


[mySubView1 setHidden:YES]; || [mySubView1 removeFromSuperView];

I even defined myView as Outlet, and nothing work.

and this is my code

if (appState == 1) {

    [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 250)];

    [self.mySubView1 setHidden:NO];
    [self.mySubView2 setHidden:YES];

    [self.mySubView2 removeFromSuperview];
    [self.mySubView1 addSubview:self.inCallView];
}
else
{
    [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 70)];

    [self.mySubView1 setHidden:YES];
    [self.mySubView2 setHidden:NO];

    [self.mySubView1 removeFromSuperview];
    [self.mySubView2 addSubview:self.chatHeaderView];
}
// I need to redraw here
[self.view setNeedsDisplay:YES];
[self.mySubView1 setNeedsDisplay:YES];
[self.mySubView2 setNeedsDisplay:YES];
// and nothing happened until I resize my window manually 
like image 920
Ahmed Khalaf Avatar asked Nov 12 '13 16:11

Ahmed Khalaf


2 Answers

I found it, the code is just fine and no need to call any redraw method, the only problem Any UI action need to be done in the MAIN thread

so the final code will be:

dispatch_async( dispatch_get_main_queue(), ^{
    if (appState == 1) {
        [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 250)];

        [self.mySubView1 setHidden:NO];
        [self.mySubView2 setHidden:YES];
    }
    else
    {
        [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 70)];

        [self.mySubView1 setHidden:YES];
        [self.mySubView2 setHidden:NO];
    }
});

Thanks, guys.

like image 110
Ahmed Khalaf Avatar answered Sep 21 '22 10:09

Ahmed Khalaf


doing a subview remove or add operation will automatically call setNeedsDisplay:YES so it's no surprise that calling it manually is having no effect.

some things to check:

  1. Check your view properties for nil values. I see you are removing the view which will cause the superview to release it and if you aren't retaining it with a strong property (or elsewhere) it will be deallocated.
  2. Be sure that you aren't fighting autolayout. turn off autolayout temporarily to confirm it is not causing your problem.
  3. you are only setting the frame size. you need to make sure it has the expected origin as well.

Also if you are removing the view you don't need to bother calling setHidden:

like image 35
Brad Allred Avatar answered Sep 23 '22 10:09

Brad Allred