모든 CALayer의 하위 계층 제거
레이어의 모든 하위 레이어를 삭제하는 데 문제가 있습니다. 현재 수동으로 수행하지만 불필요한 혼란을 가져옵니다. Google에서 이에 대한 많은 주제를 찾았지만 대답이 없습니다.
나는 다음과 같은 것을 시도했다.
for (CALayer * rootLayer.sublayers의 계층) { [레이어 removeFromSublayer]; }
하지만 작동하지 않았습니다.
또한 rootLayer.sublayers를 별도의 NSArray로 복제하려고 시도했지만 결과는 동일했습니다.
어떤 아이디어?
편집하다:
지금 작동한다고 생각했지만 틀 렸습니다. CALayers에서는 잘 작동하지만 CATextLayers에서는 작동하지 않습니다. 어떤 아이디어?
레이어에서 모든 하위 레이어를 제거하는 가장 간단한 방법은 하위 레이어 속성을 nil로 설정하는 것입니다.
rootLayer.sublayers = nil;
다음이 작동합니다.
for (CALayer *layer in [[rootLayer.sublayers copy] autorelease]) {
[layer removeFromSuperlayer];
}
[rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
Swift (짧은 버전) :
layer.sublayers?.forEach { $0.removeFromSuperlayer() }
호출 rootLayer.sublayers = nil;
하면 충돌이 발생할 수 있습니다 (예 : iOS 8에서 소유하는 뷰에서 removeFromSuperview를 두 번 호출하는 경우 rootLayer
).
올바른 방법은 다음과 같아야합니다.
[[rootLayer.sublayers copy] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]
반복적으로 호출 copy
되는 배열 removeFromSuperlayer
이 수정되지 않도록에 대한 호출 이 필요합니다 . 그렇지 않으면 예외가 발생합니다.
모든 하위 계층을 무차별 적으로 제거하면 iOS 7에서 심각한 충돌이 발생하며 이는 프로그램 실행 후반부에 발생할 수 있습니다. 나는 철저하게 모두 사용하여이 테스트 한 rootLayer.sublayers = nil
과 [rootLayer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]
. 엉망이되는 시스템 생성 레이어가 있어야합니다.
고유 한 레이어 배열을 유지하고 직접 제거해야합니다.
[myArrayOfLayersIAddedMyself makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
하위보기 가 포함 된 경우 self.view.layer.sublayers = nil
및 둘 다 설정 [layer removeFromSuperlayer]
하면 충돌이 발생합니다 UIView
. CALayer
superLayer 에서 제거 하는 가장 좋은 방법 은 레이어 배열을 유지하는 것입니다. 예를 들어 그 배열은 arrayOfLayers이고,
레이어를 UIView.sublayer
추가 할 때마다이 배열에 해당 레이어 를 추가합니다.
예를 들면
[arrayOfLayers addObject:layer];
[self.view.layer addSublayer:layer];
제거하는 동안 이것을 호출하십시오.
[arrayOfLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
역 열거를 사용하는 것은 어떻습니까?
NSEnumerator *enumerator = [rootLayer.sublayers reverseObjectEnumerator];
for(CALayer *layer in enumerator) {
[layer removeFromSuperlayer];
}
순서가 정상이면 하위 계층의 그룹이 열거 중에 변경되기 때문입니다. 위 코드의 결과를 알고 싶습니다.
인덱스 0에서 첫 번째 하위 계층 만 삭제하려고했는데 다음과 같이 작동했습니다.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell.contentView.layer.sublayers count] != 0) {
[[cell.contentView.layer.sublayers objectAtIndex:0] removeFromSuperlayer];
}
Xamarin / C #에서이 작업을 수행해야했습니다. 나는 국경을 위해 UITableViewCell
약간 CAShapeLayers
을 가지고 있었다 . 위의 모든 옵션 (배열 복사 및 레이어 제거 포함)으로 인해 충돌이 발생했습니다. 나를 위해 일한 접근 방식 :
을 추가 할 때 CALayer
이름을 지정했습니다.
var border = new CALayer();
border.BackgroundColor = color.CGColor;
border.Frame = new CGRect(x, y, width, height);
border.Name = "borderLayerName";
Layer.AddSublayer(border);
에서 PrepareForReuse
온 UITableViewCell
, 나는의 복사본을 만든 SubLayers
내가 이전에 할당 된 이름과 일치하는 것을 재산 및 제거 아무것도 :
CALayer[] copy = new CALayer[Layer.Sublayers.Length];
Layer.Sublayers.CopyTo(copy, 0);
copy.FirstOrDefault(l => l.Name == "borderLayerName")?.RemoveFromSuperLayer();
충돌이 없습니다.
도움이 되었기를 바랍니다!
나는 같은 문제에 직면했고 많은 해결책을 찾았지만 완벽하지는 않습니다.
마지막으로 pnavk의 위 답변 에서 아이디어를 얻었습니다. Xamarin / C # 사용자를위한 코드가 있습니다.
iOS 버전은 다음과 같습니다.
스위프트 2.3
if rootLayer.sublayers?.count > 0 {
rootLayer.sublayers?.forEach {
if $0.name == "bottomBorderLayer" {
$0.removeFromSuperlayer()
}
}
}
let border = CALayer()
let height = CGFloat(1.0)
border.borderColor = UIColor.blackColor().CGColor
border.borderWidth = height
border.frame = CGRectMake(0, self.frame.size.height - height, self.frame.size.width, self.frame.size.height)
border.name = "bottomBorderLayer"
rootLayer.addSublayer(border)
rootLayer.masksToBounds = true
목표 -C
if (rootLayer.sublayers.count > 0) {
for (CALayer *layer in rootLayer.sublayers) {
if ([layer.name isEqualToString:@"bottomBorderLayer"]) {
[layer removeFromSuperlayer];
}
}
}
CALayer *border = [[CALayer alloc] init];
CGFloat height = 1.0;
border.borderColor = [UIColor blackColor].CGColor;
border.borderWidth = height;
border.frame = CGRectMake(0, self.view.frame.size.height - height, self.view.frame.size.width, self.view.frame.size.height);
border.name = @"bottomBorderLayer";
[rootLayer addSublayer:border];
rootLayer.masksToBounds = TRUE;
The above code will work for bottom border only. You can change the border side as per your requirement.
Here before adding any layer to the controller, I have just run a for loop to check whether any border is already applied or not?
To identify previously added border I use name property of CALayer. And compare that layer before remove from sublayers.
I have tried the same code before using name property, but It creates random crash. But after using name property and comparing name before remove will solve the crash issue.
I hope this will help someone.
For swift3+,You can use this.
yourView.layer.sublayers?.removeAll(keepingCapacity: true)
See here: Apple API Reference
Or you can: yourView.layer.sublayers?.forEach{ $0.removeFromSuperlayer()}
What about doing:
rootLayer.sublayers = @[];
For sure you can do:
self.layer.sublayers=nil;
as suggested by Pascal Bourque. But it's better to call the setter for sublayers property:
[self.layer setSublayers:nil];
To avoid any clean up issues if there might be.
참고URL : https://stackoverflow.com/questions/2067578/removing-all-calayers-sublayers
'developer tip' 카테고리의 다른 글
Universal Apps MessageBox :“ 'MessageBox'라는 이름이 현재 컨텍스트에 없습니다.” (0) | 2020.12.06 |
---|---|
옵션을 변환하는 방법 (0) | 2020.12.06 |
Response :: download를 사용하여 laravel에서 파일 다운로드 (0) | 2020.12.06 |
iOS의 동영상 URL 또는 데이터에서 미리보기 이미지 가져 오기 (0) | 2020.12.06 |
CSS로 테이블의 마지막 td 스타일 지정 (0) | 2020.12.06 |