iOS 13.1 PDFKit PDFView.go(to page:) isn't working - ios

The Apple API isn't working on iOS 13.1, does anyone have the same issue or I did wrong way to use it.
I tried to get a PDFPage from PDFDocument.page(at: validPageIndex), the outcome page is with right index, and I set this page to PDFView.go(to: page) and the navigation isn't working.
let validPageIndex: Int = 11
guard let targetPage = document.page(at: validPageIndex) else { return }
print(targetPage.index)
// Print 11
pdfView.go(to: targetPage)
the line pdfView.go(to: targetPage) was executed but the page in PDF file stay at first page
Thanks for Usama Azam, my PDFView display direction is horizontal, seems it works on vertical.

I tried this sample piece of code and it works for me to move page next and previous. You can follow this link to add a PDF view in Storyboard.
import UIKit
import PDFKit
class ViewController: UIViewController {
#IBOutlet weak var pdfView: PDFView!
var currentPage = 0
override func viewDidLoad() {
super.viewDidLoad()
if let path = Bundle.main.path(forResource: "sample", ofType: "pdf") {
if let pdfDocument = PDFDocument(url: URL(fileURLWithPath: path)) {
pdfView.displayMode = .singlePageContinuous
pdfView.autoScales = true
pdfView.displayDirection = .vertical
pdfView.document = pdfDocument
}
}
}
#IBAction func previousPage(_ sender: UIButton) {
let validPageIndex: Int = currentPage - 1
guard let targetPage = pdfView.document!.page(at: validPageIndex) else { return }
print(targetPage.index)
currentPage = currentPage - 1
pdfView.go(to: targetPage)
}
#IBAction func nextPage(_ sender: UIButton) {
let validPageIndex: Int = currentPage + 1
guard let targetPage = pdfView.document!.page(at: validPageIndex) else { return }
print(targetPage.index)
currentPage = currentPage + 1
pdfView.go(to: targetPage)
}
}

Try this code, it solves the problem in the SwiftUI UIViewRepresentable.
if let doc = pdfView.document,
let page = doc.page(at: pageNumber)
{
Task { #MainActor in
pdfView.go(to: page )
}
}

Related

How to apply MPSImageGuidedFilter in Swift

I applied OpenCV guided filter for my project in Python successfully and now I have to carry this function to my iOS application. I searched Apple developer website and found out a filter called MPSImageGuidedFilter. I suppose it works in a similar way as OpenCV guided filter. However, my limited knowledge of iOS programming does not let me figure out how to use it. Unfortunately, I could not find a sample code on the web too. Is there anyone who used this filter before? I really appreciate the help. Or a sample code using any filter under MPS would be helpful to figure out.
After a few days of hard work, I managed to make MPSImageGUidedFilter. Please see below the code who wants to work on:
import UIKit
import MetalPerformanceShaders
import MetalKit
class ViewController: UIViewController {
public var texIn: MTLTexture!
public var coefficient: MTLTexture!
public var context: CIContext!
let device = MTLCreateSystemDefaultDevice()!
var queue: MTLCommandQueue!
var Metalview: MTKView { return view as! MTKView }
override func viewDidLoad() {
super.viewDidLoad()
Metalview.drawableSize.height = 412
Metalview.drawableSize.width = 326
Metalview.framebufferOnly = false
Metalview.device = device
Metalview.delegate = self
queue = device.makeCommandQueue()
let textureLoader = MTKTextureLoader(device: device)
let urlCoeff = Bundle.main.url(forResource: "mask", withExtension: "png")
do {
coefficient = try textureLoader.newTexture(URL: urlCoeff!, options: [:])
} catch {
fatalError("coefficient file not uploaded")
}
let url = Bundle.main.url(forResource: "guide", withExtension: "png")
do {
texIn = try textureLoader.newTexture(URL: url!, options: [:])
} catch {
fatalError("resource file not uploaded")
}
}
}
extension ViewController: MTKViewDelegate {
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
func draw(in view: MTKView) {
guard let commandBuffer = queue.makeCommandBuffer(),
let drawable = view.currentDrawable else {
return
}
let shader = MPSImageGuidedFilter(device: device, kernelDiameter: 5)
shader.epsilon = 0.001
let textOut = drawable.texture
shader.encodeReconstruction(to: commandBuffer, guidanceTexture: texIn, coefficientsTexture: coefficient, destinationTexture: textOut)
commandBuffer.present(drawable)
commandBuffer.commit()
}
}

