2010-01-28 1 views

ответ

541

Edit: С благодарностью cocoafan: Эта ситуация спутал тем, что NSView и UIView рукояток вещи по-разному. Для NSView (рабочего стола развития Mac только), вы можете просто использовать следующее:

[someNSView setSubviews:[NSArray array]]; 

Для UIView (развития IOS только), вы можете смело использовать makeObjectsPerformSelector: потому что subviews свойство возвращает копию из массива подвиды:

[[someUIView subviews] 
makeObjectsPerformSelector:@selector(removeFromSuperview)]; 

Спасибо Tommy за указание на то, что makeObjectsPerformSelector: появляется, чтобы изменить subviews массив во время его перечислен (что он делает для NSView, но не для UIView).

Для получения более подробной информации см. this SO question.

Примечание: Использование любого из этих двух методов удалит все вид, что ваш основной вид содержит и освободить их, если они не будут сохранены в другом месте. Из документации Apple по адресу removeFromSuperview:

Если супервизор приемника не равен нулю, этот метод освобождает приемник. Если вы планируете повторно использовать представление, обязательно сохраните его перед вызовом этого метода и не забудьте выпустить его по мере необходимости, когда вы закончите с ним, или после добавления его в другую иерархию представлений.

+9

Вы уверены, что это безопасно? Он мутирует список при повторении его, и я не могу найти окончательное утверждение в документации Apple. – Tommy

+8

@ Томми: Это хороший момент. Некоторый Googling поднял ответ: 'UIView' возвращает * копию * изменчивого массива' subviews', поэтому этот код просто работает. Совершенно другая история на рабочем столе, где тот же код генерирует исключение. См. Http://stackoverflow.com/questions/4665179/behavior-difference-between-uiview-subviews-and-nsview-subviews –

+0

@Tommy: Я обновил свой ответ соответственно. Спасибо, что поймали это! –

160

Получить все подвидов от корневого контроллера и отправить каждый из removeFromSuperview:

NSArray *viewsToRemove = [self.view subviews]; 
for (UIView *v in viewsToRemove) { 
    [v removeFromSuperview]; 
} 
+0

+1 и спасибо. Я должен был также использовать 'self.view', как есть. –

+1

почему бы и нет ?! 'for (UIView * v in [self.view subviews])' его проще – Frade

+3

@Frade Это намного яснее и более подробным, как он это сделал. Вербальная и читабельность> сохранение нажатий клавиш – taylorcressy

14

Если вы хотите, чтобы удалить все подвиды на вашем UIView (здесь yourView), затем записать этот код на кнопке нажмите:

[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)]; 
+12

Добро пожаловать в переполнение стека! Не могли бы вы добавить некоторые рассказы, чтобы объяснить, почему этот код работает, и что делает его ответом на вопрос? Это было бы очень полезно для человека, задающего вопрос, и любого другого, кто приходит. Кроме того, уже принятый ответ включает код, который по существу такой же, как и этот. –

+4

Как это могло бы помочь в большей степени, чем принятый ответ: он идентичен. Зачем писать? – Rambatino

0

Для ios6, использующего автоспуск, мне пришлось добавить немного кода, чтобы удалить ограничения.

NSMutableArray * constraints_to_remove = [ @[] mutableCopy] ; 
for(NSLayoutConstraint * constraint in tagview.constraints) { 
    if([tagview.subviews containsObject:constraint.firstItem] || 
     [tagview.subviews containsObject:constraint.secondItem]) { 
     [constraints_to_remove addObject:constraint]; 
    } 
} 
[tagview removeConstraints:constraints_to_remove]; 

