In this app I get access to QRCode.
Reading works perfectly from the camera.
Now I am struggling to get the image that was processed by the built in QRCode reader.
I have found many hints on SO, but cannot make it work.
Here is the code I have now.
It is a bit long, I have to slit in 2 parts
I looked at:
// https://stackoverflow.com/questions/56088575/how-to-get-image-of-qr-code-after-scanning-in-swift-ios
// https://stackoverflow.com/questions/37869963/how-to-use-avcapturephotooutput
import UIKit
import AVFoundation
class ScannerViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
		fileprivate var captureSession: AVCaptureSession! // use for QRCode reading
		fileprivate var previewLayer: AVCaptureVideoPreviewLayer!
		
		// To get the image of the QRCode
		private var photoOutputQR: AVCapturePhotoOutput!
		private var isCapturing = false
		
		override func viewDidLoad() {
				super.viewDidLoad()
				var accessGranted = false
			 //	switch AVCaptureDevice.authorizationStatus(for: .video) {
// HERE TEST FOR ACCESS RIGHT. WORKS OK ;
// But is .video enough ?
				}
				
				if !accessGranted {	return }
				captureSession = AVCaptureSession()
				
				photoOutputQR = AVCapturePhotoOutput() // IS IT THE RIGHT PLACE AND THE RIGHT THING TO DO ?
				captureSession.addOutput(photoOutputQR)	 // Goal is to capture an image of QRCode once acquisition is done
				guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
				let videoInput: AVCaptureDeviceInput
				
				do {
						videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
				} catch {	return }
				
				if (captureSession.canAddInput(videoInput)) {
						captureSession.addInput(videoInput)
				} else {
						failed()
						return
				}
				
				let metadataOutput = AVCaptureMetadataOutput()
				
				if (captureSession.canAddOutput(metadataOutput)) {
						captureSession.addOutput(metadataOutput) // SO I have 2 output in captureSession. IS IT RIGHT ?
						
						metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
						metadataOutput.metadataObjectTypes = [.qr]	// For QRCode video acquisition
						
				} else {
						failed()
						return
				}
				
				previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
				previewLayer.frame = view.layer.bounds
				previewLayer.frame.origin.y += 40
				previewLayer.frame.size.height -= 40
				previewLayer.videoGravity = .resizeAspectFill
				view.layer.addSublayer(previewLayer)
				captureSession.startRunning()
		}
		
		override func viewWillAppear(_ animated: Bool) {
				
				super.viewWillAppear(animated)
				if (captureSession?.isRunning == false) {
						captureSession.startRunning()
				}
		}
		
		override func viewWillDisappear(_ animated: Bool) {
				
				super.viewWillDisappear(animated)
				if (captureSession?.isRunning == true) {
						captureSession.stopRunning()
				}
		}
		
		// MARK: - scan Results
		
		func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
				
				captureSession.stopRunning()
				
				if let metadataObject = metadataObjects.first {
						guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
						guard let stringValue = readableObject.stringValue else { return }
						AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
						found(code: stringValue)
				}
				// Get image - IS IT THE RIGHT PLACE TO DO IT ?
				// https://stackoverflow.com/questions/37869963/how-to-use-avcapturephotooutput
				print("Do I get here ?", isCapturing)
				let photoSettings = AVCapturePhotoSettings()
				let previewPixelType = photoSettings.availablePreviewPhotoPixelFormatTypes.first!
				print("previewPixelType", previewPixelType)
				let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
														 kCVPixelBufferWidthKey as String: 160,
														 kCVPixelBufferHeightKey as String: 160]
				photoSettings.previewPhotoFormat = previewFormat
				if !isCapturing {
						isCapturing = true
						photoOutputQR.capturePhoto(with: photoSettings, delegate: self)
				}
				dismiss(animated: true)
		}
		
}
extension ScannerViewController: AVCapturePhotoCaptureDelegate {
	
		func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
			
