macOS availableMetadataObjectTypes is empty - swift

I'm experimenting a bit on what I can do with the Mac camera.
Then, with AVCaptureMetadataOutput, I noticed that availableMetadataObjectTypes always returned an empty array.
But according to the documentation, all types are compatible with macOS?
I can not find the error, why it is an empty array?
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(captureMetadataOutput)
captureMetadataOutput.setMetadataObjectsDelegate(delegate, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = captureMetadataOutput.availableMetadataObjectTypes
print(captureMetadataOutput.availableMetadataObjectTypes)

Related

XCTKVOExpectation times out even though element exists

I am using swift, xcode 8.3.3, and XCTest. I am trying to wait for an element to exist on the screen using XCTKVOExpectation. It is always returning the result of timedout (2) even though the element exists.
Here is my code:
func waitForElementToAppear(element: XCUIElement) -> Bool {
let expectation = XCTKVOExpectation(keyPath: "exists", object: element,
expectedValue: true)
let result = XCTWaiter().wait(for: [expectation], timeout: 10)
print(element.exists)
print(result.rawValue)
return result == .completed
}
When I print element.exists, it prints true. However the result.rawValue is 2 (.timedout) Increasing the timeout value did not resolve this either.
I am able to successfully use XCTNSPredicateExpectation:
let myPredicate = NSPredicate(format: "exists == true")
let myExpectation = XCTNSPredicateExpectation(predicate: myPredicate,
object: element)
let result = XCTWaiter().wait(for: [myExpectation], timeout: 10)
return result == .completed
Wondering why XCTKVOExpectation doesn't work though?
Not really an answer, but I've been seeing this in Xcode 9.3.1 as well. The exact same predicate combination works well elsewhere in many places but one in particular almost always times out.
I've worked around it for now by checking whether the object exists before issuing the wait, and then also "result == XCTWaiterResultCompleted || object.exists" (Objective C).
I'd love to know if this is a bug or am I doing something wrong?
I was having the same problem with my own code. I was able to get the KVO change to trigger using didChangeValue(forKey: "keyValuePath").
Since XCTKVOExpectation accepts a String for the key path instead of a KeyPath, paired with needing to call didChangeValue(forKey: "keyValuePath"), it seems XCTKVOExpectation is not meant to work with Swift and is more of a legacy objc object. I just don't think this is going to work in Swift

Cannot get value from Accelerometer, Gyro and DeviceMotion

I'm making an app to track your sleep by getting any movement of the iPhone. I searched everywhere and there are many ways you can get data from this but non worked. Here's my code.
func startManager() {
let manager = CMMotionManager()
manager.startAccelerometerUpdates()
let accelerometer = manager.accelerometerData
}
But manager.accelerometerData is nil. I also tried it with DeviceMotion, Gyro and UserAcceleration, non of them worked. I also tried this.
print(manager.isAccelerometerActive)
It printed false so I think this is the problem but I still cannot make it active.
I tried putting the let manager = CMMotionManager() to the top and it still won't work.
I tried putting manager.startAccelerometerUpdates() in the ViewDidLoad and still doesn't work.
I also tried another way which is this.
manager.startAccelerometerUpdates(to: OperationQueue.main) { (data : CMAccelerometerData, error : Error) in
print(data)
}
but it gave me an error saying that I have to add as! CMAccelerometerHandler but after I added that it tell me to add it again.
I want to get raw value from the Accelerometer as x, y and z
(I imported CoreMotion)
I'm doing this using Swift 3 on XCode 8.2.1 and testing it on iPhone 6s.
In Swift3, you should use optional parameters in the handler
motionManager.startAccelerometerUpdates(
to: OperationQueue.main ,
withHandler:{ (data : CMAccelerometerData?, error : Error?) in
print(data)
})

AV Foundation in relation to Camera issue

I am trying to be able to use a custom camera, and I am converting code from swift 2 to swift 3; I am pretty much complete; but I am getting this error in relation to devices; I want to have a rear and front facing camera and before in swift 2 you would set the devices like so:
let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as! [AVCaptureDevice]
now I am using what xcode is telling me to use which is:
let devices = AVCaptureDeviceDiscoverySession(deviceTypes: [AVCaptureDevice], mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition)
but i am getting this error
cannot convert value of type 'AVCaptureDevice.type' to expected argument type '[AVCaptureDeviceType]'
For the deviceTypes parameter you need to pass in an array of one or more AVCaptureDeviceType's. Your choices are:
builtInMicrophone
builtInWideAngleCamera
builtInTelephotoCamera
builtInDualCamera
See here for more information on these constants.
With that said, you are probably looking for something like:
let devices = AVCaptureDeviceDiscoverySession(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera, AVCaptureDeviceType.builtInTelephotoCamera], mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition.unspecified)

