簡體   English   中英

“removeFromSuperview”永遠不會在 UIApplication 上工作?

[英]"removeFromSuperview" NEVER work on UIApplication?

如何刪除子視圖?

我試圖通過以編程方式創建UIViewUIImageView來集成 GIF。

顯示 GIF 效果很好,但是調用隱藏 if 功能時,沒有響應。

下面是兩個函數的代碼。

class CustomLoader: UIView {

    static let instance = CustomLoader()

    var viewColor: UIColor = .black
    var setAlpha: CGFloat = 0.5
    var gifName: String = ""

    lazy var transparentView: UIView = {
        let transparentView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
        transparentView.backgroundColor = viewColor.withAlphaComponent(setAlpha)
        transparentView.isUserInteractionEnabled = false
        return transparentView
    }()

    lazy var gifImage: UIImageView = {
        var gifImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 60))
        gifImage.contentMode = .scaleAspectFit
        gifImage.center = transparentView.center
        gifImage.isUserInteractionEnabled = false
        gifImage.loadGif(name: gifName)
        return gifImage
    }()

    func showLoaderView() {
        self.addSubview(self.transparentView)
        self.transparentView.addSubview(self.gifImage)
        self.transparentView.bringSubview(toFront: self.gifImage)
        UIApplication.shared.keyWindow?.addSubview(transparentView)

    }

    func hideLoaderView() {
        self.transparentView.removeFromSuperview()
    }

}

一些想法:

  1. 我建議您在hideLoaderView添加斷點或日志語句,並確保您到達該行。

  2. 您應該將此類的init方法設為private ,以確保您不會在某個單獨的實例上調用hideLoaderView 在處理單例時,您要確保不會意外創建另一個實例。

但是我測試了你的代碼,它工作正常。 您的問題可能在於您在何處以及如何調用它(並將init設為private ,您可能會發現在何處不恰當地使用它)。

在下面的評論中,你說:

我只是簡單地調用函數“CustomLoader().hideLoaderView()” 兩者都在技術上被調用。 “我使用不當的地方”是什么意思?

這就是問題的根源。

CustomLoader().hideLoaderView() CustomLoader()CustomLoader().hideLoaderView()將創建一個CustomLoader的新實例,並帶有自己的transparencyView CustomLoader().hideLoaderView()等,這正是問題所在。 您並沒有隱藏之前顯示的舊視圖,而是試圖隱藏您剛剛創建但從未顯示過的另一個視圖。

如果您改為使用該static ,例如CustomLoader.instance.showLoaderView()CustomLoader.instance.hideLoaderView() ,那么問題就會消失。 然后,您將隱藏之前顯示的相同視圖。


順便說一下,其他一些不相關的觀察:

  1. 如果這是一個單例或共享實例,則約定將調用該static屬性shared ,而不是instance

  2. 順便說一句,您沒有將此CustomLoader用作UIView ,因此我不會將其設為UIView子類。 不要讓它成為任何東西的子類。

    顯然,您也會消除那條self.addSubview(transparentView)行。

  3. bringSubview(toFront:)調用是不必要的。

  4. 你應該避免引用UIScreen.main.bounds 你不知道你的應用程序是否可能處於多任務模式(也許現在這不是問題,但這是一種不必要的假設,會在以后導致問題)。 只需參考您將其添加到的UIWindowbounds即可。 您還應該在顯示此視圖時更新此frame ,而不是在創建它時(以防您在此期間更改了方向,或其他任何情況)。

    順便說一句,在 iOS 13 及更高版本中不鼓勵使用keyWindow ,因此您可能最終也想刪除它。

  5. 添加gifImage (我建議將其重命名為gifImageView因為它是圖像視圖,而不是圖像),您不應引用其超級視圖的center 這是透明視圖在其超級視圖坐標系中的坐標,它可能與透明視圖自身的坐標系完全不同。 在這種情況下,它恰好可以工作,但它暗示了對視圖坐標系的根本誤解。 引用transparentViewbounds ,而不是它的center

  6. 如果您要公開viewColorsetAlpha ,則至少應該將transparentView的顏色設置從lazy初始值設定項中提取到showLoaderView 現在,如果您顯示加載程序一次,然后更改顏色,並嘗試再次顯示它,您將看不到新顏色。

  7. 同樣的問題也適用於 gif 圖像。 所以,我didSetdidSet觀察者。

因此,將所有這些放在一起:

class CustomLoader{
    static let shared = CustomLoader()

    private init() { }

    var dimmingColor: UIColor = .black
    var dimmingAlpha: CGFloat = 0.5

    var gifName: String = "" { didSet { gifImage.loadGif(name: gifName) } }

    lazy var transparentView: UIView = {
        let transparentView = UIView()
        transparentView.isUserInteractionEnabled = false
        return transparentView
    }()

    lazy var gifImageView: UIImageView = {
        var gifImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 60))
        gifImage.contentMode = .scaleAspectFit
        gifImage.isUserInteractionEnabled = false
        return gifImage
    }()

    func showLoaderView() {
        guard let window = UIApplication.shared.keyWindow else { return }
        transparentView.frame = window.bounds
        transparentView.backgroundColor = dimmingColor.withAlphaComponent(dimmingAlpha)
        gifImageView.center = CGPoint(x: transparentView.bounds.midX, y: transparentView.bounds.midY)
        transparentView.addSubview(gifImageView)
        window.addSubview(transparentView)
    }

    func hideLoaderView() {
        transparentView.removeFromSuperview()
    }
}

為什么在擁有 CustomLoader 實例視圖時使用透明視圖

嘗試使用這個

class CustomLoader: UIView {

    static let instance = CustomLoader()

    var viewColor: UIColor = .black
    var setAlpha: CGFloat = 0.5
    var gifName: String = ""

    init() {
        super.init(frame: UIScreen.main.bounds)
        backgroundColor = viewColor.withAlphaComponent(setAlpha)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    lazy var gifImage: UIImageView = {
        var gifImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 60))
        gifImage.backgroundColor = .red
        gifImage.contentMode = .scaleAspectFit
        gifImage.center = center
        gifImage.isUserInteractionEnabled = false
        gifImage.loadGif(name: gifName)
        return gifImage
    }()

    func showLoaderView() {
        addSubview(self.gifImage)
        UIApplication.shared.keyWindow?.addSubview(self)

    }
    func hideLoaderView() {
        removeFromSuperview()
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM