Swift laggy zooom in/out PDFView in .singlePage mode - ios

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

Related

iOS11 PDFView Memeory Leak

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)!))

AVPlayerViewController controls not working

I have an app which plays video clips on demand. This has worked well in previous versions of Xcode but I've upgraded to 8.3.3 and am having problems with the AVPlayerViewController.
The video plays and displays correctly. The control bar appears at the bottom of the view but does not respond to taps and, once faded out, does not reappear on tapping the video - unless, that is, I tap near the top left of the view.
My guess is that the actual controls are hidden in some kind of overlay which has the wrong size i.e. it does not properly overlay the whole of the video view. Is there some way to force the AVPlayerViewController to relayout?
I've tried adding:
_playerController!.view.setNeedsLayout()
_playerController!.view.layoutIfNeeded()
But this has no effect.
Here's my code:
override func viewDidLoad() {
super.viewDidLoad()
_player = AVPlayer()
_playerController = AVPlayerViewController()
_playerController!.showsPlaybackControls = true
_playerController!.allowsPictureInPicturePlayback = false
_playerController!.videoGravity = AVLayerVideoGravityResizeAspectFill
_playerController!.player = _player
self.addChildViewController(_playerController!)
videoView.addSubview(_playerController!.view)
...
override func viewDidLayoutSubviews() {
let frame = UIScreen.main.bounds
_vidWidth = frame.width - 256.0
_vidHeight = _vidWidth / 854.0 * 480.0
videoView.frame = CGRect(x: 0, y: 10.0, width: _vidWidth, height: _vidHeight)
videoView.backgroundColor = UIColor.black
_playerController?.view.frame = CGRect(x: 0, y: 0, width: _vidWidth, height: _vidHeight)
...
func playVideo(_ clip: Clip) {
var videoUrl: URL? = nil
if clip.offlineLocation != nil && clip.state == 2 {
_videoPath = clip.offlineLocation!
videoUrl = URL(fileURLWithPath: _videoPath!)
}
else {
_videoPath = "https://xxxx.cloudfront.net/" + clip.location
videoUrl = URL(string: _videoPath!)
}
NSLog(_videoPath!)
let asset = AVURLAsset(url:videoUrl!, options:nil)
let playerItem = AVPlayerItem(asset: asset)
_player!.replaceCurrentItem(with: playerItem)
_player!.play()
}

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)
}

I don't know how to send screenshot to Instagram application in Swift

I am trying to implement image sharing to Instagram app using Swift.
I do know how to take screenshot but I am unable to get how to share the screenshot to Instagram application.
Here is my snapshot code:
_ = UIScreen.main
if UIApplication.shared.keyWindow != nil {
let top: CGFloat = 101
let bottom: CGFloat = 96
// The size of the cropped image
let size = CGSize(width: view.frame.size.width, height: view.frame.size.height - top - bottom)
// Start the context
UIGraphicsBeginImageContext(size)
// we are going to use context in a couple of places
let context = UIGraphicsGetCurrentContext()!
// Transform the context so that anything drawn into it is displaced "top" pixels up
// Something drawn at coordinate (0, 0) will now be drawn at (0, -top)
// This will result in the "top" pixels being cut off
// The bottom pixels are cut off because the size of the of the context
context.translateBy(x: 0, y: 0)
// Draw the view into the context (this is the snapshot)
UIGraphicsBeginImageContextWithOptions(size,view.isOpaque, 0)
self.view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
let snapshot = UIGraphicsGetImageFromCurrentImageContext()
// End the context (this is required to not leak resources)
UIGraphicsEndImageContext()
Swift 3.x code
You can take screenshot by passing the whichever view you like:
func getScreenshot(viewToSnapShot:UIView) -> UIImage {
UIGraphicsBeginImageContext(viewToSnapShot.frame.size)
viewToSnapShot.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
and grab the documentDirectory path too. I made a simple function that will return the document directory path.
func documentsDirectory() -> String {
return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
}
Now you can share the image on instagram using the UIDocumentInteractionController
In your ViewController import this:
import Social
//make UIDocumentInteractionController object
var docController:UIDocumentInteractionController!
And then call this function whenever you want to post screenshot/image on instagram
// On calling this function, will open your document controller
func postImageToInstagram() {
let instagram = URL(string: "instagram://app")!
if UIApplication.shared.canOpenURL(instagram) {
//By Passing self.view, I am actually taking the screenshot
let imageToBePosted = getScreenshot(viewToSnapShot: self.view)
let imageURL = URL(fileURLWithPath: documentsDirectory())
let fullPath = imageURL.appendingPathComponent("instagram.igo")
do {
try UIImagePNGRepresentation(imageToBePosted)!.write(to: fullPath)
let rect = CGRect(x: 0, y: 0, width: 0, height: 0)
let igImageHookFile = URL(string: "file://\(fullPath)")
docController = UIDocumentInteractionController(url: igImageHookFile!)
docController.uti = "com.instagram.photo"
docController.presentOpenInMenu(from: rect, in: self.view, animated: true)
} catch {
print(error)
}
} else {
print("Instagram not installed")
}
}
Tested on Xcode 8.1, iOS 10.1 device. Worked Fine.

Resources