A further update after getting some analytics around this into our app:
It isn't related to the adaptive true-tone flash, rather it occurs on any device with dual ambient light sensors.
We still believe it's only an iOS 18 issue, but may also be present on iOS 18.0.1
The issue is not yet resolved on iOS 18.2 beta
Post
Replies
Boosts
Views
Activity
Just an update on this, another way to fix it is to setup an AVCaptureDeviceInput and AVCaptureVideoDataOutput, attach them to an AVCaptureSession and call startRunning on the session.
Presumably this limits the changes to the torch so it can be used as a camera flash more effectively.
A less than ideal solution, as it will involve hand-holding of users to explain why we require camera permission, and will potentially also be picked up on by the review team too!
Hi Albert,
Thanks for your quick reply! I have to say I was half expecting this to be the answer, but a small part of me hoped it would not be the case.
It makes so much sense to have these controls for external cameras too, in particular I have a "full screen" mode in my app, and being able to use the camera control button whilst in that mode for configuring things such as shutter speed, ISO, aperture, and for actuating the shutter would make it such a better user experience! Instead users have to jump in and out of full screen mode to adjust any of these shooting settings.
They are not particularly creative ways as far as I can see, they will just allow a more seamless interaction with the external camera over WiFi, make the shooting experience less cluttered, and allow users to use more of the screen real-estate for composition!
I have submitted an enhancement under FB15100641 requesting this.
I do have a further question, do you know how much of the AVCaptureSession process I would need to do in order to open up this functionality? And how much draw that would have on CPU and memory usage? I am half tempted to setup an AVCaptureDevice but just not render it in a preview layer in order to open up this functionality. Perhaps too you could speak as to whether that would lead to rejection at the review process stage? Perhaps there's someone I could speak to at Apple regarding this, to get it pre-approved or at least have a discussion around it?
Simon
Hi Andrea, curious if you had any luck or a play around with this option? I've just discovered it myself, I'm scheduling a new connection in a similar way to you but also wondering if this is a better option!
All the best,
Simon
Did anyone ever get any intent donations to show? Having the same issue on debug builds, about to get a build into TestFlight but @Gong it looks from your comment that you haven't seen any actions donated at all for a whole year even with app live on the store!? Did you ever get to the bottom of it? I'm wondering about submitting an TSI request...
Have tried to replicate this with a simple example using a UISlider and UIViewPropertyAnimator and can't replicate, so I think it might be something to do with custom transitions, here is the code for that:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let purchaseDetailVC = transitionContext.viewController(forKey: .to) as? PurchaseDetailViewController,
let purchaseDetailView = transitionContext.view(forKey: .to) else {
return
}
let toFrame = transitionContext.finalFrame(for: purchaseDetailVC)
let dismissButton = UIButton()
dismissButton.setBackgroundImage( imageLiteral(resourceName: "icon-close"), for: .normal)
dismissButton.translatesAutoresizingMaskIntoConstraints = false
let cardView: PurchaseView = PurchaseView(frame: .zero)
cardView.translatesAutoresizingMaskIntoConstraints = false
cardView.purchasable = fromCell.purchaseView.purchasable
cardView.buyButtonState = fromCell.purchaseView.buyButtonState
cardView.buyButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .title3).withWeight(.medium)
cardView.addSubview(dismissButton)
let buttonConstraints = [
dismissButton.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 20),
dismissButton.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -20)
]
NSLayoutConstraint.activate(buttonConstraints)
let detailBGView = UIView(frame: .zero)
detailBGView.translatesAutoresizingMaskIntoConstraints = false
detailBGView.backgroundColor = purchaseDetailVC.tableView.backgroundColor
// Card view constraints
containerView.addSubview(detailBGView)
let bgVerticalConstraint = detailBGView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor, constant: (fromFrame.height/2 + fromFrame.minY) - containerView.bounds.height/2)
let bgConstraints = [
bgVerticalConstraint,
detailBGView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor)
]
NSLayoutConstraint.activate(bgConstraints)
let bgWidthConstraint = detailBGView.widthAnchor.constraint(equalToConstant: fromFrame.width)
let bgHeightConstraint = detailBGView.heightAnchor.constraint(equalToConstant: fromFrame.height)
NSLayoutConstraint.activate([bgWidthConstraint, bgHeightConstraint])
containerView.addSubview(cardView)
let verticalConstraint = cardView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor, constant: (fromFrame.height/2 + fromFrame.minY) - containerView.bounds.height/2)
let cardConstraints = [
verticalConstraint,
cardView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor)
]
NSLayoutConstraint.activate(cardConstraints)
let cardWidthConstraint = cardView.widthAnchor.constraint(equalToConstant: fromFrame.width)
let cardHeightConstraint = cardView.heightAnchor.constraint(equalToConstant: fromFrame.height)
NSLayoutConstraint.activate([cardWidthConstraint, cardHeightConstraint])
cardView.cornerRadius = 12
cardView.cornerCurve = .continuous
detailBGView.cornerRadius = 12
detailBGView.cornerCurve = .continuous
fromCell.isHidden = true
fromCell.transform = .identity
containerView.layoutIfNeeded()
springAnimator.addAnimations {
bgVerticalConstraint.constant = toFrame.minY/2
verticalConstraint.constant = (purchaseDetailVC.headerHeight/2 - toFrame.height/2 + toFrame.minY/2)
cardView.topConstraint.constant = purchaseDetailVC.purchaseView.topConstraint.constant
containerView.layoutIfNeeded()
}
springAnimator.startAnimation()
let expandingAnimator = UIViewPropertyAnimator(duration: springAnimator.duration * 0.6, curve: .linear)
expandingAnimator.addAnimations {
cardView.containerView.borderWidth = 0.0
cardView.buyButton.style = .onDarkBackground
cardView.headlineHidden = true
cardWidthConstraint.constant = toFrame.width
cardHeightConstraint.constant = purchaseDetailVC.headerHeight
bgWidthConstraint.constant = toFrame.width
bgHeightConstraint.constant = toFrame.height
// Must use layer because using view var breaks this for some reason
cardView.layer.cornerRadius = 0.0
detailBGView.layer.cornerRadius = 0.0
containerView.layoutIfNeeded()
}
expandingAnimator.startAnimation()
springAnimator.addCompletion { (_) in
detailBGView.removeFromSuperview()
cardView.removeFromSuperview()
containerView.addSubview(purchaseDetailView)
let success = !transitionContext.transitionWasCancelled
transitionContext.completeTransition(success)
}
}
The UIPanGestureRecognizer is what drives the animation, via the UIViewProperty’s “fractionComplete” property.
Could all of you submit a feature request using Apple's feedback assistant if you haven't already with use-cases for this :) Lots of us have already, but the more the merrier!
Interferon that does seem to be the case! There are a lot of use holding out hope that Apple will add an API for local network permissions as it currently seems almost impossible to detect.
If you have a case where you'd like to know if your app doesn't have permission, can you describe it? Is this for using Bonjour, or a direct connection use case? Hi Frameworks engineer! I have an app in the store which is used to control Sony's line of mirrorless and point and shoot cameras. The whole app requires this permission:
We need to send UDP messages on the local network (rather, the camera's network) and receive them from the camera for device discovery.
Once the device is discovered to control it we need to setup a socket connection (PTP/IP control) or communicate with a http API on the camera's network.
All of this is an absolute nightmare if we have to factor in this new permission, especially as lots of these APIs send errors in different ways, and in some cases URLSession errors which don't even explicitly say that the issue is local network permissions as others have pointed out!
This is also a massive issue for my app which controls 3rd party hardware (Sony cameras to be specific). I cannot rely as someone else said on "Obsolete hints" as my app simply won't function without local network permissions. I have to send UDP discovery packets on the network (Won't work) and then control the cameras either by a socket connection (newer models) or over a local RESTful API (Won't work) once the user is connected. The errors that are returned by the APIs are simply not reliable enough or descriptive enough to get this working, we absolutely need a way to check this (Just as there is with EVERY other privacy setting).