How to increase the size of the activity indicator [duplicate]

This question already has answers here:
Can I change the size of UIActivityIndicator?
(10 answers)
Closed 3 years ago.
I am newbie on IOS Development. I Created a UIWebView.
When the application launches I implemented the loader.
Now I want the loader to be a little bigger in size with some background image.
My code is this:
private var loadingObservation: NSKeyValueObservation?
private lazy var loadingIndicator: UIActivityIndicatorView = {
let spinner = UIActivityIndicatorView()
spinner.translatesAutoresizingMaskIntoConstraints = false
spinner.color = .black
return spinner
}()
override func viewDidLoad() {
super.viewDidLoad()
loadingObservation = webView.observe(\.isLoading, options: [.new, .old]) { [weak self] (_, change) in
guard let strongSelf = self else { return }
// this is fine
let new = change.newValue!
let old = change.oldValue!
if new && !old {
strongSelf.view.addSubview(strongSelf.loadingIndicator)
strongSelf.loadingIndicator.startAnimating()
NSLayoutConstraint.activate([strongSelf.loadingIndicator.centerXAnchor.constraint(equalTo: strongSelf.view.centerXAnchor),
strongSelf.loadingIndicator.centerYAnchor.constraint(equalTo: strongSelf.view.centerYAnchor)])
strongSelf.view.bringSubviewToFront(strongSelf.loadingIndicator)
}
else if !new && old {
strongSelf.loadingIndicator.stopAnimating()
strongSelf.loadingIndicator.removeFromSuperview()
}
}
let myURL = URL(string: "http://192.168.1.4:8080")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}
By this code I am getting the result like this:
Is there any expert on IOS who can help me out regarding this.
I want to increase the size of Loader. Any help is really appreciated regarding this. Thanks
You can try setting loadingIndicator.transform = CGAffineTransform.init(scaleX: 2, y: 2)
Make extension of UIActivityIndicatorView -
extension UIActivityIndicatorView {
func scaleIndicator(factor: CGFloat) {
transform = CGAffineTransform(scaleX: factor, y: factor)
}
}
Then can access scaleIndicator() method from your UIActivityIndicatorView object anywhere -
activityIndicatorView.scaleIndicator(factor: 2.5)

iOS charts what to do with empty dataset

