program story

UIView를 강제로 다시 그리는 가장 강력한 방법은 무엇입니까?

inputbox 2020. 7. 28. 08:29
반응형

UIView를 강제로 다시 그리는 가장 강력한 방법은 무엇입니까?


항목 목록이있는 UITableView가 있습니다. 항목을 선택하면 viewController가 푸시되고 다음이 진행됩니다. viewDidLoad 메서드에서 내 하위보기에 필요한 데이터에 대해 URLRequest를 해제합니다. drawRect가 재정의 된 UIView 하위 클래스입니다. 데이터가 클라우드에서 도착하면 뷰 계층을 구축하기 시작합니다. 문제의 서브 클래스는 데이터를 전달받으며 drawRect 메소드는 이제 렌더링에 필요한 모든 것을 갖습니다.

그러나.

drawRect를 명시 적으로 호출하지 않기 때문에-Cocoa-Touch에서 처리합니다.-Cocoa-Touch에 실제로이 UIView 서브 클래스가 렌더링되기를 원한다고 알려주는 방법이 없습니다. 언제? 이제 좋을 것입니다!

[myView setNeedsDisplay]를 사용해 보았습니다. 이것은 때때로 작동합니다. 매우 드문 드문

나는 몇 시간 동안 이것과 씨름하고 있습니다. UIView를 다시 렌더링하도록 강력하고 확실한 접근 방식을 제공해 주시겠습니까?

다음은 뷰에 데이터를 공급하는 코드 스 니펫입니다.

// Create the subview
self.chromosomeBlockView = [[[ChromosomeBlockView alloc] initWithFrame:frame] autorelease];

// Set some properties
self.chromosomeBlockView.sequenceString     = self.sequenceString;
self.chromosomeBlockView.nucleotideBases    = self.nucleotideLettersDictionary;

// Insert the view in the view hierarchy
[self.containerView          addSubview:self.chromosomeBlockView];
[self.containerView bringSubviewToFront:self.chromosomeBlockView];

// A vain attempt to convince Cocoa-Touch that this view is worthy of being displayed ;-)
[self.chromosomeBlockView setNeedsDisplay];

건배, 더그


UIView를 다시 렌더링 하도록 보장하는 확실한 방법 입니다 [myView setNeedsDisplay]. 문제가있는 경우 다음 문제 중 하나에 해당 될 수 있습니다.

  • 실제로 데이터를 갖기 전에 호출하거나 -drawRect:무언가를 캐싱하고 있습니다.

  • 이 메소드를 호출하는 순간 뷰가 그려 질 것으로 예상됩니다. Cocoa 그리기 시스템을 사용하여 "지금 당장 두 번째 그리기"를 요구할 방법이 없습니다. 그것은 전체보기 합성 시스템, 쓰레기 성능을 방해하고 모든 종류의 인공물을 만들 것입니다. "다음 드로우 사이클에서 드로우해야합니다"라고 말하는 방법 만 있습니다.

당신이 필요로하는 것이 "일부 로직, 그리기, 더 많은 로직"이라면, "일부 더 많은 로직"을 별도의 메소드에 -performSelector:withObject:afterDelay:넣고 0의 지연을 사용하여 호출해야합니다. 다음 추첨주기. 이러한 종류의 코드 예제와 필요할 수있는 경우에 대해서는 이 질문참조하십시오 (가능한 경우 코드를 복잡하게하기 때문에 다른 솔루션을 찾는 것이 가장 좋습니다).

물건이 그려지지 않는다고 생각되면 중단 점을 넣고 -drawRect:언제 전화를했는지 확인하십시오. 을 호출 -setNeedsDisplay하지만 -drawRect:다음 이벤트 루프에서 호출되지 않으면 뷰 계층 구조를 파헤쳐 서 현명하지 않도록하십시오. 지나치게 영리하다는 것은 내 경험에서 잘못된 그림을 그리는 가장 큰 원인입니다. 시스템이 원하는 것을 수행하도록 속이는 방법을 가장 잘 알고 있다고 생각하면 일반적으로 원하지 않는 것을 정확하게 수행하게됩니다.


