I am able to sign a pdf, But when I tried to saved it, Its not saving the updated pdf file.
Code
override func viewDidAppear(_ animated: Bool) {
pdfContainerView.usePageViewController(true, withViewOptions: nil)
guard let signatureImage = signatureImage, let page = pdfContainerView.currentPage else { return }
let pageBounds = page.bounds(for: .cropBox)
let imageBounds = CGRect(x: pageBounds.midX, y: pageBounds.midY, width: 200, height: 100)
let imageStamp = ImageStampAnnotation(with: signatureImage, forBounds: imageBounds, withProperties: nil)
page.addAnnotation(imageStamp)
btnSaveSign.isHidden = false
}
func setupPdfView(url:String) {
if let documentURL = URL(string: url),
let data = try? Data(contentsOf: documentURL),
let document = PDFDocument(data: data) {
// Set document to the view, center it, and set background color
//pdfContainerView.displayMode = .singlePageContinuous
pdfContainerView.document = document
pdfContainerView.autoScales = true
pdfContainerView.displayDirection = .horizontal
pdfContainerView.backgroundColor = UIColor.white
btnNewSign.isHidden = false
lblPlaceholder.isHidden = true
let panAnnotationGesture = UIPanGestureRecognizer(target: self, action: #selector(didPanAnnotation(sender:)))
pdfContainerView.addGestureRecognizer(panAnnotationGesture)
}
}
#objc func didPanAnnotation(sender: UIPanGestureRecognizer) {
let touchLocation = sender.location(in: pdfContainerView)
guard let page = pdfContainerView.page(for: touchLocation, nearest: true)
else {
return
}
let locationOnPage = pdfContainerView.convert(touchLocation, to: page)
switch sender.state {
case .began:
guard let annotation = page.annotation(at: locationOnPage) else {
return
}
if annotation.isKind(of: ImageStampAnnotation.self) {
currentlySelectedAnnotation = annotation
}
case .changed:
guard let annotation = currentlySelectedAnnotation else {
return
}
let initialBounds = annotation.bounds
// Set the center of the annotation to the spot of our finger
annotation.bounds = CGRect(x: locationOnPage.x - (initialBounds.width / 2), y: locationOnPage.y - (initialBounds.height / 2), width: initialBounds.width, height: initialBounds.height)
//print("move to \(locationOnPage)")
case .ended, .cancelled, .failed:
currentlySelectedAnnotation = nil
default:
break
}
}
#objc func clickButton(){
let importMenu = UIDocumentPickerViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let myURL = urls.first else {
return
}
print("import result : \(myURL)")
self.pdfURLToSave = "\(myURL)"
let pdfView = PDFView(frame: view.frame)
title = "My PDF Viewer"
setupPdfView(url:"\(myURL)")
}
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self//or use return self.navigationController for fetching app navigation bar colour
}
public func documentMenu(_ documentMenu:UIDocumentPickerViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
Code snippet for save file-
#IBAction func btnSaveAction(_ sender: Any) {
if let documentURL = URL(string: self.pdfURLToSave),
let data = try? Data(contentsOf: documentURL),
let document = PDFDocument(data: data) {
if let data = document.dataRepresentation(){
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0] // Get documents folder
let folderPathUrl = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("SignApp.pdf")
if FileManager.default.fileExists(atPath: folderPathUrl.path){
try? FileManager.default.removeItem(at: folderPathUrl)
}
pdfContainerView.document?.write(toFile: "\(folderPathUrl)")
}
}
}
ImageStampAnnotation Class
class ImageStampAnnotation: PDFAnnotation {
var image: UIImage!
// A custom init that sets the type to Stamp on default and assigns our Image variable
init(with image: UIImage!, forBounds bounds: CGRect, withProperties properties: [AnyHashable : Any]?) {
super.init(bounds: bounds, forType: PDFAnnotationSubtype.stamp, withProperties: properties)
self.image = image
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(with box: PDFDisplayBox, in context: CGContext) {
// Get the CGImage of our image
guard let cgImage = self.image.cgImage else { return }
// Draw our CGImage in the context of our PDFAnnotation bounds
context.draw(cgImage, in: self.bounds)
}
}
Error-
CGPDFContextCreate: failed to create PDF context delegate..
App screen shots-
It's not possible for me to edit your code directly to show a proper solution, since your code isn't complete, but here is a short coordinator class, including your pan annotation code that saves an updated file each time a pan gesture is completed:
class Coordinator : NSObject {
var pdfView : PDFView?
var currentlySelectedAnnotation : PDFAnnotation?
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
func save() {
guard let pdfView = pdfView else {
return
}
let url = getDocumentsDirectory().appendingPathComponent("SavedPDF.pdf")
pdfView.document?.write(to: url)
print("Wrote pdf to: ", url)
}
#objc func didPanAnnotation(sender: UIPanGestureRecognizer) {
guard let pdfContainerView = pdfView else {
fatalError()
}
let touchLocation = sender.location(in: pdfContainerView)
guard let page = pdfContainerView.page(for: touchLocation, nearest: true)
else {
return
}
let locationOnPage = pdfContainerView.convert(touchLocation, to: page)
switch sender.state {
case .began:
guard let annotation = page.annotation(at: locationOnPage) else {
return
}
print("Set")
if annotation.isKind(of: ImageStampAnnotation.self) {
currentlySelectedAnnotation = annotation
}
case .changed:
guard let annotation = currentlySelectedAnnotation else {
return
}
let initialBounds = annotation.bounds
// Set the center of the annotation to the spot of our finger
annotation.bounds = CGRect(x: locationOnPage.x - (initialBounds.width / 2), y: locationOnPage.y - (initialBounds.height / 2), width: initialBounds.width, height: initialBounds.height)
//print("move to \(locationOnPage)")
case .ended, .cancelled, .failed:
currentlySelectedAnnotation = nil
save()
default:
break
}
}
}
For context, if it helps, this is how I set up the view controller and the PDFView initially:
let vc = UIViewController()
let pdfContainerView = PDFView()
let fileUrl = Bundle.main.url(forResource: "High Noon - SCORE", withExtension: "pdf")!
let pdfDocument = PDFDocument(url: fileUrl)
pdfContainerView.document = pdfDocument
pdfContainerView.autoScales = true
vc.view.addSubview(pdfContainerView)
let panAnnotationGesture = UIPanGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.didPanAnnotation(sender:)))
pdfContainerView.addGestureRecognizer(panAnnotationGesture)
let page = pdfContainerView.currentPage!
let pageBounds = page.bounds(for: .cropBox)
let imageBounds = CGRect(x: pageBounds.midX, y: pageBounds.midY, width: 200, height: 100)
let imageStamp = ImageStampAnnotation(with: UIImage(systemName: "pencil"), forBounds: imageBounds, withProperties: nil)
page.addAnnotation(imageStamp)
Related
I need to Draw over an image using PencilKit. the problem I face is I can't able to change the PencilKit tool picker tools (Eg pen to pencil). I am able to use only pen mode in the PKInkTool
Posted my code below
class ViewController: UIViewController, PKToolPickerObserver {
private var canvasView :PKCanvasView!
#IBOutlet weak var imgView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
setup()
}
func setup() {
let navigationItem = navigationController?.navigationBar.topItem
let pencilButton = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
pencilButton.addTarget(self, action: #selector(showPKToolKit), for: .touchUpInside)
pencilButton.setImage(UIImage(systemName: "pencil.tip"), for: .normal)
pencilButton.tintColor = .tintColor
navigationItem?.rightBarButtonItem = UIBarButtonItem(customView: pencilButton)
let fileManager = FileManager.default
guard let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let urls: [URL]
do {
urls = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
} catch {
fatalError("Couldn't load files from documents directory")
}
do{
let data = try Data(contentsOf: urls[0])
print(data)
imgView.image = UIImage(data:data)
}catch{
print("failed to load image")
}
canvasView = PKCanvasView.init(frame: self.imgView.frame)
self.canvasView.isOpaque = false
self.view.addSubview(self.canvasView)
}
#objc func showPKToolKit(){
let toolPicker = PKToolPicker.init()
toolPicker.setVisible(true, forFirstResponder: canvasView)
toolPicker.addObserver(canvasView)
canvasView.becomeFirstResponder()
self.canvasView.drawingPolicy = .anyInput
}
}
so this was my code.
output video link
anybody help to resolve the issue
I have updated the showPktoolkit method
#objc func showPKToolKit(){
if #available(iOS 14.0, *) {
toolPicker = PKToolPicker()
} else {
let window = parent?.view.window
toolPicker = PKToolPicker.shared(for: window!)
}
toolPicker.setVisible(true, forFirstResponder: canvasView)
toolPicker.addObserver(canvasView)
toolPicker.addObserver(self)
canvasView.becomeFirstResponder()
self.canvasView.drawingPolicy = .anyInput
}
Now it is working for me
video link
When I try to run my camera coding I receive following error message
"2019-05-09 23:15:48.446844+0200 testing2[514:31963] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[AVCaptureSession addInput:] Multiple audio/video AVCaptureInputs are not currently supported'
* First throw call stack:
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) "
I can't find out where the problem occurs and have tried with breakpoint to get to know but didn't manage.
Have also tried solutions with info.plist so it dosn't have anything with that to do.
let captureSession = AVCaptureSession()
var previewLayer:CALayer!
var captureDevice:AVCaptureDevice!
var takePhoto = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
prepareCamera()
}
func prepareCamera() {
captureSession.sessionPreset = AVCaptureSession.Preset.photo
let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
captureDevice = availableDevices.first
beginSession()
}
func beginSession () {
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
captureSession.addInput(captureDeviceInput)
}catch {
print(error.localizedDescription)
}
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
self.previewLayer = previewLayer
self.view.layer.addSublayer(self.previewLayer)
self.previewLayer.frame = self.view.layer.frame
captureSession.startRunning()
let dataOutput = AVCaptureVideoDataOutput()
dataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString):NSNumber(value:kCVPixelFormatType_32BGRA)] as [String : Any]
dataOutput.alwaysDiscardsLateVideoFrames = true
if captureSession.canAddOutput(dataOutput) {
captureSession.addOutput(dataOutput)
}
captureSession.commitConfiguration()
let queue = DispatchQueue(label: "com.brianadvent.captureQueue")
dataOutput.setSampleBufferDelegate(self, queue: queue)
}
#IBAction func takePhoto(_ sender: Any) {
takePhoto = true
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
if takePhoto {
takePhoto = false
if let image = self.getImageFromSampleBuffer(buffer: sampleBuffer) {
let photoVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoVC") as! Viewcontroller2
photoVC.takenPhoto = image
DispatchQueue.main.async {
self.present(photoVC, animated: true, completion: {
self.stopCaptureSession()
})
}
}
}
}
func getImageFromSampleBuffer (buffer:CMSampleBuffer) -> UIImage? {
if let pixelBuffer = CMSampleBufferGetImageBuffer(buffer) {
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
let context = CIContext()
let imageRect = CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))
if let image = context.createCGImage(ciImage, from: imageRect) {
return UIImage(cgImage: image, scale: UIScreen.main.scale, orientation: .right)
}
}
return nil
}
func stopCaptureSession () {
self.captureSession.stopRunning()
if let inputs = captureSession.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
self.captureSession.removeInput(input)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
struct Constants {
static let apiKey = "AIzaSyDtaJ5eU24rbnHsG9pb1STOizDJvqcaj5E"
static let bundleId = "com.felibundle"
static let searchEngineId = "016628067786358079133:2gm9usqzouc"
}
#IBAction func pish(_ sender: Any) {
googleSearch(term: "George Bush") { results in
print(results)}
}
func googleSearch(term: String, callback:#escaping ([(title: String, url: String)]?) -> Void) {
let urlString = String(format: "https://cse.google.com/cse?cx=016628067786358079133:2gm9usqzouc", term, Constants.searchEngineId, Constants.apiKey)
let encodedUrl = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
guard let url = URL(string: encodedUrl ?? urlString) else {
print("invalid url \(urlString)")
return
}
let request = NSMutableURLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
request.httpMethod = "GET"
request.setValue(Constants.bundleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
let session = URLSession.shared
let datatask = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard
error == nil,
let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any]
else {
callback(nil)
return
}
guard let items = json?["items"] as? [[String : Any]], items.count > 0 else {
print("no results")
return
}
callback(items.map { ($0["title"] as! String, $0["formattedUrl"] as! String) })
}
datatask.resume()
}
May be this
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
prepareCamera()
}
is called multiple times when you present a vc above the current vc and dismiss it , so you may put it inside viewDidLoad
this should fix the issue....
if captureSession.inputs.isEmpty {
self.captureSession.addInput(deviceInput)
}
initial view of view control where we start the download Once the download started it look like this I were working in a mp3 application where I need to download the mp3 from the list shown when the user click the download button it shows the control for pause, stop and a progress view. my download is working but I could not show the progress for the download all over the application. For example: if I am downloading some "x.mp3" song if the user click x.mp3 in VC1 the progress should also shown in VC3. Then the big problem I am facing is after downloading the download control should hide. Due to tableview reload function I cannot handle the UIrefresh which should show the download control and also the download button accordingly.
I have attached both my ViewController class the cell class and also the design
I have attached the "CELLFORROWATINDEXPATH" function for your reference and I have enclosed all the download functionality in the cell class.
viewcontroller Cellforrowatindexpath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let table_cell = tableView.dequeueReusableCell(withIdentifier: "LecturesVcCellID", for: indexPath) as! LecturesVcCell
let trackdata = searchResults[indexPath.row]
constantsList.playTypeArray.boolArray.append(false)
table_cell.configure(track: trackdata, index: indexPath.row)
table_cell.downloadbtn.tag = indexPath.row
table_cell.pauseButton.tag = indexPath.row
table_cell.cancelButton.tag = indexPath.row
table_cell.progressLabel.tag = indexPath.row
let x : Int = trackdata.classNumber as! Int
let className = String(x)
if index == indexPath.row {
table_cell.img_play.image=#imageLiteral(resourceName: "playing_track")
table_cell.lbl_SubTitle.text = "Now playing"
table_cell.lbl_SubTitle.textColor = #colorLiteral(red: 0.968627451, green: 0.7490196078, blue: 0.4823529412, alpha: 1)
}else {
table_cell.img_play.image=#imageLiteral(resourceName: "play_track")
table_cell.lbl_SubTitle.text = String(format: "Class - %# | %#", className,(trackdata.timeoftrack!))
table_cell.lbl_SubTitle.textColor = UIColor.lightGray
}
str_image = "https://www.imaginetventures.name/swamiji/wp-content/uploads/2019/01/introved.png"
constantsList.playTypeArray.imageLecture = str_image
table_cell.img_Show.sd_setImage(with: URL(string: str_image), placeholderImage: UIImage(named: "placeholder.png"))
table_cell.navigationController = self.navigationController
if str_Type .isEqual(to: "Playlist") {
table_cell.downloadbtn.isHidden = true
// table_cell.playlistAdditionImageview.isHidden = false
if tableView.cellForRow(at: indexPath)?.accessoryType == .checkmark {
table_cell.playlistAdditionImageview.isHidden = true
}else {
table_cell.playlistAdditionImageview.isHidden = false
}
}else {
table_cell.downloadbtn.setImage(UIImage(named: "DATA11"), for: .normal)
// table_cell.playlistAdditionImageview.isHidden = true
}
table_cell.selectionStyle = .none
return table_cell
}
viewcontrollercell classfile:
override func awakeFromNib() {
super.awakeFromNib()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
context = appDelegate.persistentContainer.viewContext
entity = NSEntityDescription.entity(forEntityName: "DownloadList", in: context)
}
#IBAction func pauseBtnAction (_ sender: UIButton) {
if(downloadTask != nil && isDownload) {
downloadTask!.cancel(byProducingResumeData: { (resumeData) -> Void in
self.downloadData = resumeData
})
isDownload = false
downloadTask = nil
pauseButton.setImage(UIImage(named: "start-button"), for: .normal)
}else
if(!isDownload && downloadData != nil) {
if let resumeData = self.downloadData {
downloadTask = urlSession?.downloadTask(withResumeData: resumeData)
} else {
let url:URL = URL(string: "\((constantsList.playTypeArray.arr_subCatagriesLecture.object(at: sender.tag) as AnyObject).value(forKey: "mp3") as! String)")!
downloadTask = downloadsSession?.downloadTask(with: url)
}
downloadTask!.resume()
isDownload = true
pauseButton.setImage(UIImage(named: "x"), for: .normal)
}
}
#IBAction func cancelBtnClicked (_ sender: UIButton) {
downloadTask?.cancel()
downloadData = nil
isDownload = false
downloadTask = nil
progress.progress = 0
progressLabel.text = "0%"
progress.setProgress(0.0, animated: true)
cancelButton.isHidden = true
pauseButton.isHidden = true
downloadbtn.isHidden = false
progressLabel.isHidden = true
progress.isHidden = true
}
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let completionHandler = appDelegate.backgroundSessionCompletionHandler {
appDelegate.backgroundSessionCompletionHandler = nil
completionHandler()
}
}
}
#IBAction func downloadBtnAction(_ sender: UIButton) {
// sender.pulse()
self.reachability = Reachability.init()
if ((self.reachability?.connection) != .none) {
switch self.reachability?.connection {
case .wifi?:
print("Wifi")
print(sender.tag)
constantsList.playTypeArray.typeofnetwork = true
downloadTapped(sender: sender.tag)
case .cellular?:
print("mobile data")
print(sender.tag)
let alert = UIAlertController(title: "Mobile Data usage Alert!", message: "Downloads will be using mobile data!!", preferredStyle: UIAlertController.Style.alert);
let action1 = UIAlertAction(title: "Ok", style: .default) { (action:UIAlertAction) in
self.downloadTapped(sender: sender.tag)
}
let action2 = UIAlertAction(title: "Cancel", style: .default) { (action:UIAlertAction) in
print("Cancelled")
}
alert.addAction(action1)
alert.addAction(action2)
self.navigationController?.present(alert, animated: true, completion: nil)
case .none:
print("Network Not reachable")
case .some(.none):
print("Some")
}
}else {
print("No Internet")
}
}
func downloadTapped(sender : Int) {
constantsList.playTypeArray.arrayDownloadSort.append(sender as NSNumber)
print(constantsList.playTypeArray.arrayDownloadSort)
constantsList.playTypeArray.boolArray[sender] = true
showDownloadControls = true
downloadbtn.isHidden = true
pauseButton.isHidden = false
cancelButton.isHidden = false
progressLabel.isHidden = true
progress.isHidden = false
progressLabel.text = "Downloading..."
var urlConfiguration:URLSessionConfiguration!
urlConfiguration = URLSessionConfiguration.default
let queue:OperationQueue = OperationQueue.main
urlSession = URLSession.init(configuration: urlConfiguration, delegate: self, delegateQueue: queue)
let url:NSURL = NSURL(string: "\((constantsList.playTypeArray.arr_subCatagriesLecture.object(at: sender) as AnyObject).value(forKey: "mp3") as! String)")!
downloadTask = urlSession.downloadTask(with: url as URL)
downloadTask.resume()
}
//DOWNLOADING THE FILE UPDATE THE PROGRESS
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
// 2
let progress1 = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite);
// 3
print(progress1)
// 4
// OperationQueue.main.addOperation
DispatchQueue.main.async (execute: {
self.isDownload = true
// 2
constantsList.playTypeArray.isDownloading = true
self.progress.setProgress(progress1, animated: false)
self.progressLabel.text = String(progress1 * 100) + "%"
constantsList.playTypeArray.setprogress = progress1
let i = 0
if progress1 == 1.0 {
constantsList.playTypeArray.isDownloading = false
print(i + 1)
}
})
}
//AFTER DOWNLOADING SAVE THE FILE TO APP DATA
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("Finish Downloading")
let filemanager = FileManager()
let directoryURL = filemanager.urls(for: .documentDirectory, in: .userDomainMask)[0]
print(directoryURL)
let docDirectoryURL = NSURL(fileURLWithPath: "\(directoryURL)")
print(docDirectoryURL)
let destinationFileName = downloadTask.originalRequest?.url?.lastPathComponent
print(destinationFileName!)
let destinationURL = docDirectoryURL.appendingPathComponent("\(destinationFileName!)")
print(destinationURL!)
if let path = destinationURL?.path {
if filemanager.fileExists(atPath: path) {
do {
try filemanager.removeItem(at: destinationURL!)
}catch let error as NSError{
print(error.localizedDescription)
}
}
}
do {
try filemanager.copyItem(at: location, to: destinationURL!)
print(destinationURL!)
print(downloadbtn.tag)
newUser = NSManagedObject(entity: entity!, insertInto: context)
dic66 = constantsList.playTypeArray.arr_subCatagriesLecture.object(at: downloadbtn.tag) as? NSDictionary
newUser.setValue(dic66?.value(forKey: "classname") as! NSNumber, forKey: "classname")
newUser.setValue("\(String(describing: dic66?.value(forKey: "time") as! String))", forKey: "time")
newUser.setValue("\(String(describing: dic66?.value(forKey: "title") as! String))", forKey: "songtitle")
newUser.setValue("\(destinationURL!.path)", forKey: "mp3Url")
newUser.setValue("\(String(describing: constantsList.playTypeArray.imageLecture!))", forKey: "imageurl")
do {
try context.save()
print(context)
self.cancelButton.isHidden = true
self.pauseButton.isHidden = true
self.downloadbtn.isHidden = true
self.progressLabel.isHidden = true
self.progress.isHidden = true
print("Successful")
} catch {
print("failed")
}
}catch {
print("Error while copying file")
}
downloadData = nil;
}
func configure(track: Track,index: Int) {
var filefound: Bool = false
var shopwControls: Bool = true
if(constantsList.playTypeArray.boolArray[index]) {
filefound = true
shopwControls = false
self.progress.setProgress(constantsList.playTypeArray.setprogress, animated: true)
}
lbl_Title.text = track.songTitle
//CLASS AND VOLUME UPDATION
let x : Int = track.classNumber as! Int
let className = String(x)
lbl_SubTitle.text = String(format: "Class - %# | %#", className,(track.timeoftrack!))
//core Data checking for already downloaded file
request.returnsObjectsAsFaults = false
request.resultType = .dictionaryResultType
do {
let result = try context.fetch(request)
dic66 = constantsList.playTypeArray.arr_subCatagriesLecture.object(at: index) as? NSDictionary
for data in result as! [[String:Any]] {
print(data["classname"] as! Int)
print(dic66?.value(forKey: "classname") as! Int)
if data["classname"] as! Int == (dic66?.value(forKey: "classname") as! Int) {
filefound = true
}
}
} catch {
print("Failed")
}
// If the track is already downloaded, enable cell selection and hide the Download button
selectionStyle = filefound ? UITableViewCell.SelectionStyle.gray : UITableViewCell.SelectionStyle.none
downloadbtn.isHidden = filefound
pauseButton.isHidden = shopwControls
cancelButton.isHidden = shopwControls
progress.isHidden = shopwControls
}
}
I am currently loading images from my server. The images are plenty depending on the number of images it return. I have been able to display these images successfully and I can scroll down to view all images. Now my problem is I want a way which I can click on a specific image i will be able to zoom it. I have shared my code below:
//Declaration of variables
var albumID: String?
var imagePath: String?
var path: String?
var getClickImage = UIImageView()
var zoomscrollV = UIScrollView()
var imageArray = [String]()
//view did load
override func viewDidLoad() {
super.viewDidLoad()
setUpViewsAlbumPhotos()
zoomscrollV.delegate = self
if !CheckInternet.Connection(){
showAlert(title: "No Internet", message: "Please connect your device to an internet connection")
}else{
fetchPhotos(albumID: albumID)
}
}
//viewDidAppear
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
zoomscrollV.isHidden = true
zoomscrollV.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height - 50)
zoomscrollV.minimumZoomScale=1
zoomscrollV.maximumZoomScale=10
zoomscrollV.bounces=false
self.view.addSubview(zoomscrollV)
getClickImage=UIImageView()
getClickImage.frame = CGRect(x:0, y:0, width:zoomscrollV.frame.width, height:zoomscrollV.frame.height)
getClickImage.backgroundColor = .black
getClickImage.contentMode = .scaleAspectFit
zoomscrollV.addSubview(getClickImage)
}
//This code makes an async call to download images and details from the server
let async_call = URL(string: "\(String.api_albumPhotos)\(albumID ?? "")")
let request = NSMutableURLRequest(url: async_call!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil {
print("error is:: \(error!.localizedDescription)")
DispatchQueue.main.async {
self.showAlert(title: "Error", message: "Sorry try again later")
self.stopActivityLoader()
}
return
}
do {
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = myJSON {
var responseCode: String!
var message: NSArray!
responseCode = parseJSON["responseCode"] as! String?
if responseCode == "200" {
DispatchQueue.main.async {
self.stopActivityLoader()
message = parseJSON["message"] as? NSArray
self.path = parseJSON["path"] as? String
if let message = message {
let totalMessage = message.count
let viewHeight = self.view.frame.height
var scrollHeight = 0
var contentViewTopConstraint: CGFloat = 20
// self.preference.set(parseJSON, forKey: UserDefaultKeys.albums.rawValue)
for obj in message{
if let dict = obj as? NSDictionary {
self.imagePath = dict.value(forKey: "path") as? String
let imageID = dict.value(forKey: "id") as? String
let albumThumbnail = photos()
self.scrollView.addSubview(albumThumbnail)
albumThumbnail.translatesAutoresizingMaskIntoConstraints = false
albumThumbnail.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
albumThumbnail.topAnchor.constraint(equalTo: self.scrollView.topAnchor, constant: contentViewTopConstraint).isActive = true
albumThumbnail.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor).isActive = true
albumThumbnail.heightAnchor.constraint(equalToConstant: 150).isActive = true
albumThumbnail.isUserInteractionEnabled = true
albumThumbnail.contentMode = .scaleAspectFit
let touchRec = UITapGestureRecognizer(target: self, action: #selector(self.myImageTapped(_:)))
albumThumbnail.addGestureRecognizer(touchRec)
if let path = self.path{
if let imagePath = self.imagePath{
let strippedPath = path.replacingOccurrences(of: "\\", with: "")
let strippedImagePath = imagePath.replacingOccurrences(of: "\\", with: "")
print("\(strippedPath)\(strippedImagePath)")
albumThumbnail.sd_setImage(with: URL(string: "\(strippedPath)\(strippedImagePath)"), placeholderImage: UIImage(named: "default_profile"), options: [.continueInBackground, .progressiveDownload])
if let wrapped = self.path {
self.imageArray.append("\(strippedPath)\(strippedImagePath)")
// print(self.imageArray.append(wrapped))
}
}
}
contentViewTopConstraint = contentViewTopConstraint + 170
}
}
scrollHeight = totalMessage * 170
if totalMessage <= 1 {
self.scrollView.contentSize.height = viewHeight + 20
}else{
self.scrollView.contentSize.height = CGFloat(scrollHeight)
}
}
}
}else{
//Show alert
DispatchQueue.main.async {
self.showAlert(title: "Error", message: "Sorry could not update album. Try again")
self.stopActivityLoader()
}
}
}
}catch{
print("you:: \(error.localizedDescription)")
//Show alert
DispatchQueue.main.async {
self.showAlert(title: "Error", message: "Sorry could not update album. Try again")
self.stopActivityLoader()
}
}
}
task.resume()
}
#objc func myImageTapped(_ sender: UITapGestureRecognizer) {
zoomscrollV.isHidden = false
let myImage = imageArray[(sender.view?.tag)!]
print("myImage \(myImage)")
// RESPECTIVE IMAGE
getClickImage.image = UIImage(named: myImage)
let closeButton: UIButton = UIButton(type: .custom)
closeButton.frame = CGRect(x:40.0, y:self.view.frame.height - 50, width:self.view.frame.width - 80, height:50.0)
closeButton.addTarget(self, action: #selector(self.closeZoom), for: .touchUpInside)
closeButton.setTitle("CLOSE ZOOM", for: .normal)
closeButton.setTitleColor(UIColor.white, for: .normal)
// CLOSE BUTTON
self.view.addSubview(closeButton)
}``
#objc func closeZoom(sender: AnyObject) {
zoomscrollV.isHidden = true
zoomscrollV.setZoomScale(1.0, animated: false)
sender.removeFromSuperview()
}
//SCROLLVIEW DELEGATE
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return getClickImage
}
========================== Edit Jan 24 ============================
CONVERT URL TO IMAGE
#objc func myImageTapped(_ sender: UITapGestureRecognizer) {
zoomscrollV.isHidden = false
let myImageURL = imageArray[(sender.view?.tag)!]
if let url = URL( string: myImageURL)
{
DispatchQueue.global().async {
if let data = try? Data( contentsOf:url){
DispatchQueue.main.async {
let myImage = UIImage( data:data)
print("myImage \(myImage)")
// RESPECTIVE IMAGE
getClickImage.image = UIImage(named: myImage)
let closeButton: UIButton = UIButton(type: .custom)
closeButton.frame = CGRect(x:40.0, y:self.view.frame.height - 50, width:self.view.frame.width - 80, height:50.0)
closeButton.addTarget(self, action: #selector(self.closeZoom), for: .touchUpInside)
closeButton.setTitle("CLOSE ZOOM", for: .normal)
closeButton.setTitleColor(UIColor.white, for: .normal)
// CLOSE BUTTON
self.view.addSubview(closeButton)
}
}
}
}
===============================================================
On image click, U have create scrollview and add respective image as subview, then zoom will work out.
var getClickImage = UIImageView()
var zoomscrollV = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
zoomscrollV.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
zoomscrollV.isHidden = true
zoomscrollV.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height - 50)
zoomscrollV.minimumZoomScale=1
zoomscrollV.maximumZoomScale=10
zoomscrollV.bounces=false
self.view.addSubview(zoomscrollV)
getClickImage=UIImageView()
getClickImage.frame = CGRect(x:0, y:0, width:zoomscrollV.frame.width, height:zoomscrollV.frame.height)
getClickImage.backgroundColor = .black
getClickImage.contentMode = .scaleAspectFit
zoomscrollV.addSubview(getClickImage)
}
// ON CLICKING IMAGE ACTION
#objc func myImageTapped(_ sender: UITapGestureRecognizer) {
zoomscrollV.isHidden = false
// RESPECTIVE IMAGE
getClickImage.image = BG_CARD_IMGS[(sender.view?.tag)!]
let closeButton: UIButton = UIButton(type: .custom)
closeButton.frame = CGRect(x:40.0, y:self.view.frame.height - 50, width:self.view.frame.width - 80, height:50.0)
closeButton.addTarget(self, action: #selector(self.closeZoom), for: .touchUpInside)
closeButton.setTitle("CLOSE ZOOM", for: .normal)
closeButton.setTitleColor(UIColor.red, for: .normal)
// CLOSE BUTTON
self.view.addSubview(closeButton)
}
#objc func closeZoom(sender: AnyObject) {
zoomscrollV.isHidden = true
zoomscrollV.setZoomScale(1.0, animated: false)
sender.removeFromSuperview()
}
//SCROLLVIEW DELEGATE
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return getClickImage
}
OUTPUT
I am 100% sure this has been answered but the answers I am finding I cannot seem to make fit into my solution.
Starting from the beginning I have my ShareViewController where I have two imageViews put one on one, and in order to make it one image I am taking a screenshot of that imageView size. The code for taking screenshot I have taken here iOS: what's the fastest, most performant way to make a screenshot programmatically?
Here is my class:
import UIKit
import Photos
class ShareViewController: UIViewController, UIDocumentInteractionControllerDelegate {
var defaultImage: UIImage? = nil
var documentController: UIDocumentInteractionController!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var overlayImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
guard let image = defaultImage else {
return
}
self.imageView.image = image
self.imageView.contentMode = .ScaleAspectFill
let subimage1 = UIImage(named: "overlay")
self.overlayImageView.image = subimage1
self.imageView.clipsToBounds = true
}
#IBAction func shareButton(sender: UIButton) {
self.screenshot()
self.shareToInstagram()
_ = self.imageView.image!
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let fetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions)
if let lastAsset = fetchResult.firstObject as? PHAsset {
let localIdentifier = lastAsset.localIdentifier
let u = "instagram://library?LocalIdentifier=" + localIdentifier
_ = NSURL(string: u)!
}
}
// MARK: - Make Screenshot of ImageView
class func screenshot() -> UIImage {
var imageSize = CGSizeZero
let orientation = UIApplication.sharedApplication().statusBarOrientation
if UIInterfaceOrientationIsPortrait(orientation) {
imageSize = UIScreen.mainScreen().bounds.size
} else {
imageSize = CGSize(width: UIScreen.mainScreen().bounds.size.height, height: UIScreen.mainScreen().bounds.size.width)
}
UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
let context = UIGraphicsGetCurrentContext()
for window in UIApplication.sharedApplication().windows {
CGContextSaveGState(context)
CGContextTranslateCTM(context, window.center.x, window.center.y)
CGContextConcatCTM(context, window.transform)
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y)
if orientation == .LandscapeLeft {
CGContextRotateCTM(context, CGFloat(M_PI_2))
CGContextTranslateCTM(context, 0, -imageSize.width)
} else if orientation == .LandscapeRight {
CGContextRotateCTM(context, -CGFloat(M_PI_2))
CGContextTranslateCTM(context, -imageSize.height, 0)
} else if orientation == .PortraitUpsideDown {
CGContextRotateCTM(context, CGFloat(M_PI))
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height)
}
if window.respondsToSelector(#selector(UIView.drawViewHierarchyInRect(_:afterScreenUpdates:))) {
window.drawViewHierarchyInRect(window.bounds, afterScreenUpdates: true)
} else if let context = context {
window.layer.renderInContext(context)
}
CGContextRestoreGState(context)
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
// MARK: - Share photo to Instagram
func displayAlert(title: String, message: String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alertController, animated: true, completion: nil)
return
}
func displayShareSheet(shareContent:String) {
let activityViewController = UIActivityViewController(activityItems: [shareContent as NSString], applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: {})
}
func shareToInstagram() {
let instagramURL = NSURL(string: "instagram://app")
if (UIApplication.sharedApplication().canOpenURL(instagramURL!)) {
let imageData = UIImageJPEGRepresentation(self.imageView.image!, 100)
let captionString = "caption"
let writePath = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("instagram.igo")
if imageData?.writeToFile(writePath, atomically: true) == false {
return
} else {
let fileURL = NSURL(fileURLWithPath: writePath)
self.documentController = UIDocumentInteractionController(URL: fileURL)
self.documentController.delegate = self
self.documentController.UTI = "com.instagram.exlusivegram"
self.documentController.annotation = NSDictionary(object: captionString, forKey: "InstagramCaption")
self.documentController.presentOpenInMenuFromRect(self.view.frame, inView: self.view, animated: true)
}
} else {
print(" Instagram isn't installed ")
}
}
}
Now when I try to call screenshot() method it says that
Static member 'screenshot' cannot be used on instance of type
'ShareViewController'
How can I fix this and successfully take screenshot of my imageViews?