admin管理员组

文章数量:1391928

In the screenshot if i copy the orignial first placed ojbect twice there are two other objects that are only displayed in the saved photo. So I place a circle copy the inal twice hit the copy button twice then in the saved photo there are 5 circles and there should only be 3.You can see in the photos below what is going on. The duplicated images are being saved in the positions of 1 in the first photo.

import UIKit
import CoreData

class First: UIViewController {
    var objects = [UIImageView]()
    var nextB = UIButton()
    var drawView = Canvas()

    var libaryB = UIButton()

    var ww = 80
    var saveB = UIButton()
    var circleB = UIButton()
    var copyb = UIButton()
    var txt = UITextField()
    var currentView: UIView?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        [saveB,circleB, libaryB,txt, drawView,copyb].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
            $0.layer.borderWidth = 1
            $0.backgroundColor = UIColor(
                red: .random(in: 0.5...0.7),
                green: .random(in: 0.0...1),
                blue: .random(in: 0.3...0.5),
                alpha: 1
            )
            $0.layer.borderWidth = 1

            if let textfield = $0 as? UITextField {
                textfield.textAlignment = .center
                textfield.inputAccessoryView = createToolbar()
            }

            if let label = $0 as? UILabel {
                label.textAlignment = .center
            }
            if let button = $0 as? UIButton {
                button.setTitleColor(.black, for: .normal)
            }
        }

        circleB.setTitle("Circle", for: .normal)
        libaryB.setTitle("Library", for: .normal)
        saveB.setTitle("Save", for: .normal)
        libaryB.addTarget(self, action: #selector(libraryBUttonFunction), for: .touchDown)
        // note that I changed some of the constraints to use the safeAreaLayoutGuide of the view
        // you wouldn't want your sliders to go out of the safe area, would you?
        NSLayoutConstraint.activate([
            txt.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            txt.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            txt.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            txt.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),

            drawView.topAnchor.constraint(equalTo: txt.bottomAnchor),
            drawView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            drawView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6),
            drawView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),

            circleB.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            circleB.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            circleB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            circleB.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/4),

            saveB.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            saveB.leadingAnchor.constraint(equalTo: circleB.trailingAnchor),
            saveB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            saveB.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/4),

            libaryB.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            libaryB.leadingAnchor.constraint(equalTo: saveB.trailingAnchor),
            libaryB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            libaryB.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/4),

            copyb.bottomAnchor.constraint(equalTo: circleB.topAnchor),
            copyb.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor, multiplier: 0.05),
            copyb.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor, multiplier: 1/4),
            copyb.leadingAnchor.constraint(equalTo: libaryB.trailingAnchor),
        ])

        copyb.setTitle("Copy", for: .normal)

        circleB.addTarget(self, action: #selector(circleBox), for: .touchDown)
        saveB.addTarget(self, action: #selector(saveData), for: .touchDown)
        copyb.addTarget(self, action: #selector(copyM), for: .touchDown)
    }

    //2ndBelow

    @objc func copyM() {
        guard let originalView = currentView as? UIImageView else { return }

        // Ensure we are not duplicating unintended objects
        if objects.contains(originalView) {
            print("Original object already exists, copying it.")
        }

        let copiedView = UIImageView(image: originalView.image)
        copiedView.frame = CGRect(
            x: originalView.frame.origin.x + 20,
            y: originalView.frame.origin.y + 20,
            width: originalView.frame.width,
            height: originalView.frame.height
        )

        copiedView.isUserInteractionEnabled = true
        copiedView.backgroundColor = originalView.backgroundColor
        copiedView.layer.cornerRadius = originalView.layer.cornerRadius
        copiedView.clipsToBounds = true
        copiedView.layer.borderWidth = originalView.layer.borderWidth
        copiedView.layer.borderColor = originalView.layer.borderColor

        for subview in originalView.subviews {
            if let label = subview as? UILabel {
                let copiedLabel = UILabel(frame: label.frame)
                copiedLabel.text = label.text
                copiedLabel.textAlignment = label.textAlignment
                copiedView.addSubview(copiedLabel)
            }
        }

        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
        copiedView.addGestureRecognizer(pan)

        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        copiedView.addGestureRecognizer(tap)

        objects.append(copiedView)
        drawView.addSubview(copiedView)
        currentView = copiedView

        print("Copied object, total objects: \(objects.count)")
    }

    func captureFullScreenshot() -> UIImage {
        let allFrames = Set(objects.map { $0.frame }) // Unique frames only
        let expandedBounds = allFrames.reduce(drawView.bounds) { $0.union($1) }

        let renderer = UIGraphicsImageRenderer(bounds: expandedBounds)

        return renderer.image { context in
            context.cgContext.translateBy(x: -expandedBounds.origin.x, y: -expandedBounds.origin.y)

            // Render drawView first (background)
            drawView.layer.render(in: context.cgContext)

            // Ensure each object is rendered only once
            var drawnObjects = Set<UIImageView>()
            for imageView in objects where !drawnObjects.contains(imageView) {
                let convertedFrame = drawView.convert(imageView.frame, from: view)
                context.cgContext.translateBy(x: convertedFrame.origin.x, y: convertedFrame.origin.y)
                imageView.layer.render(in: context.cgContext)
                context.cgContext.translateBy(x: -convertedFrame.origin.x, y: -convertedFrame.origin.y)
                drawnObjects.insert(imageView) // Mark as drawn
            }
        }
    }

    @objc func handlePanGestured(_ gesture: UIPanGestureRecognizer) {
        guard let draggedView = gesture.view else { return }

        let translation = gesture.translation(in: view)
        draggedView.center = CGPoint(x: draggedView.center.x + translation.x,
                                     y: draggedView.center.y + translation.y)
        gesture.setTranslation(.zero, in: view)

        // Update the object position in objects array
        if let index = objects.firstIndex(of: draggedView as! UIImageView) {
            objects[index].frame = draggedView.frame
        }

        currentView = draggedView
    }

    @objc func circleBox() {
        // Create a UIImageView for the circle
        let subview = UIImageView()

        // Enable interaction with the subview
        subview.isUserInteractionEnabled = true
        objects.append(subview)
        view.addSubview(subview)

        // Set the frame for the circle (must be a square, so equal width and height)
        let size: CGFloat = 80  // Define size of the circle
        subview.frame = CGRect(x: view.bounds.midX, y: view.bounds.midY + CGFloat(ww), width: size, height: size)
        subview.backgroundColor = UIColor.orange

        // Make the UIImageView a circle by setting the cornerRadius to half of the width/height
        subview.layer.cornerRadius = size / 2
        subview.clipsToBounds = true  // Ensures the circle shape is maintained

        // Add a border to the subview
        subview.layer.borderWidth = 2.0  // Set the border width
        subview.layer.borderColor = UIColor.black.cgColor  // Set the border color

        // Add pan and tap gesture recognizers
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
        subview.addGestureRecognizer(pan)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        subview.addGestureRecognizer(tapGesture)

        // Create and add bottom label for width (initially set to 3)
        let bottomLabel = UILabel()
        bottomLabel.text = "3"
        bottomLabel.textAlignment = .center
        bottomLabel.frame = CGRect(
            x: (subview.bounds.width - 50) / 2,  // Center horizontally
            y: subview.bounds.height - 20,       // Align at the bottom
            width: 50,
            height: 20
        )
        subview.addSubview(bottomLabel)

        // Create and add left label for height (initially set to 1)
        let leftLabel = UILabel()
        leftLabel.text = "1"
        leftLabel.textAlignment = .center
        leftLabel.frame = CGRect(
            x: 0,                               // Align to the left edge
            y: (subview.bounds.height - 20) / 2, // Center vertically
            width: 50,
            height: 20
        )
        subview.addSubview(leftLabel)

        // Automatically select the new circle
        currentView = subview
    }

    func createToolbar() -> UIToolbar {
        let toolbar = UIToolbar()
        toolbar.sizeToFit()

        let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))

        toolbar.items = [flexSpace, doneButton]
        return toolbar
    }

    @objc func libraryBUttonFunction() {

        print("Library Button Selected")
        // Replace `YourViewController` with the name of the view controller you want to present
        let destinationVC = Second()

        // Customize the modal presentation style (optional)
        destinationVC.modalPresentationStyle = .fullScreen // or .overFullScreen, .pageSheet, etc.

        // Present the view controller modally
        self.present(destinationVC, animated: true, completion: nil)
    }

    @objc func doneButtonTapped() {
        view.endEditing(true)
    }

    @objc func saveData() {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
        let context = appDelegate.persistentContainer.viewContext

        guard let nameText = txt.text, !nameText.isEmpty else {
            print("Text field is empty")
            return
        }

        // Capture the drawing from drawView as an image
        let drawingImage = captureFullScreenshot()

        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Name")
        fetchRequest.predicate = NSPredicate(format: "nameOfPic == %@", nameText)

        do {
            let results = try context.fetch(fetchRequest)

            if let existingEntry = results.first {
                // Update the existing entry
                existingEntry.setValue(nameText, forKey: "nameOfPic")
                existingEntry.setValue(drawingImage.pngData(), forKey: "pic")
            } else {
                // Create a new entry
                let entity = NSEntityDescription.entity(forEntityName: "Name", in: context)!
                let newEntry = NSManagedObject(entity: entity, insertInto: context)
                newEntry.setValue(nameText, forKey: "nameOfPic")
                newEntry.setValue(drawingImage.pngData(), forKey: "pic")
            }

            try context.save()
            print("Data saved successfully.")

            // Save image to the photo gallery
            UIImageWriteToSavedPhotosAlbum(drawingImage, self, #selector(imageSaved(_:didFinishSavingWithError:contextInfo:)), nil)

            // Notify Second about the save and update its list
            libraryBUttonFunction()
        } catch {
            print("Failed to save data: \(error.localizedDescription)")
        }

        print("Saving screenshot with \(objects.count) objects.")
    }

    // Completion handler for image saving
    @objc func imageSaved(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            print("Error saving image: \(error.localizedDescription)")
        } else {
            print("Image saved to photo gallery successfully.")
        }
    }

    @objc func handleTapGestured(_ gesture: UITapGestureRecognizer) {
        currentView = gesture.view
        // Set slider value to match the size of the selected box

    }
}
extension UIView {
    /// Takes a screenshot of a UIView, with an option to clip to view bounds and place a waterwark image
    /// - Parameter rect: offset and size of the screenshot to take
    /// - Parameter clipToBounds: Bool to check where self.bounds and rect intersect and adjust size so there is no empty space
    /// - Parameter watermark: UIImage of the watermark to place on top
    func screenshot(for rect: CGRect, clipToBounds: Bool = true, with watermark: UIImage? = nil) -> UIImage {
        var imageRect = rect
        if clipToBounds {
            imageRect = bounds.intersection(rect)
        }
        return UIGraphicsImageRenderer(bounds: imageRect).image { _ in
            drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
            watermark?.draw(in: CGRect(x: 0, y: 0, width: 32, height: 32))
        }
    }
}