I use charts for my project. However, I now run into a problem that if a dataset is empty I will all report error when I see debug area.
Now I am trying to find a solution to be able to stop creating the chart if the dataset is empty.
the error message I get 25x :
[32865:1852701] [Unknown process name] CGAffineTransformInvert:
singular matrix.
for now I have this solution but I don't know if there is a better one.
var gewichtenHond: [GewichtHond] = [] {
didSet {
if self.gewichtenHond.count == 0 {
self.lineChartView.noDataText = "Geen data beschikbaar om een grafiek te tekenen."
} else {
grafiekData(animatieSnelheid: 1.0, typeAnimatie: .easeInBounce)
}
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getGewichtenHond()
}
func getGewichtenHond() {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let context = appDelegate?.persistentContainer.viewContext
let hondFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Hond")
hondFetch.predicate = NSPredicate(format: "hondId = %#", hondId)
let honden = try! context?.fetch(hondFetch)
let hond: Hond = honden?.first as! Hond
self.gewichtenHond = hond.gewichten?.allObjects as! [GewichtHond]
}
for now I have this solution but I don't know if there is a better one.
I can see from your code that you are trying to get the data each time you open the scene, if so try this approach
class UIViewController : UIViewController{
var gewichtenHond: [GewichtHond] = [] {
didSet {
grafiekData(animatieSnelheid: 1.0, typeAnimatie: .easeInBounce)
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let context = appDelegate?.persistentContainer.viewContext
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.lineChartView.noDataText = "Geen data beschikbaar om een grafiek te tekenen."
getGewichtenHond()
}
func getGewichtenHond() {
let hondFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Hond")
hondFetch.predicate = NSPredicate(format: "hondId = %#", hondId)
let honden = try! context?.fetch(hondFetch)
let hond: Hond = honden?.first as! Hond
self.gewichtenHond = hond.gewichten?.allObjects as! [GewichtHond]
}
}
if you are just trying to get them just once as you open the scene i suggest moving
those two line
self.lineChartView.noDataText = "Geen data beschikbaar om een grafiek te tekenen."
getGewichtenHond()
inside the viewDidLoad method because viewWillAppear will trigger every time you leave the scene and get back to it

How to solve Command failed due to signal: Segmentation fault: 11

I was searching for this issue here, and found out that this issue is not common one.
Everyone had different approaches to solve it. I'm using Firebase and Gifu framework. Actually for the last one - i copied all the files to my project, but that didn't helped either.
Here is my source code:
import FirebaseDatabase
import FirebaseAuth
import Firebase
import UIKit
import Gifu
class ViewController: UIViewController {
#IBOutlet weak var userImage: AnimatableImageView!
var displayedUserId = ""
var AcceptedOrRejected = ""
override func viewDidLoad() {
super.viewDidLoad()
let urlArray = ["http://i.imgur.com/VAWlQ0S.gif", "http://i.imgur.com/JDzGqvE.gif", "http://67.media.tumblr.com/4cd2a04b60bb867bb4746d682aa60020/tumblr_mjs2dvWX6x1rvn6njo1_400.gif", "https://media.giphy.com/media/TlK63ELk5OPDzpb6Tao/giphy.gif", "http://i3.photobucket.com/albums/y90/spicestas/GeriHalliwell-Calling-new1.gif", "http://media.tumblr.com/tumblr_lnb9aozmM71qbxrlp.gif"]
var counter = 1
for url in urlArray {
let nsUrl = NSURL(string: url)
let girls = ProfileClass()
girls.profilePhotoUrl = url
girls.profileGender = "female"
girls.profileName = "girlsname\(counter)"
girls.profileSurname = "girlsurname\(counter)"
girls.interest = "men"
girls.uid = "\(randomStringWithLength(45))"
counter++
girls.SaveUser()
}
//----setting variables
let label = UILabel(frame: CGRectMake(self.view.bounds.width / 2 - 100, self.view.bounds.height / 2 - 50, 300, 100))
//label.text = "Drag me!"
//label.textAlignment = NSTextAlignment.Center
self.view.addSubview(label)
let gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
userImage.addGestureRecognizer(gesture)
userImage.userInteractionEnabled = true
//----getting access to database
let thisUserRef = URL_BASE.childByAppendingPath("profile")
thisUserRef.queryOrderedByChild("Interest").queryEqualToValue("men").observeEventType(.Value, withBlock: {
snapshot in
for child in snapshot.children{
self.displayedUserId = (child.value["uid"] as? String)!
let imageURL = child.value["photo"] as? String
let imURL = NSURL(string: imageURL!)
//print(imageURL)
if self.AcceptedOrRejected != "" {
let AcceptedArray = child.value[AcceptedOrRejected] as? Array
AcceptedArray.append(displayedUserId)
}
if let picData = NSData(contentsOfURL: imURL!) {
self.userImage.animateWithImageData(picData)
//self.userImage.image = UIImage(data: picData)
}
}
})
}
//-----Dragging function-----------
func wasDragged(gesture: UIPanGestureRecognizer) {
//set traslations
let translation = gesture.translationInView(self.view)
let label = gesture.view
//set center position
label!.center = CGPoint(x: self.view.bounds.width / 2 + translation.x, y: self.view.bounds.height / 2 - translation.y )
let xfromCenter = (label?.center.x)! - self.view.bounds.width / 2
let scale = min(100 / abs(xfromCenter),1)
var rotation = CGAffineTransformMakeRotation(xfromCenter / 200)
var strech = CGAffineTransformScale(rotation, scale, scale)
label?.transform = strech
if gesture.state == UIGestureRecognizerState.Ended {
if label?.center.x < 100 {
self.AcceptedOrRejected = "Accepted"
} else if label?.center.x > self.view.bounds.width / 100 {
self.AcceptedOrRejected = "Rejected"
}
rotation = CGAffineTransformMakeRotation(0)
strech = CGAffineTransformScale(rotation, 1, 1)
label?.transform = strech
label?.center = CGPoint(x: self.view.bounds.width / 2 , y: self.view.bounds.height / 2 )
}
}
//---Function for generating randomn userid
func randomStringWithLength (len : Int) -> NSString {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: len)
for (var i=0; i < len; i += 1){
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
return randomString
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "LogOutSegue" {
try! FIRAuth.auth()!.signOut()
}
}
}
And I get this error
1. While emitting SIL for 'viewDidLoad' at /Users/zkid18/Desktop/wrk/Bloom/Bloom/ViewController.swift:23:14
2. While silgen closureexpr SIL function #_TFFC5Bloom14ViewController11viewDidLoadFT_T_U_FCSo15FIRDataSnapshotT_ for expression at [/Users/zkid18/Desktop/wrk/Bloom/Bloom/ViewController.swift:68:114 - line:107:9] RangeText="{
snapshot in
for child in snapshot.children{
self.displayedUserId = (child.value["uid"] as? String)!
let imageURL = child.value["photo"] as? String
let imURL = NSURL(string: imageURL!)
//print(imageURL)
if self.AcceptedOrRejected != "" {
let AcceptedArray = child.value[AcceptedOrRejected] as? Array
AcceptedArray.append(displayedUserId)
}
if let picData = NSData(contentsOfURL: imURL!) {
self.userImage.animateWithImageData(picData)
//self.userImage.image = UIImage(data: picData)
}
}
}"
I don't really know what to do with that
I just attempted a conversion to Swift 3 to get a jump on fixing issues in my code. I have similar error but I just integrated Firebase into all of my project. I found that by removing the pod and framework from the app and commenting out all firebase code fixed this compile issue.

How do i use mapbox's new MGLOfflinePackDelegate correctly?

I'm creating an app which needs an offline map. I'm testing with MapBox, which supports offline maps since today (yay!). The code I have now seems to work for downloading the map, but the delegate to report on progress never triggers, and I don't have a clue why this is.
I have this class for my mapView:
import UIKit
import Mapbox
class MapController: UIViewController, MGLMapViewDelegate, UIPopoverPresentationControllerDelegate {
#IBOutlet var mapView: MGLMapView!
override func viewDidLoad() {
super.viewDidLoad()
downloadIfNeeded()
mapView.maximumZoomLevel = 18
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func downloadIfNeeded() {
MGLOfflineStorage.sharedOfflineStorage().getPacksWithCompletionHandler { (packs, error) in guard error == nil else {
return
}
for pack in packs {
let userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context) as! [String: String]
if userInfo["name"] == "London" {
// allready downloaded
return
}
}
// define the download region
let sw = CLLocationCoordinate2DMake(51.212120, 4.415906)
let ne = CLLocationCoordinate2DMake(51.223781, 4.442401)
let bounds = MGLCoordinateBounds(sw: sw, ne: ne)
let region = MGLTilePyramidOfflineRegion(styleURL: MGLStyle.streetsStyleURL(), bounds: bounds, fromZoomLevel: 10, toZoomLevel: 12)
let userInfo = ["name": "London"]
let context = NSKeyedArchiver.archivedDataWithRootObject(userInfo)
MGLOfflineStorage.sharedOfflineStorage().addPackForRegion(region, withContext: context) { (pack, error) in
guard error == nil else {
return
}
// create popup window with delegate
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let downloadProgress: MapDownloadController = storyboard.instantiateViewControllerWithIdentifier("MapDownloadController") as! MapDownloadController
downloadProgress.modalPresentationStyle = .Popover
downloadProgress.preferredContentSize = CGSizeMake(300, 150)
let popoverMapDownloadController = downloadProgress.popoverPresentationController
popoverMapDownloadController?.permittedArrowDirections = .Any
popoverMapDownloadController?.delegate = self
popoverMapDownloadController?.sourceView = self.mapView
popoverMapDownloadController?.sourceRect = CGRect(x: self.mapView.frame.midX, y: self.mapView.frame.midY, width: 1, height: 1)
self.presentViewController(downloadProgress, animated: true, completion: nil)
// set popup as delegate <----
pack!.delegate = downloadProgress
// start downloading
pack!.resume()
}
}
}
}
And the MapDownloadController is a View which is displayed as popup (see code above) and has the MGLOfflinePackDelegate:
import UIKit
import Mapbox
class MapDownloadController: UIViewController, MGLOfflinePackDelegate {
#IBOutlet var progress: UIProgressView!
#IBOutlet var progressText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func offlinePack(pack: MGLOfflinePack, progressDidChange progress: MGLOfflinePackProgress) {
// this function is never called, but why? <----
let completed = progress.countOfResourcesCompleted
let expected = progress.countOfResourcesExpected
let bytes = progress.countOfBytesCompleted
let MB = bytes / 1024
let str: String = "\(completed)/\(expected) voltooid (\(MB)MB)"
progressText.text = str
self.progress.setProgress(Float(completed) / Float(expected), animated: true)
}
func offlinePack(pack: MGLOfflinePack, didReceiveError error: NSError) {
// neither is this one... <----
let userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context) as! [String: String]
let strError = error.localizedFailureReason
}
func offlinePack(pack: MGLOfflinePack, didReceiveMaximumAllowedMapboxTiles maximumCount: UInt64) {
// .. or this one <----
let userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context) as! [String: String]
}
}
This is all pretty much taken from the documentation, so why are the delegate's functions (func offlinePack) never called? I did test with breakpoints so i am sure it is not. Still, the popup is shown and the region gets downloaded. (Checked with observing network traffic and with other code which lists the offline packs.)
Here’s an extremely simple implementation of Minh’s answer, using the current v3.2.0b1 example code. Expect this answer to become outdated quickly, as we’re still working on the v3.2.0 release.
import UIKit
import Mapbox
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate, MGLOfflinePackDelegate {
#IBOutlet var mapView: MGLMapView!
// Array of offline packs for the delegate work around (and your UI, potentially)
var offlinePacks = [MGLOfflinePack]()
override func viewDidLoad() {
super.viewDidLoad()
mapView.maximumZoomLevel = 2
downloadOffline()
}
func downloadOffline() {
// Create a region that includes the current viewport and any tiles needed to view it when zoomed further in.
let region = MGLTilePyramidOfflineRegion(styleURL: mapView.styleURL, bounds: mapView.visibleCoordinateBounds, fromZoomLevel: mapView.zoomLevel, toZoomLevel: mapView.maximumZoomLevel)
// Store some data for identification purposes alongside the downloaded resources.
let userInfo = ["name": "My Offline Pack"]
let context = NSKeyedArchiver.archivedDataWithRootObject(userInfo)
// Create and register an offline pack with the shared offline storage object.
MGLOfflineStorage.sharedOfflineStorage().addPackForRegion(region, withContext: context) { (pack, error) in
guard error == nil else {
print("The pack couldn’t be created for some reason.")
return
}
// Set the pack’s delegate (assuming self conforms to the MGLOfflinePackDelegate protocol).
pack!.delegate = self
// Start downloading.
pack!.resume()
// Retain reference to pack to work around it being lost and not sending delegate messages
self.offlinePacks.append(pack!)
}
}
func offlinePack(pack: MGLOfflinePack, progressDidChange progress: MGLOfflinePackProgress) {
let userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context) as! [String: String]
let completed = progress.countOfResourcesCompleted
let expected = progress.countOfResourcesExpected
print("Offline pack “\(userInfo["name"])” has downloaded \(completed) of \(expected) resources.")
}
func offlinePack(pack: MGLOfflinePack, didReceiveError error: NSError) {
let userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context) as! [String: String]
print("Offline pack “\(userInfo["name"])” received error: \(error.localizedFailureReason)")
}
func offlinePack(pack: MGLOfflinePack, didReceiveMaximumAllowedMapboxTiles maximumCount: UInt64) {
let userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context) as! [String: String]
print("Offline pack “\(userInfo["name"])” reached limit of \(maximumCount) tiles.")
}
}
(Cross-posted from this GitHub issue.)
This is a bug in the SDK. The workaround is for the completion handler to assign the passed-in MGLOfflinePack object to an ivar or other strong reference in the surrounding MapDownloadController class (example).

Resources