setNeedsDisplay와 drawRect : (5 초) 호출 사이에 큰 지연 문제가있었습니다. 메인 스레드와 다른 스레드에서 setNeedsDisplay를 호출했습니다. 이 호출을 메인 스레드로 옮긴 후 지연이 사라졌습니다.

이것이 도움이되기를 바랍니다.


(호출 코드로 돌아 가기 전에) 동기식 으로 뷰를 강제로 작성하는 환불 보장, 강화 된 확실한 방법 하위 클래스 와의 상호 작용 을 구성하는 것 입니다.CALayerUIView

당신의 UIView의 하위 클래스에서는 생성 - display"고 레이어 알 방법 예는 디스플레이를 필요를 "다음 " 그래서 만들려면 "

/// Redraws the view's contents immediately.
/// Serves the same purpose as the display method in GLKView.
/// Not to be confused with CALayer's `- display`; naming's really up to you.
- (void)display
{
    CALayer *layer = self.layer;
    [layer setNeedsDisplay];
    [layer displayIfNeeded];
}

또한 - drawLayer:inContext:개인 / 내부 그리기 메서드를 호출 하는 메서드를 구현합니다 (모든 UIView가 CALayerDelegate이므로 작동합니다) .

/// Called by our CALayer when it wants us to draw
///     (in compliance with the CALayerDelegate protocol).
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    UIGraphicsPushContext(context);
    [self internalDrawWithRect:self.bounds];
    UIGraphicsPopContext();
}

그리고 - internalDrawWithRect:안전 장치와 함께 사용자 정의 방법을 만드십시오 - drawRect:.

/// Internal drawing method; naming's up to you.
- (void)internalDrawWithRect:(CGRect)rect
{
    // @FILLIN: Custom drawing code goes here.
    //  (Use `UIGraphicsGetCurrentContext()` where necessary.)
}

/// For compatibility, if something besides our display method asks for draw.
- (void)drawRect:(CGRect)rect {
    [self internalDrawWithRect:rect];
}

And now just call [myView display] whenever you really-really need it to draw. - display will tell the CALayer to displayIfNeeded, which will synchronously call back into our - drawLayer:inContext: and do the drawing in - internalDrawWithRect:, updating the visual with what's drawn into the context before moving on.


This approach is similar to @RobNapier's above, but has the advantage of calling - displayIfNeeded in addition to - setNeedsDisplay, which makes it synchronous.

This is possible because CALayers expose more drawing functionality than UIViews do— layers are lower-level than views and designed explicitly for the purpose of highly-configurable drawing within the layout, and (like many things in Cocoa) are designed to be used flexibly (as a parent class, or as a delegator, or as a bridge to other drawing systems, or just on their own).

More information about the configurability of CALayers can be found in the Setting Up Layer Objects section of the Core Animation Programming Guide.


I had the same problem, and all the solutions from SO or Google didn't work for me. Usually, setNeedsDisplay does work, but when it doesn't...
I've tried calling setNeedsDisplay of the view just every possible way from every possible threads and stuff - still no success. We know, as Rob said, that

"this needs to be drawn in the next draw cycle."

But for some reason it wouldn't draw this time. And the only solution I've found is calling it manually after some time, to let anything that blocks the draw pass away, like this:

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 
                                        (int64_t)(0.005 * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
    [viewToRefresh setNeedsDisplay];
});

It's a good solution if you don't need the view to redraw really often. Otherwise, if you're doing some moving (action) stuff, there is usually no problems with just calling setNeedsDisplay.

I hope it will help someone who is lost there, like I was.


Well I know this might be a big change or even not suitable for your project, but did you consider not performing the push until you already have the data? That way you only need to draw the view once and the user experience will also be better - the push will move in already loaded.

The way you do this is in the UITableView didSelectRowAtIndexPath you asynchronously ask for the data. Once you receive the response, you manually perform the segue and pass the data to your viewController in prepareForSegue. Meanwhile you may want to show some activity indicator, for simple loading indicator check https://github.com/jdg/MBProgressHUD

참고URL : https://stackoverflow.com/questions/1503761/what-is-the-most-robust-way-to-force-a-uiview-to-redraw

반응형