Viewcontroller похож на
Код: Выделить всё
import UIKit
struct Point {
let x: Double
let y: Double
let name: String
}
enum CoordinatePosition {
case top
case left
case bottom
case right
}
class SitesDetailsViewController: UIViewController {
@IBOutlet weak var mapImageView: UIImageView!
@IBOutlet weak var showHideMapButtonIcon: UIImageView!
@IBOutlet weak var showH
ideMapButtonLabel: UILabel!
@IBOutlet weak var showHideMapButtonView: UIView!
@IBOutlet weak var mapImageViewAspectRatio: NSLayoutConstraint!
@IBOutlet weak var sitesDetailsCollectionView: UICollectionView!
@IBOutlet weak var singleColumnButton: UIButton!
@IBOutlet weak var doubleColumnButton: UIButton!
@IBOutlet weak var tripleColumnButton: UIButton!
@IBOutlet weak var changeScaleStackView: UIStackView!
@IBOutlet weak var zoomScrollView: UIScrollView!
@IBOutlet weak var lblSitesName: UILabel!
@IBOutlet weak var changeScaleView: UIView!
@IBOutlet weak var increaseScaleButton: UIButton!
@IBOutlet weak var decreaseScaleButton: UIButton!
@IBOutlet weak var reloadButton: UIButton!
@IBOutlet weak var columnChangeView: UIView!
var selectedSite: Site?
var shouldShowMap = true
var imageSize: CGFloat = 15.0
override func viewDidLoad() {
super.viewDidLoad()
setCollectionLayout()
singleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
doubleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
tripleColumnButton.tintColor = UIColor(red: 0, green: 176, blue: 155, alpha: 1)
zoomScrollView.minimumZoomScale = 1.0
zoomScrollView.maximumZoomScale = 5.0
zoomScrollView.isUserInteractionEnabled = true
increaseScaleButton.setTitle("", for: .normal)
decreaseScaleButton.setTitle("", for: .normal)
reloadButton.setTitle("", for: .normal)
if Device.phone {
columnChangeView.isHidden = true
shouldShowMap = false
changeScaleView.isHidden = true
}
sitesDetailsCollectionView.register(JSSCameraCollectionHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: JSSCameraCollectionHeaderView.reuseIdentifier)
self.lblSitesName.text = selectedSite?.name
guard let getFloorID = selectedSitesID else { return }
self.getFloorsByID(getFloorID)
self.mapImageView.image = UIImage(named: "", in: Bundle(for: type(of: self)) , compatibleWith: nil)
}
func mapDesign() {
showHideMapViewTapped()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggleShowHideWithAnimation))
self.showHideMapButtonView.addGestureRecognizer(tapGesture)
}
@objc func toggleShowHideWithAnimation() {
showHideMapViewTapped(true)
}
func getFloorsByID(_ floorID: String) {
if !JSSCommonFunctions.NetworkState.isConnected() {
JSSCommonFunctions.sharedManager.noInternetShowAlert(self)
return
}
JSSProgressHUD.show(withStatus: "Loading...")
let getfloorbyID: JSSRequestFloorPlansByID = JSSRequestFloorPlansByID(floorID)
JSSWebAPIManager.performServiceRequest(getfloorbyID) { [weak self] result, error, errorCode in
guard let weakSelf = self else { return }
if (error != nil) {
if let err : NSError = error as NSError? {
var errorMessage : String = err.localizedDescription
if let userInfo : [String : Any] = err.userInfo as? [String : Any] {
if let errMSG : String = userInfo["message"] as? String {
errorMessage = errMSG
}
JSSCameraManager.sharedManager.writeLogFromFramework("getGroupList error: \(errorMessage)", #function)
}
//JSSCommonFunctions.sharedManager.showAlertWithError(self!, errorMessage)
JSSCameraManager.sharedManager.showAlertWithError(weakSelf, MessageUtil.ALERT_MESSGAE_FAILED_TO_PERFORM)
}
JSSProgressHUD.dismiss()
} else {
JSSProgressHUD.dismiss()
if let resultDict = result as? [String: Any],
let resultFinalDict = resultDict[MessageUtil.API_KEY_API_RESULT] as? [String: Any] {
let site = Site(dict: resultFinalDict)
weakSelf.selectedSite = site
print("selected Sites \(weakSelf.selectedSite)")
weakSelf.mapDesign()
weakSelf.filterCameraFromSitesList(weakSelf.selectedSite)
weakSelf.fetchMapImage()
}
DispatchQueue.main.async {
weakSelf.sitesDetailsCollectionView.reloadData()
}
}
}
}
func fetchMapImage() {
changeScaleView.isHidden = true
guard let getImage = selectedSite?.image?.thumbnailOriginal?.url else {
return
}
if let getImageURL = URL(string: getImage) {
JSSProgressHUD.show()
mapImageView.kf.setImage(with: getImageURL, placeholder: nil, options: nil, completionHandler: { [weak self] result in
JSSProgressHUD.dismiss()
switch result {
case .success(let resultImage):
self?.mapImageView.image = resultImage.image
self?.showHideMapButtonView.isHidden = false
if Device.pad {
self?.changeScaleView.isHidden = false
self?.addCooridnatesView()
}
case .failure(let error):
self?.reloadButton.isHidden = false
print("error in map = \(error.localizedDescription)")
}
})
}
}
func addCooridnatesView() {
mapImageView.subviews.forEach { $0.removeFromSuperview() }
guard let getObjects = selectedSite?.objects else { return }
var count = 0
let allCameras = JSSCameraManager.sharedManager.cameras
for singlePoint in getObjects {
print(singlePoint)
count = count + 1
let x = singlePoint.position?.x ?? 0
let y = singlePoint.position?.y ?? 0
let imageHeight = mapImageView.bounds.size.height
let imageWidth = mapImageView.bounds.size.width
for camera in allCameras {
if let id = singlePoint.id,
let cameraAttribute = camera.getAttributeFromId(id),
let name = cameraAttribute.name {
let cameraID = singlePoint.id ?? ""
let rotation = singlePoint.data?.rotation as? Int ?? 0
let viewAngle = singlePoint.data?.viewAngle as? Int ?? 0
let xInt = x / 100
let finalX = xInt * imageWidth
let yInt = y / 100
let finalY = yInt * imageHeight
let imageHeight:Int = 25
let imageWidth:Int = 25
print(zoomScrollView.zoomScale)
if zoomScrollView.zoomScale >= 3.0 {
let referencePoint = CGPoint(x: self.mapImageView.frame.midX, y: self.view.frame.midY)
let coordinate = CGPoint(x: finalX, y: finalY)
let position = getCoordinatePosition(coordinate: coordinate, referencePoint: referencePoint)
switch position {
case .top:
print("===Coordinate is in the top quadrant")
let imageX = Int(finalX) - (imageHeight / 2)
let imageY = Int(finalY) - (imageHeight / 2)
let labelX = Int(finalX) - imageHeight
let labelY = imageY + 15
addToolTip(cameraId: cameraID, imageX: imageX, imageY: imageY, imageName: "ArrowUpMap", labelX: labelX, labelY: labelY, labelText: name)
case .left:
print("===Coordinate is in the left quadrant")
let imageX = Int(finalX) - (imageHeight / 2)
let imageY = Int(finalY) - (imageHeight / 2)
var labelX = Int(finalX) - imageHeight
labelX += imageWidth + 4
let labelY = imageY - 2
addToolTip(cameraId: cameraID, imageX: imageX, imageY: imageY, imageName: "ArrowLeftMap", labelX: labelX, labelY: labelY, labelText: name)
case .right:
print("===Coordinate is in the right quadrant")
let imageX = Int(finalX) - (imageHeight / 2)
let imageY = Int(finalY) - (imageHeight / 2)
var labelX = Int(finalX) - imageHeight
let labelY = imageY - 2
let font = UIFont.systemFont(ofSize: 17)
let size = (name as NSString).size(withAttributes: [NSAttributedString.Key.font: font])
labelX = labelX - Int(size.width) + 21
addToolTip(cameraId: cameraID, imageX: imageX, imageY: imageY, imageName: "ArrowRightMap", labelX: labelX, labelY: labelY, labelText: name)
default:
print("===Coordinate is in the bottom quadrant")
let imageX = Int(finalX) - (imageHeight / 2)
let imageY = Int(finalY) - (imageHeight / 2)
let labelX = Int(finalX) - imageHeight
let labelY = Int(finalY) - imageHeight - 8
addToolTip(cameraId: cameraID, imageX: imageX, imageY: imageY, imageName: "ArrowDownMap", labelX: labelX, labelY: labelY, labelText: name)
}
} else {
print("Camera Id = \(cameraID), Point = \(CGPoint(x: finalX, y: finalY))")
addCameraImage(cameraName: name, cameraId: cameraID, point: CGPoint(x: finalX, y: finalY), rotation: rotation, viewAngle: viewAngle)
}
}
}
}
}
func addCameraImage(cameraName: String, cameraId: String, point: CGPoint, rotation: Int, viewAngle: Int) {
mapImageView.isUserInteractionEnabled = true
var imageSize: CGFloat = 15.0
if Device.pad {
imageSize = 25.0
}
let imageView = UIImageView(frame: CGRect(x: point.x - imageSize / 2, y: point.y - imageSize / 2, width: imageSize, height: imageSize))
imageView.image = UIImage(named: "Camera", in: Bundle(for: type(of: self)) , compatibleWith: nil)
imageView.contentMode = .scaleAspectFit
let rotationAngle = CGFloat(rotation) * .pi / 180
imageView.transform = CGAffineTransform(rotationAngle: rotationAngle)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(cameraImageTapped(_:)))
tapGesture.cameraID = cameraId
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapGesture)
self.mapImageView.addSubview(imageView)
}
func addToolTip(cameraId: String, imageX:Int, imageY: Int, imageName: String, labelX: Int, labelY: Int, labelText: String) {
let label = UILabel(frame: CGRect(x: labelX, y: labelY, width: 100, height: 30))
label.text = labelText
label.textAlignment = .center
label.textColor = UIColor(red: 0.079, green: 0.079, blue: 0.079, alpha: 1)
label.layer.cornerRadius = 5
label.clipsToBounds = true
let labelSize = label.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: 30))
label.frame.size.width = labelSize.width// + 30
label.font = UIFont(name: "JioType-Medium", size: 12)
label.layer.borderWidth = 1
label.layer.borderColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
label.backgroundColor = .clear
mapImageView.addSubview(label)
var imageSize: CGFloat = 10.0
if Device.pad {
imageSize = 25.0
}
let imageView = UIImageView(frame: CGRect(x: CGFloat(imageX), y: CGFloat(imageY), width: imageSize, height: imageSize))
imageView.image = UIImage(named: imageName, in: Bundle(for: type(of: self)) , compatibleWith: nil)
imageView.contentMode = .scaleAspectFit
mapImageView.addSubview(imageView)
let tapGestureLabel = UITapGestureRecognizer(target: self, action: #selector(cameraImageTapped(_:)))
tapGestureLabel.cameraID = cameraId
label.addGestureRecognizer(tapGestureLabel)
let tapGestureIcon = UITapGestureRecognizer(target: self, action: #selector(cameraImageTapped(_:)))
tapGestureIcon.cameraID = cameraId
imageView.addGestureRecognizer(tapGestureIcon)
label.isUserInteractionEnabled = true
imageView.isUserInteractionEnabled = true
self.mapImageView.isUserInteractionEnabled = true
}
func getCoordinatePosition(coordinate: CGPoint, referencePoint: CGPoint) -> CoordinatePosition {
if coordinate.x < referencePoint.x && coordinate.y < referencePoint.y {
return .top
} else if coordinate.x < referencePoint.x && coordinate.y > referencePoint.y {
return .left
} else if coordinate.x > referencePoint.x && coordinate.y > referencePoint.y {
return .bottom
} else {
return .right
}
}
@objc func cameraImageTapped(_ sender: UITapGestureRecognizer) {
if let cameraId = sender.cameraID {
if let cameraDict = setSelectedCameraDetails(cameraID: cameraId) {
let dict = [MessageUtil.API_KEY_API_RESULT:cameraDict as Any,MessageUtil.API_KEY_API_SUCCESS:true] as [String : Any]
let jsonData = try? JSONSerialization.data(withJSONObject: dict as Any, options: [])
let camDetails = try? JSONDecoder().decode(CameraDetails.self, from: jsonData!)
JSSCameraManager.sharedManager.selectedCameraDetails = camDetails
JSSCameraManager.sharedManager.stopOtherAudios()
DispatchQueue.main.async {
let bundle = Bundle.init(for: LiveAndArchiveVideoVC.self)
let storyboard : UIStoryboard = UIStoryboard(name: "LiveAndArchive", bundle: bundle)
let liveVC = storyboard.instantiateViewController(withIdentifier: "LiveAndArchiveVideoVC") as! LiveAndArchiveVideoVC
self.navigationController?.pushViewController(liveVC, animated: true)
}
}
}
}
@IBAction func reloadClicked() {
reloadButton.isHidden = true
fetchMapImage()
}
@IBAction func increaseScaleTapped(_ sender: Any) {
zoomScrollView.isUserInteractionEnabled = true
zoomScrollView.zoomScale = zoomScrollView.zoomScale + 0.5
print("Scale === \(zoomScrollView.zoomScale)")
self.addCooridnatesView()
}
@IBAction func decreaseScaleTapped(_ sender: Any) {
zoomScrollView.isUserInteractionEnabled = true
zoomScrollView.zoomScale = zoomScrollView.zoomScale - 0.5
print("Scale === \(zoomScrollView.zoomScale)")
self.addCooridnatesView()
}
@IBAction func singleColumnButtonPressed(_ sender: Any) {
singleColumnButton.tintColor = UIColor(red: 0, green: 176, blue: 155, alpha: 1)
doubleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
tripleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
self.numberOfColumnsInCollectionView = 1
reloadCollectionView()
}
@IBAction func doubleColumnButtonPressed(_ sender: Any) {
singleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
doubleColumnButton.tintColor = UIColor(red: 0, green: 176, blue: 155, alpha: 1)
tripleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
self.numberOfColumnsInCollectionView = 2
reloadCollectionView()
}
@IBAction func tripleleColumnButtonPressed(_ sender: Any) {
singleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
doubleColumnButton.tintColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.65)
tripleColumnButton.tintColor = UIColor(red: 0, green: 176, blue: 155, alpha: 1)
self.numberOfColumnsInCollectionView = 3
reloadCollectionView()
}
func reloadCollectionView() {
UIView.transition(with: self.sitesDetailsCollectionView,
duration: 0.7,
options: .transitionCrossDissolve,
animations: {
self.sitesDetailsCollectionView.reloadData()
},completion: nil)
}
func getAspectRatio() -> CGFloat {
var aspectRatio = selectedSite?.image?.thumbnailOriginal?.resolution?.aspectRatio ?? 1.0
var height = ScreenSize.SCREEN_WIDTH/aspectRatio
let heightRatio = height/ScreenSize.SCREEN_HEIGHT
if heightRatio > 0.7 {
height = 0.7 * ScreenSize.SCREEN_HEIGHT
aspectRatio = ScreenSize.SCREEN_WIDTH/height
mapImageView.contentMode = .scaleAspectFit
}
return aspectRatio
}
@objc func showHideMapViewTapped(_ shouldAnimate : Bool = false) {
if shouldShowMap {
self.showHideMapButtonIcon.image = UIImage(named: "hide_map_image", in: Bundle(for: type(of: self)) , compatibleWith: nil)
self.showHideMapButtonLabel.text = "Hide Map"
changeScaleView.isHidden = false
zoomScrollView.isScrollEnabled = true
mapImageViewAspectRatio = mapImageViewAspectRatio.setMultiplier(multiplier: getAspectRatio())
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.addCooridnatesView()
}
} else {
self.showHideMapButtonIcon.image = UIImage(named: "show_map_image", in: Bundle(for: type(of: self)) , compatibleWith: nil)
self.showHideMapButtonLabel.text = "Show Map"
changeScaleView.isHidden = true
zoomScrollView.zoomScale = 1.0
let aspectRatio = UIScreen.main.bounds.width/80.0
mapImageView.contentMode = .scaleAspectFill
mapImageViewAspectRatio = mapImageViewAspectRatio.setMultiplier(multiplier: aspectRatio)
}
shouldShowMap = !shouldShowMap
if shouldAnimate {
UIView.animate(withDuration: 0.4, animations: {
self.view.layoutIfNeeded()
})
}
}
/// Set the selected camera details object in JSSCameraManager.sharedManager.selectedCameraDetails to be used for further reference.
/// - Parameter selectedIndexPath: Indexpath of selected camera
func setSelectedCameraDetails(selectedIndexPath : IndexPath) -> Any? {
guard let getCameraIDs = selectedSite?.objects.map({ $0.id }) else {
return nil
}
let (camera, attribute, attributeIndex) = selectedCamerasWihAttribute[selectedIndexPath.row]
let cameraID = getCameraIDs[selectedIndexPath.row]
let allCameras = JSSCameraManager.sharedManager.cameras
guard let cameraDictionaries = JSSCameraManager.sharedManager.parsedCamList else { return nil }
if let cameraIndex = allCameras.firstIndex(where: {
let cameraAttributeIds = $0.cameraAttributes.map { $0.id }
if cameraAttributeIds.contains(cameraID) {
return true
}
return false
}) {
let cameraDictionary = cameraDictionaries[cameraIndex] as? [String: Any]
let camerasDictionaryies = cameraDictionary?[MessageUtil.API_KEY_CAMERAS] as? [Any]
return camerasDictionaryies?[attributeIndex]
}
return nil
}
func setSelectedCameraDetails(cameraID : String) -> Any? {
let allCameras = JSSCameraManager.sharedManager.cameras
guard let cameraDictionaries = JSSCameraManager.sharedManager.parsedCamList else { return nil }
if let cameraIndex = allCameras.firstIndex(where: {
let cameraAttributeIds = $0.cameraAttributes.map { $0.id }
if cameraAttributeIds.contains(cameraID) {
return true
}
return false
}) {
let cameraDictionary = cameraDictionaries[cameraIndex] as? [String: Any]
let camerasDictionaryies = cameraDictionary?[MessageUtil.API_KEY_CAMERAS] as? [Any]
return camerasDictionaryies?[0]
}
return nil
}
func filterCameraFromSitesList(_ site: Site?) {
guard let cameraIds = site?.objects.map({
return $0.id
}) else { return }
selectedCamerasWihAttribute.removeAll()
for cameraId in cameraIds {
let allCameras = JSSCameraManager.sharedManager.cameras
if let cameraIndex = allCameras.firstIndex(where: {
let cameraAttributeIds = $0.cameraAttributes.map { $0.id }
if cameraAttributeIds.contains(cameraId) {
return true
}
return false
}) {
let selectedCamera = allCameras[cameraIndex]
let cameraAttributeIds = selectedCamera.cameraAttributes.map { $0.id }
if let cameraAttributeIndex = cameraAttributeIds.firstIndex(of: cameraId),
cameraAttributeIndex < selectedCamera.cameraAttributes.count {
let selectedAttribute = selectedCamera.cameraAttributes[cameraAttributeIndex]
selectedCamerasWihAttribute.append((selectedCamera, selectedAttribute, cameraAttributeIndex))
}
}
}
sitesDetailsCollectionView.reloadData()
}
@IBAction func menuBtnPressed(_ sender: UIButton) {
self.navigationController?.popViewController(animated: true)
}
}
extension UIImageView {
func imageFrame() -> CGRect? {
guard let image = self.image else {
return nil
}
let imageViewSize = self.frame.size
guard let imageSize = image.size as? CGSize else {
return nil
}
let imageRatio = imageSize.width / imageSize.height
let viewRatio = imageViewSize.width / imageViewSize.height
if imageRatio < viewRatio {
let scale = imageViewSize.height / imageSize.height
let width = scale * imageSize.width
let topLeftX = (imageViewSize.width - width) * 0.5
return CGRect(x: topLeftX, y: 0, width: width, height: imageViewSize.height)
} else {
let scale = imageViewSize.width / imageSize.width
let height = scale * imageSize.height
let topLeftY = (imageViewSize.height - height) * 0.5
return CGRect(x: 0, y: topLeftY, width: imageViewSize.width, height: height)
}
}
}
//MARK: - scroll view delegate
extension SitesDetailsViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return mapImageView
}
}
extension String {
func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
return ceil(boundingBox.width)
}
}
extension UITapGestureRecognizer {
private static var cameraIDKey: UInt8 = 0
var cameraID: String? {
get {
return objc_getAssociatedObject(self, &UITapGestureRecognizer.cameraIDKey) as? String
}
set {
objc_setAssociatedObject(self, &UITapGestureRecognizer.cameraIDKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
Если увеличить изображение до 1,5 X, то My TapGesture работает нормально и вызывается cameraImageTapped(_ sender: UITapGestureRecouncer). Если пользователь увеличивает изображение более чем в 1,5 раза, то cameraImageTapped(_ sender: UITapGestureRecouncer) не вызывает. Почему? Пожалуйста, помогите мне это исправить.
Подробнее здесь: https://stackoverflow.com/questions/784 ... e-1-5x-why
Мобильная версия