iOS11 PDFView Memeory Leak - ios

I use PDFView to display PDFs. If I scroll quickly I get memory leaks.
let pdfView = PDFView.init(frame: CGRect.zero)
self.view.insertSubview(pdfView, belowSubview: bottomBar)
pdfView.snp.makeConstraints { (make) in
make.top.equalTo(topBar.snp.bottom).offset(8)
make.left.equalTo(8)
make.right.equalTo(-8)
make.bottom.equalTo(-54)
}
let url = Bundle.main.url(forResource: "swift", withExtension: "pdf")!
let doc = PDFDocument.init(url: url)
pdfView.document = doc
if let page = doc?.page(at: 0) {
let rect = page.bounds(for: .mediaBox)
let scale = (UIScreen.width - 16) / rect.width
pdfView.minScaleFactor = scale
pdfView.maxScaleFactor = scale
pdfView.scaleFactor = scale
pdfView.displaysPageBreaks = true
pdfView.pageBreakMargins = UIEdgeInsets.init(top: 0, left: 0, bottom: 8/scale, right: 0)
pdfView.layoutDocumentView()
}
View Memory Graph Image

Can you try to display your PDF in a WebView instead ?
Something like this :
let url = yourLocalURL
webView.loadRequest(URLRequest(url: URL(string: url)!))

Related

Swift laggy zooom in/out PDFView in .singlePage mode

Why is using PDFView in .singlePage mode when I try to zoom in and zoom out is lagging?
I don't have any kinds of strange settings, just create a project from scratch to replicate this.
func displayPDF() {
pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
if let pdf = Bundle.main.url(forResource: "sample_pdf", withExtension: "pdf", subdirectory: nil, localization: nil) {
let doc = PDFDocument(url: pdf)
pdfView.document = doc
}
pdfView.displayMode = .singlePage
view.addSubview(pdfView)
}
This is an example of what is going on:
https://streamable.com/eyxiw2

Image is not showing according to size

I just want to show image according to image size if the image height is grater then width then image will show horizentally or if the width is grater then height then it will show in centre.
I have already tried and I am showing my code. What I am trying ?
override func viewDidLoad() {
super.viewDidLoad()
var profileImagesData:Array<UIImage> = []
for i in 0..<profileImages.count {
// for venueImageTemp in profileImages {
var statusDict = profileImages[i] as! Dictionary<String,Any>
var imageUrl = String(format:"%#",statusDict["imageId"] as! CVarArg)
print(imageUrl)
if imageUrl.contains("cloudinary.com") {
let imgNameArr = imageUrl.components(separatedBy: "upload/")
print(imgNameArr)
let subFisrtStr = imgNameArr[0]
print(subFisrtStr)
let subStr = imgNameArr[1]
print(subStr)
let subImgNameArr = subStr.components(separatedBy: "/")
print(subImgNameArr)
let subNameStr = subImgNameArr[1]
print(subNameStr)
imageUrl = ""
imageUrl = subFisrtStr + "upload/h_600,w_600/" + subNameStr
print(imageUrl)
}
let url = URL(string: imageUrl)
print(url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in
let image = UIImage(data: (data)!)
profileImagesData.append(image!)
}
let imageView = CYCImageScrollView(images: profileImagesData, frame: CGRect(x: 0, y: 20, width: self.view.frame.size.width, height: self.view.frame.size.height-150), pageColor: UIColor.lightGray, currentPageColor: UIColor.orange)
// imageView.layer.cornerRadius = 30
imageView.backgroundColor = UIColor.clear
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.layer.masksToBounds = true
self.view.addSubview(imageView)
}
I just want to show image according to their sizes.
Use content mode scaleAspectFill instead of scaleAspectFit
imageView.contentMode = .scaleAspectFill

Annotate/Draw on PDF in Swift

I am writing an app that will contain multiple PDF documents that I will display on screen depending on the user's input.
Once displayed, I would like to allow the user to draw/annotate on the PDF. I would then like to save the PDF with the drawings/annotations on for later use.
I have searched endlessly for tutorials on annotating a PDF but I am coming back with not much at all!
I have found a cocoapod on GitHub called 'UXMPDF'. Has anyone used this?
Any information on performing this type of operation would be hugely appreciated! Thanks
First Create PDFView and Load pdfFile:
override func viewDidLoad() {
super.viewDidLoad()
let pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
guard let document = PDFDocument(url: YOUR_FILE_PATH) else {
return
}
pdfView.document = document
pdfView.displayMode = .singlePageContinuous
pdfView.autoScales = true
pdfView.displayDirection = .horizontal
pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
pdfView.maxScaleFactor = 4
pdfView.delegate = self
pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
pdfView.usePageViewController(true, withViewOptions: nil)
pdfView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(pdfView)
self.pdfView = pdfView
self.pdfDocument = document
let highLightItem = UIMenuItem(title:"Highlight"), action: #selector(highlightFromMenuItem))
}
you can use pdfAnnotation from UIMenuItem like that:
#objc func highlightFromMenuItem() {
if let document = self.pdfDocument {
let pdfSelection : PDFSelection = PDFSelection(document: document)
pdfSelection.add((self.pdfView?.currentSelection)!)
let arrayByLines = self.pdfView?.currentSelection?.selectionsByLine()
arrayByLines?.forEach({ (selection) in
let annotation = PDFAnnotation(bounds: selection.bounds(for: (self.pdfView?.currentPage)!), forType: .highlight, withProperties: nil)
annotation.color = .yellow
self.pdfView?.currentPage?.addAnnotation(annotation)
})
}
}
If you want to save what did you did:
self.pdfView.document.write(to:YOUR_FILE_URL)
other pdfAnnotation you can use:
.underline
.strikeOut
.circle
.square

