ios 从视图层次结构中删除子视图并取消它的正确方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1516294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:29:40  来源:igfitidea点击:

What is the correct way to remove a subview from a view hierarchy and nuke it?

ioscocoa-touchuiviewsubview

提问by dugla

I have a parent UIView with a number of subviews. Periodically I need to remove a subview and completely remove it from the system. What is the correct way to do this? I tried this:

我有一个带有许多子视图的父 UIView。我需要定期删除子视图并将其从系统中完全删除。这样做的正确方法是什么?我试过这个:

UIView *v = [self.containerView viewWithTag:[n integerValue]];

[v removeFromSuperview];

and got a bizarre result. Previously present UIViews disappeared as well. What's going on?

并得到了一个奇怪的结果。之前存在的UIViews 也消失了。这是怎么回事?

回答by mahboudz

Try this:

尝试这个:

UIView *v = [self.containerView viewWithTag:[n integerValue]];
v.hidden = YES;
[self.containerView bringSubviewToFront:v];
[v removeFromSuperview];

Another thing I just noticed from the UIView class document - see the last sentence:

我刚刚从 UIView 类文档中注意到的另一件事——见最后一句:

removeFromSuperview Unlinks the receiver from its superview and its window, and removes it from the responder chain.

removeFromSuperview 取消接收者与其父视图及其窗口的链接,并将其从响应者链中移除。

  • (void)removeFromSuperview
  • (void)removeFromSuperview

Discussion If the receiver's superview is not nil, this method releases the receiver. If you plan to reuse the view, be sure to retain it before calling this method and be sure to release it as appropriate when you are done with it or after adding it to another view hierarchy.

讨论 如果接收者的superview 不为nil,则该方法释放接收者。如果您打算重用该视图,请确保在调用此方法之前保留它,并确保在完成它或将其添加到另一个视图层次结构后适当地释放它。

Never invoke this method while displaying.

显示时切勿调用此方法。

UPDATE: It is now 2014 and removing a subview without hiding it works perfectly fine. The original poster's code should work as-is:

更新:现在是 2014 年,删除子视图而不隐藏它工作得很好。原始海报的代码应按原样工作:

UIView *v = [self.containerView viewWithTag:[n integerValue]];
[v removeFromSuperview];

This will remove v and any views it has attached to it as subviews, leaving behind containerView and any siblings of v.

这将删除 v 和它作为子视图附加到它的任何视图,留下 containerView 和 v 的任何兄弟。

回答by iKushal

To remove all subviews from your view:

要从您的视图中删除所有子视图:

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

If you want to remove some specific view only then:

如果您只想删除某些特定视图,则:

for(UIView *subview in [view subviews]) {
  if([subview isKindOfClass:[UIButton class]]) {
     [subview removeFromSuperview];
 } else {
     // Do nothing - not a UIButton or subclass instance
 }
}

You can also delete sub views by tag value:

您还可以通过标签值删除子视图:

for(UIView *subview in [view subviews]) {
    if(subview.tag==/*your subview tag value here*/) {
        [subview removeFromSuperview];

    } else {
        // Do nothing - not a UIButton or subclass instance
    }
}

回答by Alexey

Swift 3.0:

斯威夫特 3.0:

let viewToRemove = mySuperView.viewWithTag(myTag)
viewToRemove?.removeFromSuperview()

回答by JonJ

Swift 4: extend UIView

Swift 4:扩展 UIView

extension UIView {
    public func removeAllSubviews() {
        for subview in self.subviews {
            subview.removeFromSuperview()
        }
    }
}

or

或者

extension UIView {
    public func removeAllSubviews() {
        self.subviews.forEach { 
    override func viewWillAppear(_ animated: Bool)
    {
        super.viewWillAppear(animated)

        if let topController = UIApplication.topViewController() {

            if topController.isKind(of: ProviderHome.self)
            {
                let arrOfSuview = self.view.subviews

                if arrOfSuview.count > 1
                {
                    print("Davender Arr of subviews : \(arrOfSuview)")

                    for i in 0..<arrOfSuview.count
                    {
                        let objSub = arrOfSuview[i]

                        if objSub.tag == 101
                        {
                          objSub.removeFromSuperview()
                        }

                    }



                }


                NotificationCenter.default.addObserver(self, selector: #selector(ProviderHome.handelPushNotification), name: NSNotification.Name(rawValue: "handelPush"), object: nil)

                NotificationCenter.default.addObserver(self, selector: #selector(ProviderHome.handelLocalNotification), name: NSNotification.Name(rawValue: "handelLocal"), object: nil)
            }
        }


    }

@objc func handelPushNotification(_ notification: NSNotification)  {


        let arrOfSuview = self.view.subviews

        if arrOfSuview.count > 1
        {
            print("Davender Arr of subviews : \(arrOfSuview)")

            for i in 0..<arrOfSuview.count
            {
                let objSub = arrOfSuview[i]

                if objSub.tag == 101
                {
                    objSub.removeFromSuperview()
                }

            }

        }

        if notification.userInfo != nil
        {


            let dict = notification.userInfo as! Dictionary<String, Any>

            let d = dict["data"] as! Dictionary<String, Any>

            let action = d["gcm.notification.label"] as! String

            print("current message id :- ", action)

            self.getNotificationId = action

            if getNotificationId != ""
            {
               //call the api for getting Data

                AppDelegate.sharedInstance().myCurrentnotificationId = getNotificationId

                //working code
                let storyboard = UIStoryboard(name: "Provider", bundle: nil)
                let vc = storyboard.instantiateViewController(withIdentifier: "CommonPopUpsVC") as! CommonPopUpsVC
                vc.modalPresentationStyle = .overFullScreen
                vc.view.frame = self.view.frame
                vc.view.tag = 101
                self.view.addSubview(vc.view)
                self.present(vc, animated: true, completion: nil)

            }


       }
    }
.removeFromSuperview() } } }

回答by Davender Verma

##代码##

回答by sujal

That's the right general idea. those other UIViews that disappear, what's their relationship to this UIView? Are they subviews of this view? Are they dealloc'd in the dealloc method of the view you're removing?

这是正确的总体思路。那些消失的其他 UIView,它们与这个 UIView 有什么关系?它们是这个视图的子视图吗?它们是否在您要删除的视图的 dealloc 方法中解除分配?

Are you sure your Tags are unique?

您确定您的标签是独一无二的吗?

Sujal

苏加尔

回答by NSResponder

Are they just disappearing from the display, or disappearing from the display andthe view hierarchy? What does the debugger show you?

它们只是从显示中消失,还是从显示视图层次结构中消失?调试器向您展示了什么?

回答by Kevlar

Is it possible that cell.contentView has the same tag as the subview you want to remove? according to the documentationviewWithTag removes:

cell.contentView 是否有可能与您要删除的子视图具有相同的标签?根据文档viewWithTag 删除:

The view in the receiver's hierarchy that matches tag. The receiver is included in the search.

接收者层次结构中与标签匹配的视图。接收器包含在搜索中。

If this is the case then you may be inadvertently removing cell.contentView from the cell. If n is zero and your cell's contentview has no tag set to it, it would default to 0 and cause that to happen.

如果是这种情况,那么您可能会无意中从单元格中删除 cell.contentView。如果 n 为零并且您的单元格的 contentview 没有为其设置标签,它将默认为 0 并导致这种情况发生。