ตรวจสอบว่ามุมมองย่อยอยู่ในมุมมองหรือไม่


97

ฉันทำ app ที่ฉันจะเพิ่ม subview ให้มุมมองที่ใช้ในaddSubview: IBActionในทำนองเดียวกันเมื่อปุ่มที่IBActionถูกแตะอีกครั้งควรเรียกremoveFromSuperviewใช้มุมมองย่อยที่เพิ่มเข้ามาIBAction:

รหัส PSEUDO

-(IBAction)showPopup:(id)sender 
{
    System_monitorAppDelegate *delegate = (System_monitorAppDelegate *)[[UIApplication sharedApplication] delegate];
    UIView *rootView = delegate.window.rootViewController.view;

    if([self popoverView] is not on rootView) 
    { 
        [rootView addSubview:[self popoverView]];
    } 
    else 
    {
        [[self popoverView] removeFromSuperview];
    }

}

คำตอบ:


271

คุณอาจจะมองหา UIView ได้-(BOOL)isDescendantOfView:(UIView *)view;ดำเนินการในการอ้างอิงระดับ UIView

ค่าส่งคืน ใช่ถ้าผู้รับเป็นมุมมองย่อยในทันทีหรือระยะไกลหรือหากมุมมองเป็นผู้รับเอง มิฉะนั้นไม่

คุณจะได้รหัสเช่น:

วัตถุประสงค์ -C

- (IBAction)showPopup:(id)sender {
    if(![self.myView isDescendantOfView:self.view]) { 
        [self.view addSubview:self.myView];
    } else {
        [self.myView removeFromSuperview];
    }
}

สวิฟต์ 3

@IBAction func showPopup(sender: AnyObject) {
    if !self.myView.isDescendant(of: self.view) {
        self.view.addSubview(self.myView)
    } else {
        self.myView.removeFromSuperview()
    }
}

2
ไม่ได้ผลเพียงแค่เพิ่มมุมมองลงไป ฉันจะแก้ไขรหัสเพื่อแสดงกรณีจริง
pmerino

@ zad0xsis - ฉันไม่เข้าใจกรณีที่แท้จริง หากคุณเพิ่มมุมมองที่สองโดยใช้addSubview:วิธีการ (ซึ่งอาจเป็นเช่นนั้นในครั้งแรก) ในครั้งต่อไปคุณจะไปถึงส่วนอื่นเนื่องจากมุมมองที่สองตอนนี้เป็นมุมมองย่อยของมุมมองแรก นี่ไม่ใช่สิ่งที่คุณพยายามทำเหรอ? คุณอาจกำลังมองหาสิ่งที่ผิดปกติอื่น ๆ เช่นการใส่ตัวควบคุมมุมมองไว้ล่วงหน้าหรือไม่?

ดีpopoverViewเป็นของ subview rootView (rootViewController) ฉันต้องการตรวจสอบว่ามันอยู่บนหน้าจอหรือไม่ (ถ้ามี rootView เป็น superview) และถ้าเป็นเช่นนั้นให้ลบออกหรือเพิ่มหากไม่ใช่
pmerino

กำลัง[self popoverView]ส่งคืนป๊อปโอเวอร์ที่สร้างขึ้นใหม่ทุกครั้งหรือไม่ จะไม่สามารถเพิ่มมุมมอง "ทับ" ได้หากเป็นมุมมองเดียวกันการเพิ่มมุมมองที่ไม่มีการดำเนินการ หากpopoverViewวิธีการสร้างใหม่ทุกครั้งก็จะไม่อยู่ในลำดับชั้นมุมมอง
เสมอ

1
การพิจารณาที่สำคัญอย่างหนึ่งที่ทำให้ฉันสะดุดที่นี่: เมื่อลบแล้วเพิ่มมุมมองย่อยที่คุณถือไว้ด้วยคุณสมบัติ IBOutlet (หรือ ivars) คุณต้องตรวจสอบให้แน่ใจว่าคุณสมบัติ (ivars) นั้นแข็งแกร่งหรือ (pre ARC) ที่ยังคงอยู่ . โดยค่าเริ่มต้นถ้าคุณ ctrl ลากจากมุมมองไปยังคอนโทรลเลอร์เพื่อสร้างเต้ารับมันจะสร้างมันออกมาอย่างอ่อนแอเนื่องจากถือว่ามุมมองที่สร้างขึ้นในปลายปากกาจะเป็นเจ้าของดังนั้นคุณจึงไม่จำเป็นต้องมีการอ้างอิงที่ชัดเจน แต่ถ้าคุณลบออกโดยทางโปรแกรมมันจะยกเลิกการจัดสรรการควบคุมและตั้งค่าการอ้างอิงของคุณเป็นศูนย์ (ใน ARC)
Rhubarb

18

ลองสิ่งนี้:

-(IBAction)showPopup:(id)sender
{
    if (!myView.superview)
        [self.view addSubview:myView];
    else
        [myView removeFromSuperview];
}

สุดยอด! บางครั้งก็ต้องการ myView.view.superview แต่มันใช้งานได้เหมือนเวทมนตร์สำหรับฉัน ขอบคุณ @MarkGranoff
Lior Frenkel

11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }

ไม่ได้ผลเพียงแค่เพิ่มมุมมองลงไป ฉันจะแก้ไขรหัสเพื่อแสดงกรณีจริง - zad0xsis 1 นาทีที่แล้วแก้ไข
pmerino

12
@pmerino ยินดีด้วยที่ขี้เกียจคัดลอก "zad0xsis 1 min ago edit" :-)
Thomas Kekeisen

ฉันคิดว่านี่แพงกว่าวิธีแก้ปัญหาอื่น ๆ เพราะต้องทำซ้ำในมุมมองย่อยทั้งหมด
SimplyKiwi

4

เทียบเท่า Swift จะมีลักษณะดังนี้:

if(!myView.isDescendantOfView(self.view)) {
    self.view.addSubview(myView)
} else {
    myView.removeFromSuperview()
}

2

ตรวจสอบยอดเยี่ยมของมุมมองย่อย ...

-(IBAction)showPopup:(id)sender {
    if([[self myView] superview] == self.view) { 
        [[self myView] removeFromSuperview];           
    } else {
        [self.view addSubview:[self myView]];         
    }
}

1

เงื่อนไข if ของคุณควรเป็นอย่างไร

if (!([rootView subviews] containsObject:[self popoverView])) { 
    [rootView addSubview:[self popoverView]];
} else {
    [[self popoverView] removeFromSuperview];

}

นี่เป็นการปรับเปลี่ยนคำตอบของ Michael Frederick เล็กน้อย มันให้ผลลัพธ์ที่แตกต่างจากรหัสของ Vincent ที่ใช้isDescendantOfView:หรือไม่?
paulmelnikow

มันให้ผลลัพธ์ที่แตกต่างกันอย่างแน่นอน สิ่งนี้จะตรวจสอบว่าเป็นมุมมองของเด็กไม่ใช่หลานหรือเหลน ฯลฯ
Sami Samhuri

0

ที่นี่เราใช้สองมุมมองที่แตกต่างกัน มุมมองหลักคือมุมมองที่เรากำลังค้นหามุมมองลูกหลานและตรวจสอบว่าเพิ่มในมุมมองหลักหรือไม่

if parentView.subviews.contains(descendantView) {
   // descendant view added to the parent view.
}else{
  // descendant view not added to the parent view.
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.