เมื่อแอพของฉันกลับไปที่ตัวควบคุมมุมมองรูทในviewDidAppear:
วิธีที่ฉันต้องการลบการดูทั้งหมด
ฉันจะทำสิ่งนี้ได้อย่างไร
เมื่อแอพของฉันกลับไปที่ตัวควบคุมมุมมองรูทในviewDidAppear:
วิธีที่ฉันต้องการลบการดูทั้งหมด
ฉันจะทำสิ่งนี้ได้อย่างไร
คำตอบ:
แก้ไข:ด้วยความขอบคุณcocoafan : สถานการณ์นี้ยุ่งเหยิงกับความจริงที่ว่าNSView
และUIView
จัดการกับสิ่งต่าง ๆ สำหรับNSView
( สำหรับการพัฒนาบนเดสก์ท็อป Mac เท่านั้น) คุณสามารถใช้สิ่งต่อไปนี้:
[someNSView setSubviews:[NSArray array]];
สำหรับUIView
(การพัฒนา iOS เท่านั้น) คุณสามารถใช้งานได้อย่างปลอดภัยmakeObjectsPerformSelector:
เนื่องจากsubviews
คุณสมบัติจะส่งคืนสำเนาของอาร์เรย์ของการดูย่อย:
[[someUIView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
ขอบคุณTommy ที่ชี้ให้เห็นว่าmakeObjectsPerformSelector:
ดูเหมือนจะแก้ไขsubviews
อาเรย์ในขณะที่มันกำลังถูกแจกแจง (ซึ่งมันทำเพื่อNSView
แต่ไม่ใช่สำหรับUIView
)
โปรดดูคำถาม SO นี้สำหรับรายละเอียดเพิ่มเติม
หมายเหตุ:การใช้วิธีใดวิธีหนึ่งจากสองวิธีนี้จะลบทุกมุมมองที่มุมมองหลักของคุณมีและปล่อยมุมมองนั้นหากไม่ได้เก็บไว้ที่อื่น จากเอกสารของ Apple ในremoveFromSuperview :
หาก superview ของผู้รับไม่เป็นศูนย์วิธีนี้จะปล่อยผู้รับ หากคุณวางแผนที่จะนำมุมมองนั้นกลับมาใช้ใหม่ให้แน่ใจว่าได้เก็บมุมมองนั้นไว้ก่อนที่จะเรียกวิธีการนี้และให้แน่ใจว่าได้ปล่อยมุมมองนั้นตามความเหมาะสมเมื่อคุณทำเสร็จแล้ว
UIView
กลับมา: ส่งคืนสำเนาของsubviews
อาร์เรย์ที่ไม่แน่นอนดังนั้นรหัสนี้ใช้งานได้ เรื่องราวที่แตกต่างอย่างสิ้นเชิงบนเดสก์ท็อปโดยที่รหัสเดียวกันจะมีข้อยกเว้น ดูstackoverflow.com/questions/4665179/…
someUIView.Subviews.All( v => { v.RemoveFromSuperview(); return true; } );
ดังนั้น IMHO สะอาดกว่าที่จะพูดในสิ่งที่คุณหมายถึง: someUIView.Subviews.ToList().ForEach( v => v.RemoveFromSuperview() );
.
รับมุมมองย่อยทั้งหมดจากตัวควบคุมรูทของคุณและส่ง 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]
คืนค่า COPY ของอาร์เรย์จึงปลอดภัย (โปรดทราบว่าใน OSX สิ่งที่คุณพูดนั้นถูกต้อง)
ลองวิธีนี้อย่างรวดเร็ว 2.0
view.subviews.forEach { $0.removeFromSuperview() }
forEach
มีการเพิ่มโซลูชันพื้นฐานหลังจากคุณแล้วฉันพลาดมันไป ขอโทษ.
ใช้รหัสต่อไปนี้เพื่อลบการชมย่อยทั้งหมด
for (UIView *view in [self.view subviews])
{
[view removeFromSuperview];
}
ใช้UIView
ส่วนขยายSwift :
extension UIView {
func removeAllSubviews() {
for subview in subviews {
subview.removeFromSuperview()
}
}
}
ในวัตถุประสงค์ -C ไปข้างหน้าและสร้างวิธีการหมวดหมู่ออกจากคลาส UIView
- (void)removeAllSubviews
{
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
}
view.subviews.forEach { $0.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
นี่เป็นรหัสรถและใช้ไม่ได้แน่นอน