how to show video in a small frame in ios

I want to show a video of a topic in top half of the view and its matter in textview in the bottom half of the view. For that video control i want to have the features like play,pause,stop,ff etc. Also i want to play it from local resource as my web services hasn't been setup yet. pls suggest a good solution
I have tried UIWebView and added constraints to webview and textview but for some reason the web view is not showing the video correctly. below is my code
let purl = NSURL(fileURLWithPath: "/Users/Rohit/Desktop/videos/demo/demo/video1.mp4") webView.loadHTMLString("<iframe width = \" \(webView.frame.width) \" height = \"\(webView.frame.height)\" src = \"\(purl)\"></iframe>", baseURL: nil)
webView.backgroundColor = UIColor.green
webView.mediaPlaybackRequiresUserAction = true
webView.scrollView.isScrollEnabled = true
webView.isUserInteractionEnabled = true
Import AVFoundation and AVKit
Then play the video using an URL object (in Swift 3 NSURL is renamed to URL)
let player = AVPlayer(URL: URI)
let controller = AVPlayerViewController()
controller.player = player
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 10, width: screenSize.width, height: (screenSize.height - 10) * 0.5)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player.play()
You can use AVPlayerLayer and give it bounds.
private func inits() {
//let rootLayer: CALayer = self.layer
// rootLayer.masksToBounds = true
avPlayerLayer = AVPlayerLayer(player: player)
avPlayerLayer.bounds = self.bounds
// avPlayerLayer.backgroundColor = UIColor.yellowColor().CGColor
self.layer.insertSublayer(avPlayerLayer, atIndex: 0)
}

UIWebview remove padding / margin

