ProgramingTip

iOS에서 긴 작업을 할 때 "오버레이"로드

bestdevel 2020. 12. 2. 21:39
반응형

iOS에서 긴 작업을 할 때 "오버레이"로드


긴 작업을 할 때 Swift IOS 애플리케이션에서 기계를로드하는 예는 무엇입니까? 원격 서버에서 데이터를로드하는 예입니다. 검색했지만 답변을 찾지 못했습니다.

업데이트 :

@Sebastian Dressler에게 감사드립니다. 이것은 간단한 방법입니다. 내 코드를 업데이트하면 멋지게 실행됩니다.

public class LoadingOverlay{

var overlayView = UIView()
var activityIndicator = UIActivityIndicatorView()

class var shared: LoadingOverlay {
    struct Static {
        static let instance: LoadingOverlay = LoadingOverlay()
    }
    return Static.instance
}

    public func showOverlay(view: UIView) {

        overlayView.frame = CGRectMake(0, 0, 80, 80)
        overlayView.center = view.center
        overlayView.backgroundColor = UIColor(hex: 0x444444, alpha: 0.7)
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10

        activityIndicator.frame = CGRectMake(0, 0, 40, 40)
        activityIndicator.activityIndicatorViewStyle = .WhiteLarge
        activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)

        overlayView.addSubview(activityIndicator)
        view.addSubview(overlayView)

        activityIndicator.startAnimating()
    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        overlayView.removeFromSuperview()
    }
}

사용하자 :

LoadingOverlay.shared.showOverlay(self.view)
//To to long tasks
LoadingOverlay.shared.hideOverlayView()

위의 답변은 로딩 뷰를 추가하지만 화면의 클릭 이벤트를 차단하지 않고 나머지 화면에 대한 장비도 제공하지 않습니다. 다음과 같이 달성 할 수 있습니다.

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .Alert)

alert.view.tintColor = UIColor.blackColor()
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.startAnimating();

alert.view.addSubview(loadingIndicator)
presentViewController(alert, animated: true, completion: nil)

스위프트 3.0

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();

alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)

Swift 4.0 이상

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();

alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)

다음과 같이 숨길 수 있습니다.

dismiss(animated: false, completion: nil)

다음과 같이 표시됩니다. 여기에 이미지 설명 입력


조립보기를 직접 만들어 부모보기에 추가하고 작업이 완료되면 제거합니다 (예 : 추가).

var overlay : UIView? // This should be a class variable

[ ... ]

overlay = UIView(frame: view.frame)
overlay!.backgroundColor = UIColor.blackColor()
overlay!.alpha = 0.8

view.addSubview(overlay!)

제거 :

overlay?.removeFromSuperview()

배경 흐림 + 활동 표시기, Swift 5 예제

extension UIView {
    func showBlurLoader() {
        let blurLoader = BlurLoader(frame: frame)
        self.addSubview(blurLoader)
    }

    func removeBluerLoader() {
        if let blurLoader = subviews.first(where: { $0 is BlurLoader }) {
            blurLoader.removeFromSuperview()
        }
    }
}


class BlurLoader: UIView {

    var blurEffectView: UIVisualEffectView?

    override init(frame: CGRect) {
        let blurEffect = UIBlurEffect(style: .dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = frame
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.blurEffectView = blurEffectView
        super.init(frame: frame)
        addSubview(blurEffectView)
        addLoader()
    }

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

    private func addLoader() {
        guard let blurEffectView = blurEffectView else { return }
        let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
        activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
        blurEffectView.contentView.addSubview(activityIndicator)
        activityIndicator.center = blurEffectView.contentView.center
        activityIndicator.startAnimating()
    }
}

도장


저처럼 늦은 사람을 위해 @Sonrobby 코드를 약간 수정했습니다. 내가 이해했듯이 @Sonrobby는 모든 showOverlay호출 의 기계에 활동을 추가합니다 . 그리고 일부 구성은 init 함수에 전달되어 showOverlay메서드 의 배치 만 허용 됩니다.

또한 내 앱이 대부분 흰색이기 때문에 기기의 배경을 검정색으로 변경합니다.

다음은 코드입니다.

public class LoadingOverlay{

    var overlayView : UIView!
    var activityIndicator : UIActivityIndicatorView!

    class var shared: LoadingOverlay {
        struct Static {
            static let instance: LoadingOverlay = LoadingOverlay()
        }
        return Static.instance
    }

    init(){
        self.overlayView = UIView()
        self.activityIndicator = UIActivityIndicatorView()

        overlayView.frame = CGRectMake(0, 0, 80, 80)
        overlayView.backgroundColor = UIColor(white: 0, alpha: 0.7)
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10
        overlayView.layer.zPosition = 1

        activityIndicator.frame = CGRectMake(0, 0, 40, 40)
        activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
        activityIndicator.activityIndicatorViewStyle = .WhiteLarge
        overlayView.addSubview(activityIndicator)
    }