				isCapturing = false
				print("photo", photo, photo.fileDataRepresentation())
				guard let imageData = photo.fileDataRepresentation() else {
						print("Error while generating image from photo capture data.");
						return
				}
		 }
}
I get the following print on console
Clearly photo is not loaded properly
Do I get here ? false
previewPixelType 875704422
photo <AVCapturePhoto: 0x281973a20 pts:nan 1/1 settings:uid:3 photo:{0x0} time:nan-nan> nil
Error while generating image from photo capture data.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
When editing a Swift file in Xcode 12.2, I wanted to change the quotes autocompletion.
For this I looked at the Edit > Substitution menu and selected smartQuotes.
From this point, the whole substitution menu is disabled, no way to enable back.
Opened another file: same issue.
Opened another older version of Xcode: the same.
Opened Xcode 12.2 on another Mac: same thing
How can I re-enable the menu ?
Whilst typing this message, I tried again and the menu is once again reactivated ! I did nothing (at least intentionally).
Was it some type of time out or time required to complete a task ?
But did not return to normal on the other Mac.
But now, 10 more minutes later, it is disabled once again…
That's the type of surprise effect I do dislike in an app…
From the Landmarks sample project, I tried a variation, to get two cells side by side in the List.
This is the original with on cell per row as in the tutorial:
struct LandmarkList: View {
		
		var body: some View {
				List(landmarks) { landmark in
						LandmarkRow(landmark: landmark)
				}
		}
}
Surprisingly, the following variation works well to display 2 cells side by side:
struct LandmarkList: View {
		
		var body: some View {
				List (0 ..< (landmarks.count+1)/2) { item in
						LandmarkRow(landmark: landmarks[2*item])
						if 2*item + 1 < landmarks.count {
								LandmarkRow(landmark: landmarks[(2*item)+1])
						}
				}
		}
}
I thus tried to go on and add navigationLinks…
It works when adding a navigation link to the first cell only
struct LandmarkList: View {
		
		var body: some View {
				NavigationView {
						List (0 ..< (landmarks.count+1)/2) { item in
								NavigationLink(destination: LandmarkDetail()) {
										LandmarkRow(landmark: landmarks[2*item])
								}
								if 2*item + 1 < landmarks.count {
										LandmarkRow(landmark: landmarks[(2*item)+1])
								}
						}
						.navigationTitle("Landmarks")	
				}
		}
}
But adding NavigationLink to the second makes it fail:
struct LandmarkList: View {
		
