170 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Swift
		
	
	
		
		
			
		
	
	
			170 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Swift
		
	
	
|  | // | ||
|  | //  GuruBannerCoordinator.swift | ||
|  | //  Pods | ||
|  | // | ||
|  | //  Created by 250102 on 2025/5/9. | ||
|  | // | ||
|  | 
 | ||
|  | protocol GuruBannerView { | ||
|  |      | ||
|  |     func view() -> UIView | ||
|  |     func setPlacementName(placement: String) | ||
|  |     func onShow(); | ||
|  |     func onHide(); | ||
|  | } | ||
|  | 
 | ||
|  | class GuruBannerCoordinator<T: GuruBannerView> { | ||
|  |      | ||
|  |     private let viewController: UIViewController | ||
|  |     public private(set) var bannerAd: T | ||
|  |     private var bannerPosition: BannerPosition { return lastShowRequest?.position ?? BannerPosition.bottom } | ||
|  |     private var bannerOffset: CGFloat { return CGFloat(lastShowRequest?.offset ?? 0.0) } | ||
|  |     private var lastShowRequest: BannerShowRequest? = nil | ||
|  | 
 | ||
|  |     public private(set) var orientation: ScreenOrientation = .portrait | ||
|  |          | ||
|  |     public init(viewController: UIViewController, bannerAd: T, contentId: Int) { | ||
|  |         self.viewController = viewController | ||
|  |         self.bannerAd = bannerAd | ||
|  |     } | ||
|  |      | ||
|  |     public func logInfo(_ message: String) { | ||
|  |         Logger.i(tag: "GuruBannerCoordinator", message: "\(message)") | ||
|  |     } | ||
|  |     public func logWarn(_ message: String) { | ||
|  |         Logger.w(tag: "GuruBannerCoordinator", message: "\(message)") | ||
|  |     } | ||
|  |      | ||
|  |     public func show(_ request: BannerShowRequest? = nil) -> Bool { | ||
|  |         var shouldReattach = false | ||
|  |          | ||
|  |         // Check if position or offset has changed | ||
|  |         if let newOffset = request?.offset, newOffset != Float(bannerOffset) { | ||
|  |             shouldReattach = true | ||
|  |         } | ||
|  |          | ||
|  |         if let newPosition = request?.position, newPosition != bannerPosition { | ||
|  |             shouldReattach = true | ||
|  |         } | ||
|  |          | ||
|  |         lastShowRequest = request | ||
|  |          | ||
|  |         guard let container = viewController.viewIfLoaded else { | ||
|  |             logWarn("viewController.view is nil, returns false") | ||
|  |             return false | ||
|  |         } | ||
|  |         let bannerAdView = bannerAd.view() | ||
|  |          | ||
|  |         var attached = container.subviews.contains(bannerAdView) | ||
|  |          | ||
|  |         // If we already have a view and parameters changed, remove it | ||
|  |         if shouldReattach || !attached { | ||
|  |             logInfo("Parameters changed! Re-attaching view!") | ||
|  |             if(attached) { | ||
|  |                 bannerAdView.removeFromSuperview() | ||
|  |             } | ||
|  |             let isTablet = UIDevice.current.userInterfaceIdiom == .pad | ||
|  |             let bannerHeight: CGFloat = isTablet ? 90 : 50 | ||
|  |             let screenWidth = min(viewController.view.bounds.width, viewController.view.bounds.height) | ||
|  |              | ||
|  |             container.addSubview(bannerAdView) | ||
|  |             bannerAdView.translatesAutoresizingMaskIntoConstraints = false | ||
|  |              | ||
|  |              | ||
|  |             logInfo("BannerAd show!!! bannerSize: \(screenWidth)x\(bannerHeight)") | ||
|  |                          | ||
|  |             if let placement = lastShowRequest?.placement { | ||
|  |                 bannerAd.setPlacementName(placement: placement) | ||
|  |             } | ||
|  |             // Configure banner position and rotation | ||
|  |             var transform = CGAffineTransform.identity | ||
|  |             switch bannerPosition { | ||
|  |             case .start: | ||
|  |                 transform = CGAffineTransform(rotationAngle: .pi / 2) | ||
|  |                 NSLayoutConstraint.activate([ | ||
|  |                     bannerAdView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: bannerOffset), | ||
|  |                     bannerAdView.centerYAnchor.constraint(equalTo: container.centerYAnchor), | ||
|  |                     bannerAdView.widthAnchor.constraint(equalToConstant: screenWidth), | ||
|  |                     bannerAdView.heightAnchor.constraint(equalToConstant: bannerHeight) | ||
|  |                 ]) | ||
|  |                  | ||
|  |             case .end: | ||
|  |                 transform = CGAffineTransform(rotationAngle: -(.pi / 2)) | ||
|  |                 NSLayoutConstraint.activate([ | ||
|  |                     bannerAdView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -bannerOffset), | ||
|  |                     bannerAdView.centerYAnchor.constraint(equalTo: container.centerYAnchor), | ||
|  |                      | ||
|  |                     bannerAdView.widthAnchor.constraint(equalToConstant: screenWidth), | ||
|  |                     bannerAdView.heightAnchor.constraint(equalToConstant: bannerHeight) | ||
|  |                 ]) | ||
|  |                  | ||
|  |             case .top: | ||
|  |                 transform = CGAffineTransform(rotationAngle: 0) | ||
|  |                  | ||
|  |                 NSLayoutConstraint.activate([ | ||
|  |                     bannerAdView.centerXAnchor.constraint(equalTo: container.centerXAnchor), | ||
|  |                     bannerAdView.topAnchor.constraint(equalTo: container.safeAreaLayoutGuide.topAnchor, constant: bannerOffset), | ||
|  |                      | ||
|  |                     bannerAdView.heightAnchor.constraint(equalToConstant: bannerHeight), | ||
|  |                     bannerAdView.widthAnchor.constraint(equalToConstant: screenWidth), | ||
|  |                 ]) | ||
|  |                  | ||
|  |             default: | ||
|  |                 transform = CGAffineTransform(rotationAngle: 0) | ||
|  |                 NSLayoutConstraint.activate([ | ||
|  |                     bannerAdView.centerXAnchor.constraint(equalTo: container.centerXAnchor), | ||
|  |                     bannerAdView.bottomAnchor.constraint(equalTo: container.safeAreaLayoutGuide.bottomAnchor, constant: -bannerOffset), | ||
|  |                      | ||
|  |                     bannerAdView.heightAnchor.constraint(equalToConstant: bannerHeight), | ||
|  |                     bannerAdView.widthAnchor.constraint(equalToConstant: screenWidth) | ||
|  |                 ]) | ||
|  |             } | ||
|  |              | ||
|  |             bannerAdView.transform = transform | ||
|  |             bannerAdView.isHidden = false | ||
|  |             bannerAd.onShow() | ||
|  |         } else { | ||
|  |             bannerAd.view().isHidden = false | ||
|  |             bannerAd.onShow() | ||
|  |         } | ||
|  |          | ||
|  |         if let placement = request?.placement { | ||
|  |             bannerAd.setPlacementName(placement: placement) | ||
|  |         } | ||
|  |          | ||
|  |         return true | ||
|  |     } | ||
|  |      | ||
|  |     public func hide() -> Bool { | ||
|  |         guard let _ = viewController.view.superview?.contains(bannerAd.view()) else { | ||
|  |             return true | ||
|  |         } | ||
|  | 
 | ||
|  |         bannerAd.view().isHidden = true | ||
|  |         bannerAd.onHide() | ||
|  |          | ||
|  |         return true | ||
|  |     } | ||
|  |      | ||
|  |     public func destroy() -> Bool { | ||
|  |         bannerAd.view().removeFromSuperview() | ||
|  | 
 | ||
|  |         return true | ||
|  |     } | ||
|  |      | ||
|  |     public func updateOrientation(orientation: ScreenOrientation) -> Bool { | ||
|  |         if let _ = viewController.view.superview?.contains(bannerAd.view()), self.orientation != orientation { | ||
|  |             let isVisible = !bannerAd.view().isHidden | ||
|  |              | ||
|  |             bannerAd.onHide() | ||
|  |             bannerAd.view().isHidden = true | ||
|  |             if isVisible { | ||
|  |                 return show() | ||
|  |             } | ||
|  |         } | ||
|  |          | ||
|  |         self.orientation = orientation | ||
|  |         return true | ||
|  |     } | ||
|  | } |