    public func showOverlay(view: UIView) {
        overlayView.center = view.center
        view.addSubview(overlayView)
        activityIndicator.startAnimating()
    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        overlayView.removeFromSuperview()
    }
}


때때로 코드를 실행할 수 있습니다. 개인적으로 showOverlay가 제대로 호출되지 않는 경우가 있습니다. 씬에 들어 가려고했기 때문에 viewDidLoad 중에 즉시이 함수를 호출 때문입니다.

저와 강화 문제가 발생하면 코드에 대한 수정 사항과 제가 권장하는 접근 방식 변경이 있습니다.

FIX : 다음과 같이 dispatch_async 호출에 대한 클로저로 두 코드 블록을 배치합니다.

dispatch_async(dispatch_get_main_queue(),
 { //code });

접근 방식 : 코드를 호출 할 때 기본 큐에 dispatch_after 호출을 수행하여 호출을 몇 밀리 초만큼 지연 수정합니다.

추론? viewDidLoad 동안 UI에 너무 많은 작업을 요청하는 것입니다.

솔루션에 대한이 능력이 도움이됩니다.

-조엘 롱

XCode v6.3.2에서 작동하는 PS 솔루션


@sonrobby 답변 업데이트, 마스크 크기 조정을 완화 배경보기 및 방향 처리 추가 ...이 간단한 작업에 사용할 수 있습니다.

public class LoadingOverlay{

    var overlayView = UIView()
    var activityIndicator = UIActivityIndicatorView()
    var bgView = UIView()

    class var shared: LoadingOverlay {
        struct Static {
            static let instance: LoadingOverlay = LoadingOverlay()
        }
        return Static.instance
    }

    public func showOverlay(view: UIView) {

        bgView.frame = view.frame
        bgView.backgroundColor = UIColor.gray
        bgView.addSubview(overlayView)
        bgView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin,.flexibleHeight, .flexibleWidth]
        overlayView.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
        overlayView.center = view.center
        overlayView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin]
        overlayView.backgroundColor = UIColor.black
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10

        activityIndicator.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        activityIndicator.activityIndicatorViewStyle = .whiteLarge
        activityIndicator.center = CGPoint(x: overlayView.bounds.width / 2, y: overlayView.bounds.height / 2)

        overlayView.addSubview(activityIndicator)
        view.addSubview(bgView)
        self.activityIndicator.startAnimating()

    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        bgView.removeFromSuperview()
    }
}

keywindow에 추가하면 탐색 및 탭 표시 줄을 넘어갈 수 있습니다.

LoadingOverlay.shared.showOverlay(view: UIApplication.shared.keyWindow!)

ATKit을 사용하십시오.

참조 : https://aurvan.github.io/atkit-ios-release/index.html

ATProgressOverlay 클래스 https://aurvan.github.io/atkit-ios-release/helpbook/Classes/ATProgressOverlay.html

암호 :

import ATKit

ATProgressOverlay.sharedInstance.show() // Does not show network activity indicator on status bar.

ATProgressOverlay.sharedInstance.show(isNetworkActivity: true) // Shows network activity indicator on status bar.

스크린 샷 :

오버레이 스크린 샷로드


스위프트 3.

아래 답변에서 @Lucho의 코드를 사용하는 기계 배경색을 지우고 스피너 색상을 추가했습니다.

public class LoadingOverlay {

    var overlayView : UIView!
    var activityIndicator : UIActivityIndicatorView!

    class var shared: LoadingOverlay {
        struct Static {
            static let instance: LoadingOverlay = LoadingOverlay()
        }
        return Static.instance
    }

    init(){
        self.overlayView = UIView()
        self.activityIndicator = UIActivityIndicatorView()

        overlayView.frame = CGRect(0, 0, 80, 80)
        overlayView.backgroundColor = .clear
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10
        overlayView.layer.zPosition = 1

        activityIndicator.frame = CGRect(0, 0, 40, 40)
        activityIndicator.center = CGPoint(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
        activityIndicator.activityIndicatorViewStyle = .whiteLarge
        activityIndicator.color = .gray
        overlayView.addSubview(activityIndicator)
    }

    public func showOverlay(view: UIView) {
        overlayView.center = view.center
        view.addSubview(overlayView)
        activityIndicator.startAnimating()
    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        overlayView.removeFromSuperview()
    }
}

자신의 뷰 컨트롤러를 준비로 표시하기위한 프로토콜을 만들었습니다. 사용법은 매우 간단합니다.

class ViewController: UIViewController, OverlayHost {
    @IBAction func showOverlayButtonPressed() {
        showOverlay(type: YourOverlayViewController.self, 
            fromStoryboardWithName: "Main")
    }
}

결과 :

스위프트 OverlayViewController

소스 코드 : https://github.com/agordeev/OverlayViewController

관련 기사 : https://andreygordeev.com/2017/04/18/overlay-view-controller-protocols-swift/

참고 URL : https://stackoverflow.com/questions/27960556/loading-an-overlay-when-running-long-tasks-in-ios

반응형