Когда мое приложение возвращается к своему корневому контроллеру представления, в методе viewDidAppear:
мне нужно удалить все подпредставления.
Как я могу это сделать?
Когда мое приложение возвращается к своему корневому контроллеру представления, в методе viewDidAppear:
мне нужно удалить все подпредставления.
Как я могу это сделать?
Изменить: Благодаря cocoafan: эта ситуация запутана тем фактом, что NSView
и UIView
обращаться с вещами по-другому. Для NSView
(только для настольных компьютеров Mac) вы можете просто использовать следующее:
[someNSView setSubviews:[NSArray array]];
Для UIView
(только разработка для iOS) вы можете безопасно использовать makeObjectsPerformSelector:
, потому что свойство subviews
вернет копию массива вложенных представлений:
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
Спасибо Томми за то, что он указал, что makeObjectsPerformSelector:
, похоже, изменяет массив subviews
во время его перечисления (что он делает для NSView
, но не для UIView
).
Дополнительные сведения см. В этом вопросе SO.
Примечание. Использование любого из этих двух методов приведет к удалению всех представлений, содержащихся в основном представлении, и их освобождение, если они не сохраняются где-либо еще. Из документации Apple по removeFromSuperview:
Если супервизор получателя не равен нулю, этот метод освобождает получателя. Если вы планируете повторно использовать представление, обязательно сохраните его перед вызовом этого метода и обязательно отпустите его при необходимости, когда вы закончите с ним или после добавления в другую иерархию представлений.
UIView
возвращает копию subviews
изменяемого массива, так что этот код просто работает. Совершенно другая история на рабочем столе, где тот же код выдает исключение. См. stackoverflow.com / questions / 4665179 /
- person e.James; 08.03.2011
UIView
. Это NSView
, что позволяет устанавливать их извне.
- person e.James; 16.03.2011
someUIView.Subviews.All( v => { v.RemoveFromSuperview(); return true; } );
. ИМХО чище сказать то, что вы имеете в виду: someUIView.Subviews.ToList().ForEach( v => v.RemoveFromSuperview() );
.
- person ToolmakerSteve; 13.07.2016
Получите все подпредставления из корневого контроллера и отправьте каждому removeFromSuperview:
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
self.view
, как и вы.
- person e.James; 28.01.2010
for (UIView *v in [self.view subviews])
это проще
- person Frade; 18.06.2014
В Swift вы можете использовать функциональный подход следующим образом:
view.subviews.forEach { $0.removeFromSuperview() }
Для сравнения императивный подход будет выглядеть так:
for subview in view.subviews {
subview.removeFromSuperview()
}
Эти фрагменты кода работают только в iOS / tvOS, однако в macOS все немного по-другому.
.map
. это чистый побочный эффект, и с ним лучше справиться следующим образом: view.subviews.forEach() { $0.removeFromSuperview() }
- person Martin Algesten; 24.11.2015
Если вы хотите удалить все подпредставления в 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 также будет удален. Это может вызвать исключение за пределами допустимого диапазона.
- person Daniel; 03.06.2015
[yourView subviews]
возвращает КОПИЮ массива, поэтому это безопасно. (ОБРАТИТЕ ВНИМАНИЕ, что в OS X то, что вы говорите, верно.)
- person ToolmakerSteve; 13.07.2016
Попробуйте так быстро 2.0
view.subviews.forEach { $0.removeFromSuperview() }
forEach
было добавлено после вашего, я это пропустил. Извинения.
- person Cristik; 27.01.2016
Используйте следующий код, чтобы удалить все подпредставления.
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
Использование расширения Swift UIView
:
extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}
В 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).
Если вы используете Swift, это очень просто:
subviews.map { $0.removeFromSuperview }
По своей философии он похож на подход makeObjectsPerformSelector
, но с немного большей безопасностью типов.
map
не должно вызывать побочных эффектов. К тому же такого же результата можно добиться с помощью forEach
.
- person Cristik; 26.10.2018
Для 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 были установлены ограничения, которые очищались.
В 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
. Это определенно ошибочный и НЕИСПОЛЬЗУЕМЫЙ код.
- person Daniel; 22.05.2014