In the screenshot if i copy the orignial first placed ojbect twice there are two other objects that are only displayed in the saved photo. So I place a circle copy the inal twice hit the copy button twice then in the saved photo there are 5 circles and there should only be 3.You can see in the photos below what is going on. The duplicated images are being saved in the positions of 1 in the first photo.

import UIKit
import CoreData

class First: UIViewController {
    var objects = [UIImageView]()
    var nextB = UIButton()
    var drawView = Canvas()

    var libaryB = UIButton()

    var ww = 80
    var saveB = UIButton()
    var circleB = UIButton()
    var copyb = UIButton()
    var txt = UITextField()
    var currentView: UIView?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        [saveB,circleB, libaryB,txt, drawView,copyb].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
            $0.layer.borderWidth = 1
            $0.backgroundColor = UIColor(
                red: .random(in: 0.5...0.7),
                green: .random(in: 0.0...1),
                blue: .random(in: 0.3...0.5),
                alpha: 1
            )
            $0.layer.borderWidth = 1

            if let textfield = $0 as? UITextField {
                textfield.textAlignment = .center
                textfield.inputAccessoryView = createToolbar()
            }

            if let label = $0 as? UILabel {
                label.textAlignment = .center
            }
            if let button = $0 as? UIButton {
                button.setTitleColor(.black, for: .normal)
            }
        }

        circleB.setTitle("Circle", for: .normal)
        libaryB.setTitle("Library", for: .normal)
        saveB.setTitle("Save", for: .normal)
        libaryB.addTarget(self, action: #selector(libraryBUttonFunction), for: .touchDown)
        // note that I changed some of the constraints to use the safeAreaLayoutGuide of the view
        // you wouldn't want your sliders to go out of the safe area, would you?
        NSLayoutConstraint.activate([
            txt.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            txt.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            txt.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            txt.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),

            drawView.topAnchor.constraint(equalTo: txt.bottomAnchor),
            drawView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            drawView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6),
            drawView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),

            circleB.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            circleB.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            circleB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            circleB.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/4),

            saveB.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            saveB.leadingAnchor.constraint(equalTo: circleB.trailingAnchor),
            saveB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            saveB.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/4),

            libaryB.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            libaryB.leadingAnchor.constraint(equalTo: saveB.trailingAnchor),
            libaryB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            libaryB.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/4),

            copyb.bottomAnchor.constraint(equalTo: circleB.topAnchor),
            copyb.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor, multiplier: 0.05),
            copyb.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor, multiplier: 1/4),
            copyb.leadingAnchor.constraint(equalTo: libaryB.trailingAnchor),
        ])

        copyb.setTitle("Copy", for: .normal)

        circleB.addTarget(self, action: #selector(circleBox), for: .touchDown)
        saveB.addTarget(self, action: #selector(saveData), for: .touchDown)
        copyb.addTarget(self, action: #selector(copyM), for: .touchDown)
    }

    //2ndBelow

    @objc func copyM() {
        guard let originalView = currentView as? UIImageView else { return }

        // Ensure we are not duplicating unintended objects
        if objects.contains(originalView) {
            print("Original object already exists, copying it.")
        }

        let copiedView = UIImageView(image: originalView.image)
        copiedView.frame = CGRect(
            x: originalView.frame.origin.x + 20,
            y: originalView.frame.origin.y + 20,
            width: originalView.frame.width,
            height: originalView.frame.height
        )

        copiedView.isUserInteractionEnabled = true
        copiedView.backgroundColor = originalView.backgroundColor
        copiedView.layer.cornerRadius = originalView.layer.cornerRadius
        copiedView.clipsToBounds = true
        copiedView.layer.borderWidth = originalView.layer.borderWidth
        copiedView.layer.borderColor = originalView.layer.borderColor

        for subview in originalView.subviews {
            if let label = subview as? UILabel {
                let copiedLabel = UILabel(frame: label.frame)
                copiedLabel.text = label.text
                copiedLabel.textAlignment = label.textAlignment
                copiedView.addSubview(copiedLabel)
            }
        }

        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
        copiedView.addGestureRecognizer(pan)

        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        copiedView.addGestureRecognizer(tap)

        objects.append(copiedView)
        drawView.addSubview(copiedView)
        currentView = copiedView

        print("Copied object, total objects: \(objects.count)")
    }

    func captureFullScreenshot() -> UIImage {
        let allFrames = Set(objects.map { $0.frame }) // Unique frames only
        let expandedBounds = allFrames.reduce(drawView.bounds) { $0.union($1) }

        let renderer = UIGraphicsImageRenderer(bounds: expandedBounds)

        return renderer.image { context in
            context.cgContext.translateBy(x: -expandedBounds.origin.x, y: -expandedBounds.origin.y)

            // Render drawView first (background)
            drawView.layer.render(in: context.cgContext)

            // Ensure each object is rendered only once
            var drawnObjects = Set<UIImageView>()
            for imageView in objects where !drawnObjects.contains(imageView) {
                let convertedFrame = drawView.convert(imageView.frame, from: view)
                context.cgContext.translateBy(x: convertedFrame.origin.x, y: convertedFrame.origin.y)
                imageView.layer.render(in: context.cgContext)
                context.cgContext.translateBy(x: -convertedFrame.origin.x, y: -convertedFrame.origin.y)
                drawnObjects.insert(imageView) // Mark as drawn
            }
        }
    }

    @objc func handlePanGestured(_ gesture: UIPanGestureRecognizer) {
        guard let draggedView = gesture.view else { return }

        let translation = gesture.translation(in: view)
        draggedView.center = CGPoint(x: draggedView.center.x + translation.x,
                                     y: draggedView.center.y + translation.y)
        gesture.setTranslation(.zero, in: view)

        // Update the object position in objects array
        if let index = objects.firstIndex(of: draggedView as! UIImageView) {
            objects[index].frame = draggedView.frame
        }

        currentView = draggedView
    }

    @objc func circleBox() {
        // Create a UIImageView for the circle
        let subview = UIImageView()

        // Enable interaction with the subview
        subview.isUserInteractionEnabled = true
        objects.append(subview)
        view.addSubview(subview)

        // Set the frame for the circle (must be a square, so equal width and height)
        let size: CGFloat = 80  // Define size of the circle
        subview.frame = CGRect(x: view.bounds.midX, y: view.bounds.midY + CGFloat(ww), width: size, height: size)
        subview.backgroundColor = UIColor.orange

        // Make the UIImageView a circle by setting the cornerRadius to half of the width/height
        subview.layer.cornerRadius = size / 2
        subview.clipsToBounds = true  // Ensures the circle shape is maintained

        // Add a border to the subview
        subview.layer.borderWidth = 2.0  // Set the border width
        subview.layer.borderColor = UIColor.black.cgColor  // Set the border color

        // Add pan and tap gesture recognizers
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
        subview.addGestureRecognizer(pan)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        subview.addGestureRecognizer(tapGesture)

        // Create and add bottom label for width (initially set to 3)
        let bottomLabel = UILabel()
        bottomLabel.text = "3"
        bottomLabel.textAlignment = .center
        bottomLabel.frame = CGRect(
            x: (subview.bounds.width - 50) / 2,  // Center horizontally
            y: subview.bounds.height - 20,       // Align at the bottom
            width: 50,
            height: 20
        )
        subview.addSubview(bottomLabel)

        // Create and add left label for height (initially set to 1)
        let leftLabel = UILabel()
        leftLabel.text = "1"
        leftLabel.textAlignment = .center
        leftLabel.frame = CGRect(
            x: 0,                               // Align to the left edge
            y: (subview.bounds.height - 20) / 2, // Center vertically
            width: 50,
            height: 20
        )
        subview.addSubview(leftLabel)

        // Automatically select the new circle
        currentView = subview
    }

    func createToolbar() -> UIToolbar {
        let toolbar = UIToolbar()
        toolbar.sizeToFit()

        let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))

        toolbar.items = [flexSpace, doneButton]
        return toolbar
    }

    @objc func libraryBUttonFunction() {

        print("Library Button Selected")
        // Replace `YourViewController` with the name of the view controller you want to present
        let destinationVC = Second()

        // Customize the modal presentation style (optional)
        destinationVC.modalPresentationStyle = .fullScreen // or .overFullScreen, .pageSheet, etc.

        // Present the view controller modally
        self.present(destinationVC, animated: true, completion: nil)
    }

    @objc func doneButtonTapped() {
        view.endEditing(true)
    }

    @objc func saveData() {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
        let context = appDelegate.persistentContainer.viewContext

        guard let nameText = txt.text, !nameText.isEmpty else {
            print("Text field is empty")
            return
        }

        // Capture the drawing from drawView as an image
        let drawingImage = captureFullScreenshot()

        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Name")
        fetchRequest.predicate = NSPredicate(format: "nameOfPic == %@", nameText)

        do {
            let results = try context.fetch(fetchRequest)

            if let existingEntry = results.first {
                // Update the existing entry
                existingEntry.setValue(nameText, forKey: "nameOfPic")
                existingEntry.setValue(drawingImage.pngData(), forKey: "pic")
            } else {
                // Create a new entry
                let entity = NSEntityDescription.entity(forEntityName: "Name", in: context)!
                let newEntry = NSManagedObject(entity: entity, insertInto: context)
                newEntry.setValue(nameText, forKey: "nameOfPic")
                newEntry.setValue(drawingImage.pngData(), forKey: "pic")
            }

            try context.save()
            print("Data saved successfully.")

            // Save image to the photo gallery
            UIImageWriteToSavedPhotosAlbum(drawingImage, self, #selector(imageSaved(_:didFinishSavingWithError:contextInfo:)), nil)

            // Notify Second about the save and update its list
            libraryBUttonFunction()
        } catch {
            print("Failed to save data: \(error.localizedDescription)")
        }

        print("Saving screenshot with \(objects.count) objects.")
    }

    // Completion handler for image saving
    @objc func imageSaved(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            print("Error saving image: \(error.localizedDescription)")
        } else {
            print("Image saved to photo gallery successfully.")
        }
    }

    @objc func handleTapGestured(_ gesture: UITapGestureRecognizer) {
        currentView = gesture.view
        // Set slider value to match the size of the selected box

    }
}
extension UIView {
    /// Takes a screenshot of a UIView, with an option to clip to view bounds and place a waterwark image
    /// - Parameter rect: offset and size of the screenshot to take
    /// - Parameter clipToBounds: Bool to check where self.bounds and rect intersect and adjust size so there is no empty space
    /// - Parameter watermark: UIImage of the watermark to place on top
    func screenshot(for rect: CGRect, clipToBounds: Bool = true, with watermark: UIImage? = nil) -> UIImage {
        var imageRect = rect
        if clipToBounds {
            imageRect = bounds.intersection(rect)
        }
        return UIGraphicsImageRenderer(bounds: imageRect).image { _ in
            drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
            watermark?.draw(in: CGRect(x: 0, y: 0, width: 32, height: 32))
        }
    }
}
Share Improve this question edited Mar 16 at 22:54 Sam Burns asked Mar 13 at 0:55 Sam BurnsSam Burns 271 silver badge13 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0 +50

Sounds like the screenshot is picking up duplicated UIImageView copies because drawHierarchy renders everything in the view hierarchy, even what you don’t see on screen. Try switching to layer.render and ensure copied views are fresh instances rather t cloned references.

Try this:

func takeScreenshot() -> UIImage {
    let renderer = UIGraphicsImageRenderer(bounds: view.bounds)
    return renderer.image { ctx in
        view.layer.render(in: ctx.cgContext) // Renders what’s actually there
    }
}

@objc func copyButtonTapped() {
    guard let orig = objects.first else { return }
    let copy = UIImageView(image: orig.image) // Fresh copy, no baggage
    copy.frame = orig.frame.offsetBy(dx: 20, dy: 20)
    view.addSubview(copy)
    objects.append(copy)
}

@objc func saveButtonTapped() {
    let shot = takeScreenshot()
    UIImageWriteToSavedPhotosAlbum(shot, nil, nil, nil)
}

本文标签: swiftScreenshot duplicating copied imagesStack Overflow