Ответы:
Редактировать: С благодаря Cocoafan : Эта ситуация запутана тем, что NSViewи по- UIViewразному. Для NSView(только для разработки на настольном Mac) вы можете просто использовать следующее:
[someNSView setSubviews:[NSArray array]];
Для UIView(только для iOS) вы можете безопасно использовать, makeObjectsPerformSelector:потому что subviewsсвойство вернет копию массива подпредставлений:
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
Спасибо Томми за то, что он указал, что, по- makeObjectsPerformSelector:видимому, изменяет subviewsмассив во время его перечисления (что он делает для NSView, но не для UIView).
Пожалуйста, смотрите этот вопрос для получения более подробной информации.
Примечание. Использование любого из этих двух методов приведет к удалению всех представлений, содержащихся в вашем главном представлении, и их освобождению , если они не сохраняются в другом месте. Из документации Apple по removeFromSuperview :
Если супервизор получателя не ноль, этот метод освобождает получателя. Если вы планируете повторно использовать представление, обязательно сохраните его перед вызовом этого метода и обязательно отмените его, когда вы закончите с ним или после добавления его в другую иерархию представления.
UIViewвозвращает копию на subviewsизменяемый массив, так что этот код просто работает. Совершенно другая история на рабочем столе, где один и тот же код выдаст исключение. См stackoverflow.com/questions/4665179/...
someUIView.Subviews.All( v => { v.RemoveFromSuperview(); return true; } );. ИМХО чище сказать что ты имеешь ввиду someUIView.Subviews.ToList().ForEach( v => v.RemoveFromSuperview() );.
Получите все подпредставления от вашего корневого контроллера и отправьте каждому a removeFromSuperview:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
self.viewкак ты.
for (UIView *v in [self.view subviews])это проще
В Swift вы можете использовать такой функциональный подход :
view.subviews.forEach { $0.removeFromSuperview() }
Для сравнения, императивный подход будет выглядеть так:
for subview in view.subviews {
subview.removeFromSuperview()
}
Эти фрагменты кода работают только в iOS / tvOS, хотя в MacOS все немного иначе.
(subviews as [UIView]).map { $0.removeFromSuperview() }
.map. это чистый побочный эффект, с которым лучше справляться следующим образом:view.subviews.forEach() { $0.removeFromSuperview() }
Если вы хотите удалить все подпредставления в вашем UIView (здесь yourView), то напишите этот код при нажатии кнопки:
[[yourView subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
Это относится только к OSX, так как в iOS сохраняется копия массива
При удалении всех подпредставлений хорошей идеей будет начать удаление в конце массива и продолжать удаление, пока не дойдете до начала. Это может быть достигнуто с помощью этих двух строк кода:
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 :
Посылает каждому объекту в массиве сообщение, идентифицированное данным селектором, начиная с первого объекта и продолжая через массив до последнего объекта.
(что было бы неправильным направлением для этой цели)
removeFromSuperviewокончании UIView будет удален из массива, и если нет других живых экземпляров, имеющих сильное отношение к UIView, UIView также будет удален. Это может вызвать исключение из-за границы.
[yourView subviews]возвращает копию массива, поэтому является безопасным. (ЗАМЕТЬТЕ, что на OSX, что вы говорите, правильно.)
Попробуйте этот способ Swift 2.0
view.subviews.forEach { $0.removeFromSuperview() }
forEachпосле вашего решения было добавлено основанное решение, я пропустил это. Извиняюсь.
Используйте следующий код, чтобы удалить все подпредставления.
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
Для того, чтобы удалить все подпункты синтаксиса:
- (void)makeObjectsPerformSelector:(SEL)aSelector;
Использование :
[self.View.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
Этот метод присутствует в файле NSArray.h и использует интерфейс NSArray (NSExtendedArray)
Если вы используете Swift, это так просто, как:
subviews.map { $0.removeFromSuperview }
По своей философии это похоже на makeObjectsPerformSelectorподход, но с большей степенью безопасности.
mapне должно приводить к побочным эффектам. Кроме того , тот же результат может быть достигнут с помощью forEach.
Для 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--;
}
iCount++и iCount--, оставляя индекс одинаковым, так что это будет бесконечный цикл, если [oSubView count]>0. Это определенно глючит и НЕ ПОЛЕЗНЫЙ код.