		var body: some View {
				NavigationView {
						List (0 ..< (landmarks.count+1)/2) { item in
								NavigationLink(destination: LandmarkDetail()) {
										LandmarkRow(landmark: landmarks[2*item])
								}
								if 2*item + 1 < landmarks.count {
NavigationLink(destination: LandmarkDetail()) {
										 LandmarkRow(landmark: landmarks[(2*item)+1])
								 }
								}
						}
						.navigationTitle("Landmarks")	
				}
		}
}
The error is on line 3:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions Is it a normal List behaviour ?
Or did I miss something ?
Which expression could I break ?
Using AVSpeechSynthesizer, I noticed that some works in UPPERCASe are not correctly spoken.
SMALL is pronounced small
but WIDTH is pronounced W-I-D-T-H
I reproduced the problem in playground:
let sentence = "Hello everyone. Two minutes to go. SMALL WIDTH." let synthesizer = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: sentence)
utterance.voice = AVSpeechSynthesisVoice(
&#9;language: "en-GB"
)
utterance.rate = AVSpeechUtteranceDefaultSpeechRate * 1.05
synthesizer.speak(utterance)
Is it the expected behaviour ?
I suspect this point has been discussed in length, but I would like to find some reference to the design logic behind some Swift key aspect : the assignment operator, by value or reference.
We know well how = works, depending it deals with reference or value (knowing the consequence of misuse) and the difference between the 2 :
class AClass {
var val: Int = 0
}
struct AStruct {
var val : Int = 0
}
let aClass = AClass()
let bClass = aClass
bClass.val += 10
print("aClass.val", aClass.val, "bClass.val", bClass.val)
let aStruct = AStruct()
var bStruct = aStruct
bStruct.val += 10
print("aStruct.val", aStruct.val, "bStruct.val", bStruct.val)
Hence my question.
Was it ever considered to have 2 operators, one used to assign reference and the other to assign value?
Imagine we have :
= operator when dealing with references
:= operator when dealing with content.
Then
let bClass = aClass
would remain unchanged.
But
var bStruct = aStruct
would not be valid anymore, with a compiler warning to replace by
var bStruct := aStruct
On the other end, we could now write
let bClass := aClass
to create a new instance and assign another instance content, equivalent to convenience initialiser
class AClass {
var val: Int = 0
init(with aVar: AClass) {
self.val = aVar.val
}
init() {
}
}
called as
let cClass = AClass(with: aClass)
But the 2 operators would have made it clear that when using = we copy the reference. When using := we copy content.
I do think there is a strong rationale behind the present design choice (side effects I do not see ?), but I would appreciate to better understand which.
I have created a new entry in the capability list (background modes)
None is selected, so that seems to have no effect.
However, I would like to remove this entry to clean the screen. But I cannot find any "-" button, nor contextual menu, nor editing in XML…
Is it simply possible to remove ?
I consider the following distribution scheme for some Mac App: distribute the commercial (paying) version on Appstore
propose a free demo version (of course limited in some aspects) on a web site. This would of course be notarised.
The reason is to avoid having several versions on the Appstore which could create some confusion. The 2 versions would have similar names and differ essentially in the size of data they can handle.
Does anyone know if this is authorised by the Appstore Guidelines ? Or must I publish both on the AppStore ? Is there a risk my app being rejected as spam ?
In a MacOS App: When I create a file (in a folder), I save a security bookmark for the file.
if I ask user to authorise its folder (before creating the file in it), I can save its bookmark too, allowing to create other files in this folder.
So, when I create a file and need to create a companion (eg, a Results file), I first ask access to the folder, then create the file and create the results file in the same folder (hence having sandbox authorisation).
My understanding is that it is not possible to programmatically create and save the folder bookmark, after deriving its url from the file url, without requesting user to explicitly grant access (with NSOpen panel) ? Which would be very logical as it would deny the goal of security bookmarks.
So, is user explicit authorisation required (logical but creates more complexity when user moves files in the Finder).
Note: In fact don't really need it, as I save bookmark for every accessed file, but I would like to know.
The Code Block doesn't number lines anymore.
The work around is to ask for Numbered list in addition to Code block.
Just applying Code Block:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
Code Block AND Numbered List (or the other order)
1. required init?(coder aDecoder: NSCoder) {
2. super.init(coder: aDecoder)
3. commonInit()
4. }
Is there another way to get numbering directly ?
Even though I have selected all the notification options in my profile,
I do not receive any mail (since about a week), at least when an answer is marked as correct.
I did check they are not in spam.
What do I miss ?
I try to rotate a page 180° in a pdf file.
I nearly get it, but the page is also mirrored horizontally.
Some images to illustrate:
Initial page:
Result after rotation (see code): it is rotated 180° BUT mirrored horizontally as well:
The expected result
It is just as if it was rotated 180°, around the x axis of the page. And I would need to rotate 180° around z axis (perpendicular to the page). It is probably the result of
writeContext!.scaleBy(x: 1, y: -1)
I have tried a lot of changes for transform, translate, scale parameters, including removing calls to some of them, to no avail.
@IBAction func createNewPDF(_ sender: UIButton) {
var originalPdfDocument: CGPDFDocument!
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = urls[0]
// read some pdf from bundle for test
if let path = Bundle.main.path(forResource: "Test", ofType: "pdf"), let pdf = CGPDFDocument(URL(fileURLWithPath: path) as CFURL) {
originalPdfDocument = pdf
} else { return }
// create new pdf
let modifiedPdfURL = documentsDirectory.appendingPathComponent("Modified.pdf")
guard let page = originalPdfDocument.page(at: 1) else { return } // Starts at page 1
var mediaBox: CGRect = page.getBoxRect(CGPDFBox.mediaBox) // mediabox which will set the height and width of page
let writeContext = CGContext(modifiedPdfURL as CFURL, mediaBox: &mediaBox, nil) // get the context
var pageRect: CGRect = page.getBoxRect(CGPDFBox.mediaBox) // get the page rect
writeContext!.beginPage(mediaBox: &pageRect)
let m = page.getDrawingTransform(.mediaBox, rect: mediaBox, rotate: 0, preserveAspectRatio: true) // Because of rotate 0, no effect ; changed rotate to 180, then get an empty page
writeContext!.translateBy(x: 0, y: pageRect.size.height)
writeContext!.scaleBy(x: 1, y: -1)
writeContext!.concatenate(m)
writeContext!.clip(to: pageRect)
writeContext!.drawPDFPage(page) // draw content in page
writeContext!.endPage() // end the current page
writeContext!.closePDF()
}
Note: This is a follow up of a previous thread,
https://developer.apple.com/forums/thread/688436
I try to exclude some activities from UIActivity.
It works as expected when exclusion is done directly with the activity, as with:
UIActivity.ActivityType.message,
UIActivity.ActivityType.airDrop
but not when activity is declared with an init as with:
UIActivity.ActivityType(rawValue: "net.whatsapp.WhatsApp.ShareExtension"),
UIActivity.ActivityType(rawValue: "com.ifttt.ifttt.share"),
So, with the following code:
let excludedActivityTypes = [
UIActivity.ActivityType.message,
UIActivity.ActivityType.airDrop,
UIActivity.ActivityType(rawValue: "net.whatsapp.WhatsApp.ShareExtension"),
UIActivity.ActivityType(rawValue: "com.ifttt.ifttt.share")
]
let activityVC = UIActivityViewController(activityItems: [modifiedPdfURL], applicationActivities: nil)
activityVC.excludedActivityTypes = excludedActivityTypes
message and airDrop do not show, but WhatsApp and IFTTT still show.
I have tested with
activityVC.completionWithItemsHandler = { (activity, success, modifiedItems, error) in
print("activity: \(activity), success: \(success), items: \(modifiedItems), error: \(error)")
}
that WhatsApp and IFTTT services are effectively the ones listed here.
When selecting WhatsApp, print above gives:
activity: Optional(__C.UIActivityType(_rawValue: net.whatsapp.WhatsApp.ShareExtension)), success: false, items: nil, error: nil
When testing in simulator with Xcode 13, I noted a subtle difference in the display of WKInterfaceLabel between Watch series 6 and series 7.
WKInterfaceLabel is in a WKInterfaceGroup.
On Series 7: the text Fast Driving is clipped with round corner at top and bottom
On Series 6, round clipping is much less (noticeable on leading F and D)
I could not find what parameter has changed in IB nor how to change this round corner value. Nor why such a change ?
UISegmented controls seem not to work correctly in iPhone 13 Mini simulator. When tapping on a segment, control does not react before 30 to 40 s ; then it shows uncomplete redraw:
I also noted similar lag in updating display when some label text changes.
Configuration:
MacOS 11.6.1
Xcode 13RC
iOS 15.0 simulator.
It works ok on a few other simulators I tested.
I created an extremely simple project to reproduce:
new project in Xcode 13RC
added a segmentedControl at bottom of view, constrained to leading and trailing 0 to the safe area
set selected color to red.
run on iPhone 13 mini simulator
I will test later with Xcode 13.2ß
The following code opens the app settings, including preferred language.
func openSettings() {
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: nil)
}
}
That works well in iOS (14.6 or 15.2), on iPadOS 14.4 ( both device and simulator)
But on iPadOS 15.2 simulator, the preferred language setting for the app does not show.
I noticed this in 2 different apps.