[ [tagview subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; 

Я уверен, что это более простой способ сделать это, но это сработало для меня. В моем случае я не мог использовать прямой [tagview removeConstraints:tagview.constraints], поскольку в XCode были установлены ограничения, которые очищались.

1

Для того, чтобы удалить все подвидов Синтаксис:

- (void)makeObjectsPerformSelector:(SEL)aSelector; 

Использование:

[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 

Этот метод присутствует в NSArray.ч файл и использует интерфейс NSArray (NSExtendedArray)

-10

Для того, чтобы удалить все подвиды из superviews:

NSArray *oSubView = [self subviews]; 
for(int iCount = 0; iCount < [oSubView count]; iCount++) 
{ 
    id object = [oSubView objectAtIndex:iCount]; 
    [object removeFromSuperview]; 
    iCount--; 
} 
+0

Пара основных ошибок здесь @ Pravin. Во-первых, вам нужно, чтобы «объект» был определен как UIView *, иначе вы получили бы ошибку компилятора с [object removeFromSuperview]. Во-вторых, ваш цикл for уже уменьшает iCount, поэтому вы пропускаете дополнительную строку iCount--. И, наконец, есть два рабочих и правильных подхода выше, и ваш не является более элегантным и быстрым. – amergin

+5

каждой итерации вы делаете 'iCount ++' и 'iCount -', оставляя индекс одинаковым, поэтому он будет бесконечным циклом, если '[oSubView count]> 0'. Это определенно багги и ** NOT USABLE ** код. – Daniel

7

При удалении всех подвидов, это хорошая идея, чтобы начать удаление в конце массива и продолжайте удалять, пока не достигнете начала. Это может быть достигнуто с этими двумя строками кода:

for (int i=mySuperView.subviews.count-1; i>=0; i--) 
     [[mySuperView.subviews objectAtIndex:i] removeFromSuperview]; 

SWIFT 1,2

for var i=mySuperView.subviews.count-1; i>=0; i-- { 
    mySuperView.subviews[i].removeFromSuperview(); 
} 

или (менее эффективным, но более читаемым)

for subview in mySuperView.subviews.reverse() { 
    subview.removeFromSuperview() 
} 

Примечание

Вы должны NOT удалите подзапросы в нормальном порядке, так как это может привести к сбою, если экземпляр UIView удален до того, как сообщение removeFromSuperview было отправлено всем объектам массива. (Очевидно, что удаление последнего элемента не приведет к аварии)

Поэтому код

[[someUIView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; 

должен НЕ использовать.

Цитата Apple documentation about makeObjectsPerformSelector:

Посылает каждый объект в массиве сообщения, идентифицированное в данном селектора, начиная с первым объектом, и продолжающиеся через массив до последнего объекта.

(что было бы неправильное направление для этой цели)

+0

Не могли бы вы привести пример того, о чем вы говорите? Не знаете, что вы называете «элементом». Как удалить эти элементы перед вызовом removeFromSuperView? –

+0

с элементом Я имел в виду экземпляр UIView (отредактирован). – Daniel

+0

Но как удалить экземпляр UIView при вызове этого метода?Вы хотите удалить из массива subview? –

69

В Swift вы можете использовать функциональный подход так:

view.subviews.forEach { $0.removeFromSuperview() } 

В сравнении, императив подход будет выглядеть так:

for subview in view.subviews { 
    subview.removeFromSuperview() 
} 

Эти фрагменты кода работают только в iOS/tvOS, хотя на MacOS все немного отличается.

+4

'' '(subviews as [UIView]). Map {$ 0.removeFromSuperview()}' '' – DeFrenZ

+5

не работает, поскольку функция возвращает значение, и это просто отбрасывает результат «.map». это чистый побочный эффект и лучше обрабатывается следующим образом: 'view.subviews.forEach() {$ 0.removeFromSuperview()}' –

+1

Вы правы, Мартин, я согласен с вами. Я просто не знал, что для массивов Array существует метод forEach(). Когда он был добавлен или я просто наблюдал за ним? Я обновил свой ответ! – Dschee

2

Если вы используете Swift, это так просто, как:

subviews.map { $0.removeFromSuperview } 

Это похоже на философию к makeObjectsPerformSelector подхода, однако с немного большей безопасности типа.

2

Использование Swift UIView расширение:

extension UIView { 
    func removeAllSubviews() { 
     for subview in subviews { 
      subview.removeFromSuperview() 
     } 
    } 
} 
4

Попробуйте этот путь быстрый 2,0

view.subviews.forEach { $0.removeFromSuperview() } 
+0

Это решение уже было предоставлено: http://stackoverflow.com/a/27117440/1974224 – Cristik

+2

Разве вы не видите дату ответа на дату раньше? Почему бы не вставить ссылку на ответ в этот ответ? –

+1

Правильно ... ответ был отправлен перед вашим, однако решение 'forEach' было добавлено после вас, я пропустил это. Извиняюсь. – Cristik

0

В MonoTouch/xamarin.ios это работало для меня:

SomeParentUiView.Subviews.All(x => x.RemoveFromSuperview); 
2

В Objective-C , продолжайте и создайте метод категории класса UIView.

- (void)removeAllSubviews 
{ 
    for (UIView *subview in self.subviews) 
     [subview removeFromSuperview]; 
} 
2

Используйте следующий код, чтобы удалять все подзаголовки.

for (UIView *view in [self.view subviews]) 
{ 
[view removeFromSuperview]; 
} 
Смежные вопросы