Удалить все подвиды?


когда мое приложение вернется к своему корневому контроллеру представления, в viewDidAppear: метод мне нужно удалить все подвиды.

Как я могу это сделать?

15 297

15 ответов:

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

[someNSView setSubviews:[NSArray array]];

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

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

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

см. это так вопрос для более подробной информации.

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

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

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

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

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

view.subviews.forEach { .removeFromSuperview() }

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

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

эти фрагменты кода работают только в iOS / tvOS хотя, на macOS все немного по-другому.

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

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

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

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()
}

Примечание

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

следовательно, код

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

должны не использоваться.

цитата документация Apple о makeObjectsPerformSelector:

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

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

попробуйте этот способ swift 2.0

view.subviews.forEach { .removeFromSuperview() }

используйте следующий код для удаления всех вложенных представлений.

for (UIView *view in [self.view subviews]) 
{
 [view removeFromSuperview];
}

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

subviews.map { .removeFromSuperview }

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

С Помощью Swift

в objective-C, идти вперед и создать метод категории от класса UIView.

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

чтобы удалить все подвиды синтаксис:

- (void)makeObjectsPerformSelector:(SEL)aSelector;

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

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

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

view.subviews.forEach { .removeFromSuperview() }

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

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 были установлены ограничения, которые очищались.

в monotouch / xamarin.ios это сработало для меня:

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

чтобы удалить все подвиды из супервизоров:

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