I am loading a PDF into a UIWebview and I changed the background color to clear and set opaque to false. However now there is a padding or margin in my UIWebView that I would like to remove so the UIWebview is the screen.
I created a UIWebview like so:
let webview = UIWebView()
webview.frame = self.view.bounds
webview.scrollView.frame = webview.frame
webview.userInteractionEnabled = true
webview.scalesPageToFit = true
webview.becomeFirstResponder()
webview.delegate = self
webview.scrollView.delegate = self
webview.opaque = false
webview.backgroundColor = UIColor.clearColor()
self.view.addSubview(webview)
webview.loadRequest(NSURLRequest(URL:url))
webview.gestureRecognizers = [pinchRecognizer, panRecognizer]
and I applied this to the webViewDidFinishLoad method
func webViewDidFinishLoad(webView: UIWebView) {
let padding = "document.body.style.margin='0';document.body.style.padding = '0'"
webView.stringByEvaluatingJavaScriptFromString(padding)
}
but there is still a padding or margin, it looks like this:
How do I fix this?
The Reason why I need this fixed is because I am going to be saving this UIWebView as a PDF and when I save it, that extra spacing is there also, here is my PDF generate code:
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, CGRectZero, nil)
UIGraphicsBeginPDFPage()
printPageRenderer.drawPageAtIndex(0, inRect: UIGraphicsGetPDFContextBounds())
UIGraphicsEndPDFContext()
return data
}
and more
let screenHeight = appDelegate.webview!.scrollView.bounds.size.height
let heightStr = appDelegate.webview!.scrollView.bounds.size.height
let height = heightStr
let pages = ceil(height / screenHeight)
let pdfMutableData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfMutableData, appDelegate.webview!.scrollView.bounds, nil)
for i in 0..<Int(pages)
{
if (CGFloat((i+1)) * screenHeight > CGFloat(height)) {
var f = appDelegate.webview!.scrollView.frame
f.size.height -= ((CGFloat((i+1)) * screenHeight) - CGFloat(height));
appDelegate.webview!.scrollView.frame = f
}
UIGraphicsBeginPDFPage()
let currentContext = UIGraphicsGetCurrentContext()
appDelegate.webview!.scrollView.setContentOffset(CGPointMake(0, screenHeight * CGFloat(i)), animated: false)
appDelegate.webview!.scrollView.layer.renderInContext(currentContext!)
}
UIGraphicsEndPDFContext()
Setting the scroll view frame to the web view frame will have no effect while the web view is at the origin and an unwanted effect otherwise.
Adjust the scroll view contentInset:
// set t,l,b,r to be negative CGFloat values that suit your content
webView.scrollView.contentInset = UIEdgeInsetsMake(t,l,b,r);
This appears to fix my issue, not sure how well it work with other PDF documents (Portrait) mine is Landscape and it works fine.
appDelegate.webview = UIWebView()
appDelegate.webview!.frame = CGRect(x: 0 - 8, y: 0 - 8, width: self.view.bounds.size.width + 14, height: self.view.bounds.size.height + 14)
appDelegate.webview!.scrollView.frame = CGRect(x: 0 - 8, y: 0 - 8, width: self.view.bounds.size.width + 14, height: self.view.bounds.size.height + 14)
and then for saving the PDF
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
{
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect(x: 0 + 8, y: 0 - 8, width: aView.bounds.size.width - 17, height: aView.bounds.size.height - 117), nil)
UIGraphicsBeginPDFPage()
guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
aView.layer.renderInContext(pdfContext)
UIGraphicsEndPDFContext()
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.writeToFile(documentsFileName, atomically: true)
}
}
Please let me know if I am doing anything wrong
It worked for me to apply negative content insets. This works on iOS 11 and 10, on Swift 4:
webView.scrollView.contentInset = UIEdgeInsets(top: -8, left: -8, bottom: -8, right: -8)
I am not sure if you have found the answer but as a quick work around you can give pre adjusted constraint .
lets say if yours padding space is 10px from all 4 sides and if its always a constant
the work around is :
Give -10 space for the webView around it , also make don't forget to add a superview to your webView without the -10px side constraints and mark the superview
clipsToBounds = true
clipSubViews = true
This example gives a top spacing of 64 to allow for a nav bar.
let webView: UIWebView = UIWebView()
webView.frame = self.view.bounds
webView.scrollView.frame = webView.frame
webView.scrollView.contentInset = UIEdgeInsetsMake(64,0,0,0)
I don't know why I come here so many times but google never sends me through to the actually answered question. For anyone with the same problem here is the actual answer: https://stackoverflow.com/a/2442859/3393964
The problem is that browsers add a default margin, a simple fix is adding this:
body { margin: 0; padding: 0; }

Resources