Using NSSpeechStatusNumberOfCharactersLeft to update a progress indicator for NSSpeechSynthesizer

I'm new to Swift and OS X programming. I'm trying to use a progress monitor to indicate the progress of my speech synthesizer speaking text.
let speechSynthesizer = NSSpeechSynthesizer()
speechSynthesizer.delegate = self;
speechSynthesizer.startSpeakingString(contents)
I would like to set
progressIndicator.maxValue = Double(NSSpeechStatusNumberOfCharactersLeft.characters.count)
and then periodically update the progressIndicator with NSSpeechStatusNumberOfCharactersLeft, which according to Apple's documentation should hit 0.
Every way I try to access this key, it returns the same inaccurate number, so I'm obviously not using it correctly. The only example I found was in Objective-C
NSNumber *n = [[self.speechSynth objectForProperty:NSSpeechStatusProperty error:NULL] objectForKey:NSSpeechStatusNumberOfCharactersLeft];
and I tried to translate that to Swift, but still, no dice.
let count = try speechSynthesizer.objectForProperty(NSSpeechStatusProperty).objectForKey(NSSpeechStatusNumberOfCharactersLeft)
I've also tried
speechSynthesizer.valueForKey(NSSpeechStatusNumberOfCharactersLeft))
speechSynthesizer.valueWithName(NSSpeechStatusNumberOfCharactersLeft, inPropertyWithKey: NSSpeechStatusProperty))
which throw runtime exceptions. Any thoughts? Thanks in advance!
Your second attempt is pretty close to correct:
let count = try speechSynthesizer.objectForProperty(NSSpeechStatusProperty).objectForKey(NSSpeechStatusNumberOfCharactersLeft)
Without an error message (and since I don't have a Swift 2 compiler handy) I'm guessing the reason that this fails is that the return value of objectForProperty isn't known to be an dictionary, so you can't look up values in it.
Here's my quick & dirty Swift 3 playground for testing this:
import PlaygroundSupport
import Cocoa
let synth = NSSpeechSynthesizer()
synth.startSpeaking("I'm not standing still, I am lying in wait")
// quick way to test for progress without setting up an app and delegate
PlaygroundPage.current.needsIndefiniteExecution = true
let timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
let statusDict = try! synth.object(forProperty: NSSpeechStatusProperty) as! [String: Any]
print(statusDict[NSSpeechStatusNumberOfCharactersLeft])
}
(Obviously, you don't need all the timer stuff or playground business if you're running this in an app with a synthesizer delegate.)
The key bit (no pun intended) is to cast the return value of objectForProperty so that Swift knows it's a dictionary, then look up the number of characters in that dictionary.
Now, this code runs correctly, but it doesn't completely work for setting a progress bar — when the synthesizer finishes speaking, NSSpeechStatusNumberOfCharactersLeft is likely to be some nonzero value. (In that case, another status key, NSSpeechStatusOutputBusy will become false.) So your progress bar will get to not quite 100%, and you can use either the NSSpeechStatusOutputBusy key or the delegate didFinishSpeaking callback to take your bar the rest of the way, remove your progress UI, or whatever.

Ambiguous use of a subscript when accessing a 2-dimensional array bridged from Obj-C

This code which ran perfectly in Xcode 7.0 now complains with a error : Ambiguous use of a subscript in Xcode 7.3.1 on the second line.
let ar = sender.draggingPasteboard().propertyListForType("ABLinkedPeopleUIDsPboardType") as! NSArray?
let uniqueID = ar![0][0] as! String
I understand that the NSArray on its own is now considered bad practice, but what do I need to do to get this to compile and run?
NSArray is a single-dimensioned array, but you're trying to use it as a two-dimensional array. I can't see how this would ever compile.
You need to translate into Swift types immediately so you can continue programming in Swift, not go adrift in a sea of force-unwrapped Optionals.
How about:
if let ar = sender.draggingPasteboard().propertyListForType("ABLinkedPeopleUIDsPboardType") as? [[String]] {
// I'm assuming you're expecting to get back a two-dimensional array of Strings, or in the Obj-C realm, an NSArray of NSArrays of NSStrings
let uniqueID = ar[0][0]
}
else {
print("Property List for ABLinkedetc. is not a 2D String Array!")
}
Hayden's link is the correct general discussion but if you're new to bridging Obj C to Swift it may be difficult to apply in your particular case.