alert view automatically dismissed in ios13 in appdelegate and its working fine in ios11 - ios13

alert view automatically dismissed ios13 in appdelegate and its working fine in ios11 and issue happened only with ios13
let alertController = UIAlertController (title: "messageTitle", message:"notificationMessage", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Close", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindow.Level.alert + 1;
alertWindow.makeKeyAndVisible()
alertController.modalPresentationStyle = .fullScreen
alertWindow.rootViewController?.present(alertController, animated: true, completion: nil)

If you create new UIWindow, you should hold it like a property because "alertWindow" will be destroyed in the end of the method where it was created. Another case you can get the window guard let window = UIApplication.shared.keyWindow else { return } and use it.

Related

Elm with webcomponents - Is this a bug or am I doing something wrong?

Problem summary
I am using webcomponents in elm 0.19.1.
Goal is for the webcomponent to emit an event if the webcomponent attribute "requeststate" changes.
The event is emitted (I can see in the the logging in the webcomponent constructor), but elm is not firing the 'WebcomponentEvent' correctly.
Problem is on both windows 10 and ubuntu 16.04, firefox and chrome.
Didnot test older elm versions.
Steps to reproduce:
I have the problem reproduced in this minimal repo:
https://github.com/Derryrover/elm_webcom_bug
Compile elm with:
elm make src/Main.elm --output elm.js --debug
use a webserver (for example 'serve') to host locally
click the button 'request'. This will change the attribute 'requeststate' on the webcomponent. That in turn triggers the custom event 'created' on the webcomponent. But elm does not receive this event..
Opening the elm-debugger or clicking the 'request' button again will magically make the event fire in elm. Strange.
Also I have made the branch 'tom-experiment'. In this branch I got the event from webcomponent-click working, but only if I directly click on the webcomponent itself.
The importance of this problem
Why do I want to trigger an event on a webcomponent by changing an attribute?
Goal of this approach is also JavaScript interop.
For example I can now use this webcomponent to create a date-time or uuid or do some other javascript magic. This way I can work around ports completely.
A solution for this problem might settle the entire Javascript interop discussion !
Code
This is my Main.elm:
module Main exposing (..)
import Browser
import Html
import Html.Attributes
import Html.Events
import Json.Decode
main =
Browser.sandbox
{ init = init
, view = view
, update = update
}
type alias Model =
{ request : Bool
, received: Bool
}
init : Model
init = { request = False
, received = False
}
type Msg
= Request
| Reset
| WebcomponentEvent
update : Msg -> Model -> Model
update msg model =
case msg of
WebcomponentEvent ->
{ model | received = True}
Request ->
{ model | request = True }
Reset ->
{ model | request = False , received = False}
view : Model -> Html.Html Msg
view model =
Html.div []
[ Html.button [Html.Events.onClick Request] [Html.text "Request"]
, Html.div
[]
[ Html.text "requested:"
, Html.text (if model.request then "true" else "false")
]
, Html.div
[]
[ Html.text "received:"
, Html.text (if model.received then "true" else "false")
]
, Html.button [Html.Events.onClick Reset] [Html.text "Reset"]
, Html.node "webcomponent-test"
[ Html.Events.on "created" (Json.Decode.succeed WebcomponentEvent)
, Html.Attributes.attribute "requeststate" (if model.request == True then "requested" else "idle")
] []
]
This is the webcomponent.js
class Webcomponent extends HTMLElement {
static get observedAttributes() {
return [
"requeststate"
];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "requeststate":
if (newValue === "requested") {
console.log(`requested in webcomponent triggered`);
const customEvent = new CustomEvent('created', {detail: ""});
this.dispatchEvent(customEvent);
}
}
}
constructor() {
super();
this.addEventListener('created', function (e) {
console.log("event triggered as sensed by javascript: ", e.detail, e);
}, false, true);
}
}
customElements.define('webcomponent-test', Webcomponent);
this is my index.html
<!doctype html>
<html>
<head>
<script type="module" src="./webcomponent.js"></script>
<script src="./elm.js"></script>
</head>
<body>
<div id="elm_element"></div>
<script>
var app = Elm.Main.init({
node: document.getElementById('elm_element')
});
</script>
</body>
</html>
This was discussed on the Elm Slack. The issue ended up being a timing issue. The resolution is to change from
this.dispatchEvent(customEvent)
to
requestAnimationFrame(() => this.dispatchEvent(customEvent))
in the custom element, as can be seen in this ellie https://ellie-app.com/cqGkT6xgwqKa1.
Thanks to #antew for the final solution.
There is another potential cause:
This attributeChangedCallback runs before the element is connected to the DOM
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "requeststate":
if (newValue === "requested") {
console.log(`requested in webcomponent triggered`);
const customEvent = new CustomEvent('created', {detail: ""});
this.dispatchEvent(customEvent);
}
}
}
Add
connectedCallback(){
console.log("Now I am ready to emit Events");
}
to verify your dispatchEvent doesn't run too soon.
requestAnimationFrame (or setTimeout) are workarounds to wait till the Event Loop is empty (and thus connectedCallback ran)
(I don't know your use case) You could also test for oldValue === null or this.isConnected in your attributeChangedCallback
Also note you probably need bubbles:true and composed:true on that CustomEvent when shadowDOM is involved.

UIImagePickerController and PHPickerViewController image selection blank in iOS14

Had this working on the last few versions of iOS but on 14 cannot get this to work, I have spent the past 5 days Googling.
Whenever I go to add an image from the gallery the popup to select an image is blank.
I have tried UIImagePickerController(which works fine iOS13 and below) and the new PHPickerViewController.
What has been working up until iOS14 is the user clicks a bar button to "add image" and the pop up asks to pick from the gallery and then presents the picker with images in your gallery.
I have set the Info.plist "Privacy - Photo Library Usage Description" for UIImagePickerController, I know the PHPickerViewController doesn't need perms as it handles getting the image for you.
I have also been seeing these purple warning now and again saying "xxxx must be used from main thread only", never seen that before until the new Xcode.
Any help would be much appreciated. Running Xcode 12.0.1 (12A7300), simulators running iOS14.
Adam
class AddCustomExerciseViewController: UIViewController, UITextViewDelegate, UINavigationControllerDelegate, GADBannerViewDelegate, UIImagePickerControllerDelegate, PHPickerViewControllerDelegate{
let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in self.openGallery() }))
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
func openGallery()
{
let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
switch photoAuthorizationStatus {
case .authorized:
self.showGallery()
print("Access is granted by user")
case .notDetermined:
PHPhotoLibrary.requestAuthorization({
(newStatus) in
print("status is \(newStatus)")
if newStatus == PHAuthorizationStatus.authorized {
self.showGallery()
print("success")
}
})
print("It is not determined until now")
case .restricted:
// same same
print("User do not have access to photo album.")
case .denied:
// same same
print("User has denied the permission.")
case .limited:
// same same
print("User has denied the permission.")
}
}
func showGallery()
{
if #available(iOS 14, *)
{
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 0
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
self.present(picker, animated: true, completion: nil)
}
else
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = false
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
//get the file url
if let fileUrl = info[UIImagePickerControllerImageURL] as? URL {
print(fileUrl)
print(fileUrl.lastPathComponent)
let filePath = fileUrl.lastPathComponent
if(filePath.hasSuffix("GIF")||filePath.hasSuffix("gif"))
{
//to change later to support gifs
gifView.image = pickedImage
}
else
{
//to show the static image to users
gifView.image = pickedImage
}
//for saving the file name to retrieve in local parse datastore
imageNameToSave = fileUrl.lastPathComponent
}
//for saving the selected image
imageToSave = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
#available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
{
picker.dismiss(animated: true, completion: nil)
for result in results
{
result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { (object, error) in
if let image = object as? UIImage {
DispatchQueue.main.async {
// Use UIImage
print("Selected image: \(image)")
}
}
})
}
} }
On iOS 14 the restricted image picker permission dialog opens in a separate thread, so when the authorization return you will need to perform UI tasks on main thread.
PHPhotoLibrary.requestAuthorization({
(newStatus) in
DispatchQueue.main.async {
print("status is \(newStatus)")
if newStatus == PHAuthorizationStatus.authorized {
self.showGallery()
print("success")
}
}
})
If this is helpful for anyone else I discovered that editing the scrollview appearance proxy background caused a bug in both the UIImagePickerController and the PHPickerViewController preventing them from showing images in iOS 14 and above. I had edited the scrollview background proxy because it is black even in light mode. After hours of googling and testing I discovered that removing the appearance background modification on the scrollview proxy allowed the image pickers to function as expected. I filed a bug report with Apple. The line of code that caused the bug was:
UIScrollView.appearance().backgroundColor = .systemBackground

App crashed on iOS 13, after switching rootviewcontroller

Application runs fine on iOS 12. But crashed on iOS 13.1. I think the issue is in the setting root view controller.
let storyboard = UIStoryboard(name: storyBoard, bundle: nil)
let desiredViewController = storyboard.instantiateViewController(withIdentifier: identifier);
self.window?.switchRootViewController(desiredViewController,animated: animate,options:options)
and the extension is:
extension UIWindow {
func switchRootViewController(_ viewController: UIViewController, animated: Bool = true, duration: TimeInterval = 0.3, options: UIView.AnimationOptions = .transitionFlipFromRight, completion: (() -> Void)? = nil) {
guard animated else {
rootViewController = viewController
return
}
UIView.transition(with: self, duration: duration, options: options, animations: {
let oldState = UIView.areAnimationsEnabled
UIView.setAnimationsEnabled(false)
self.rootViewController = viewController
UIView.setAnimationsEnabled(oldState)
}) { _ in
completion?()
}
}
}

SwiftUI: how to handle BOTH tap & long press of button?

I have a button in SwiftUI and I would like to be able to have a different action for "tap button" (normal click/tap) and "long press".
Is that possible in SwiftUI?
Here is the simple code for the button I have now (handles only the "normal" tap/touch case).
Button(action: {self.BLEinfo.startScan() }) {
Text("Scan")
} .disabled(self.BLEinfo.isScanning)
I already tried to add a "longPress gesture" but it still only "executes" the "normal/short" click. This was the code I tried:
Button(action: {self.BLEinfo.startScan() }) {
Text("Scan")
.fontWeight(.regular)
.font(.body)
.gesture(
LongPressGesture(minimumDuration: 2)
.onEnded { _ in
print("Pressed!")
}
)
}
Thanks!
Gerard
I tried many things but finally I did something like this:
Button(action: {
}) {
VStack {
Image(self.imageName)
.resizable()
.onTapGesture {
self.action(false)
}
.onLongPressGesture(minimumDuration: 0.1) {
self.action(true)
}
}
}
It is still a button with effects but short and long press are different.
Combining a high priority gesture and a simultaneous gesture should do the trick.
Button(action: {})
{
Text("A Button")
}
.simultaneousGesture(
LongPressGesture()
.onEnded { _ in
print("Loooong")
}
)
.highPriorityGesture(TapGesture()
.onEnded { _ in
print("Tap")
})
Found this a handy pattern when interacting with other views as well.
I just discovered that the effect depends on the order of the implementation. Implementing the detection of gestures in the following order it seems to be possible to detect and identify all three gestures:
handle a double tap gesture
handle a longPressGesture
handle a single tap gesture
Tested on Xcode Version 11.3.1 (11C504)
fileprivate func myView(_ height: CGFloat, _ width: CGFloat) -> some View {
return self.textLabel(height: height, width: width)
.frame(width: width, height: height)
.onTapGesture(count: 2) {
self.action(2)
}
.onLongPressGesture {
self.action(3)
}
.onTapGesture(count: 1) {
self.action(1)
}
}
Here is my implementation using a modifier:
struct TapAndLongPressModifier: ViewModifier {
#State private var isLongPressing = false
let tapAction: (()->())
let longPressAction: (()->())
func body(content: Content) -> some View {
content
.scaleEffect(isLongPressing ? 0.95 : 1.0)
.onLongPressGesture(minimumDuration: 1.0, pressing: { (isPressing) in
withAnimation {
isLongPressing = isPressing
print(isPressing)
}
}, perform: {
longPressAction()
})
.simultaneousGesture(
TapGesture()
.onEnded { _ in
tapAction()
}
)
}
}
Use it like this on any view:
.modifier(TapAndLongPressModifier(tapAction: { <tap action> },
longPressAction: { <long press action> }))
It just mimics the look a button by scaling the view down a bit. You can put any other effect you want after scaleEffect to make it look how you want when pressed.
I had to do this for an app I am building, so just wanted to share. Refer code at the bottom, it is relatively self explanatory and sticks within the main elements of SwiftUI.
The main differences between this answer and the ones above is that this allows for updating the button's background color depending on state and also covers the use case of wanting the action of the long press to occur once the finger is lifted and not when the time threshold is passed.
As noted by others, I was unable to directly apply gestures to the Button and had to apply them to the Text View inside it. This has the unfortunate side-effect of reducing the 'hitbox' of the button, if I pressed near the edges of the button, the gesture would not fire. Accordingly I removed the Button and focused on manipulating my Text View object directly (this can be replaced with Image View, or other views (but not Button!)).
The below code sets up three gestures:
A LongPressGesture that fires immediately and reflects the 'tap' gesture in your question (I haven't tested but this may be able to replaced with the TapGesture)
Another LongPressGesture that has a minimum duration of 0.25 and reflect the 'long press' gesture in your question
A drag gesture with minimum distance of 0 to allow us to do events at the end of our fingers lifting from the button and not automatically at 0.25 seconds (you can remove this if this is not your use case). You can read more about this here: How do you detect a SwiftUI touchDown event with no movement or duration?
We sequence the gestures as follows: Use 'Exclusively' to combine the "Long Press" (i.e. 2 & 3 above combined) and Tap (first gesture above), and if the 0.25 second threshold for "Long Press" is not reached, the tap gesture is executed. The "Long Press" itself is a sequence of our long press gesture and our drag gesture so that the action is only performed once our finger is lifted up.
I also added code in the below for updating the button's colours depending on the state. One small thing to note is that I had to add code on the button's colour into the onEnded parts of the long press and drag gesture because the minuscule processing time would unfortunately result in the button switching back to darkButton colour between the longPressGesture and the DragGesture (which should not happen theoretically, unless I have a bug somewhere!).
You can read more here about Gestures: https://developer.apple.com/documentation/swiftui/gestures/composing_swiftui_gestures
If you modify the below and pay attention to Apple's notes on Gestures (also this answer was useful reading: How to fire event handler when the user STOPS a Long Press Gesture in SwiftUI?) you should be able to set up complex customised button interactions. Use the gestures as building blocks and combine them to remove any deficiency within individual gestures (e.g. longPressGesture does not have an option to do the events at its end and not when the condition is reached).
P.S. I have a global environment object 'dataRouter' (which is unrelated to the question, and just how I choose to share parameters across my swift views), which you can safely edit out.
struct AdvanceButton: View {
#EnvironmentObject var dataRouter: DataRouter
#State var width: CGFloat
#State var height: CGFloat
#State var bgColor: Color
#GestureState var longPress = false
#GestureState var longDrag = false
var body: some View {
let longPressGestureDelay = DragGesture(minimumDistance: 0)
.updating($longDrag) { currentstate, gestureState, transaction in
gestureState = true
}
.onEnded { value in
print(value.translation) // We can use value.translation to see how far away our finger moved and accordingly cancel the action (code not shown here)
print("long press action goes here")
self.bgColor = self.dataRouter.darkButton
}
let shortPressGesture = LongPressGesture(minimumDuration: 0)
.onEnded { _ in
print("short press goes here")
}
let longTapGesture = LongPressGesture(minimumDuration: 0.25)
.updating($longPress) { currentstate, gestureState, transaction in
gestureState = true
}
.onEnded { _ in
self.bgColor = self.dataRouter.lightButton
}
let tapBeforeLongGestures = longTapGesture.sequenced(before:longPressGestureDelay).exclusively(before: shortPressGesture)
return
Text("9")
.font(self.dataRouter.fontStyle)
.foregroundColor(self.dataRouter.darkButtonText)
.frame(width: width, height: height)
.background(self.longPress ? self.dataRouter.lightButton : (self.longDrag ? self.dataRouter.brightButton : self.bgColor))
.cornerRadius(15)
.gesture(tapBeforeLongGestures)
}
}
This isn't tested, but you can try to add a LongPressGesture to your button.
It'll presumably look something like this.
struct ContentView: View {
#GestureState var isLongPressed = false
var body: some View {
let longPress = LongPressGesture()
.updating($isLongPressed) { value, state, transaction in
state = value
}
return Button(/*...*/)
.gesture(longPress)
}
}
Kevin's answer was the closest to what I needed. Since ordering the longPressGesture before the tapGesture broke ScrollViews for me, but the inverse made the minimumDuration parameter do nothing, I implemented the long press functionality myself:
struct TapAndLongPressModifier: ViewModifier {
#State private var canTap = false
#State private var pressId = 0
let tapAction: (()->())
let longPressAction: (()->())
var minimumDuration = 1.0
func body(content: Content) -> some View {
content
.onTapGesture {
if canTap {
tapAction()
}
}
.onLongPressGesture(
minimumDuration: 1.0,
pressing: { (isPressing) in
pressId += 1
canTap = isPressing
if isPressing {
let thisId = pressId
DispatchQueue.main.asyncAfter(deadline: .now() + minimumDuration) {
if thisId == pressId {
canTap = false
longPressAction()
}
}
}
},
// We won't actually use this
perform: {}
)
}
}
just do this:
the first modifier should be onLongPressGesture(minumumDuration: (the duration you want))
and the following mondifier should be onLongPressGesture(minimumDuration: 0.01) <- or some other super small numbers
this works for me perfectly
As a follow up, I had the same issue and I tried all of these answers but didn't like how they all worked.
I ended up using a .contextMenu it was way easier and produces pretty much the same effect.
Check link here
and here is an example
UPDATE:
As of iOS 16, .contextMenu has been depreciated. So I ended up using .simultaneousGesture on the Button, not the content in the button's label block.
i.e.
Button {
// handle Button Tap
} label: {
// button label content here
}
.simultaneousGesture(LongPressGesture()
.onEnded { _ in
// handle long press here
}
)
This still preserves the button animations as well.
Note tested before iOS 16 however.
Thought I'd post back on this, in case anyone else is struggling. Strange that Apple's default behaviour works on most controls but not buttons. In my case I wanted to keep button effects while supporting long press.
An approach that works without too much complexity is to ignore the default button action and create a simultaneous gesture that handles both normal and long clicks.
In your view you can apply a custom long press modifier like this:
var body: some View {
// Apply the modifier
Button(action: self.onReloadDefaultAction) {
Text("Reload")
}
.modifier(LongPressModifier(
isDisabled: self.sessionButtonsDisabled,
completionHandler: self.onReloadPressed))
}
// Ignore the default click
private func onReloadDefaultAction() {
}
// Handle the simultaneous gesture
private func onReloadPressed(isLongPress: Bool) {
// Do the work here
}
My long press modifier implementation looked like this and uses the drag gesture that I found from another post. Not very intuitive but it works reliably, though of course I would prefer not to have to code this plumbing myself.
struct LongPressModifier: ViewModifier {
// Mutable state
#State private var startTime: Date?
// Properties
private let isDisabled: Bool
private let longPressSeconds: Double
private let completionHandler: (Bool) -> Void
// Initialise long press behaviour to 2 seconds
init(isDisabled: Bool, completionHandler: #escaping (Bool) -> Void) {
self.isDisabled = isDisabled
self.longPressSeconds = 2.0
self.completionHandler = completionHandler
}
// Capture the start and end times
func body(content: Content) -> some View {
content.simultaneousGesture(DragGesture(minimumDistance: 0)
.onChanged { _ in
if self.isDisabled {
return
}
// Record the start time at the time we are clicked
if self.startTime == nil {
self.startTime = Date()
}
}
.onEnded { _ in
if self.isDisabled {
return
}
// Measure the time elapsed and reset
let endTime = Date()
let interval = self.startTime!.distance(to: endTime)
self.startTime = nil
// Return a boolean indicating whether a normal or long press
let isLongPress = !interval.isLess(than: self.longPressSeconds)
self.completionHandler(isLongPress)
})
}
}
Try this :)
Handles isInactive, isPressing, isLongPress and Tap(Click)
based on this
I tried to make this as a viewmodifier without success. I would like to see an example with #GestureState variable wrapper used in same manner as #State/#Published are bound to #Binding in view components.
Tested: Xcode 12.0 beta, macOS Big Sur 11.0 beta
import SwiftUI
enum PressState {
case inactive
case pressing
case longPress
var isPressing: Bool {
switch self {
case .inactive:
return false
case .pressing, .longPress:
return true
}
}
var isLongPress: Bool {
switch self {
case .inactive, .pressing:
return false
case .longPress:
return true
}
}
var isInactive : Bool {
switch self {
case .inactive:
return true
case .pressing, .longPress:
return false
}
}
}
struct ContentView: View {
#GestureState private var pressState: PressState = PressState.inactive
#State var showClick: Bool = false
var press: some Gesture {
LongPressGesture(minimumDuration: 0.8, maximumDistance: 50.0)
.sequenced(before: LongPressGesture(minimumDuration: .infinity, maximumDistance: 50.0))
.updating($pressState) { value, state, transaction in
switch value {
case .first(true): // first gesture starts
state = PressState.pressing
case .second(true, nil): // first ends, second starts
state = PressState.longPress
default: break
}
}
}
var body: some View {
ZStack{
Group {
Text("Click")
.offset(x: 0, y: pressState.isPressing ? (pressState.isLongPress ? -120 : -100) : -40)
.animation(Animation.linear(duration: 0.5))
.opacity(showClick ? 1 : 0 )
.animation(Animation.linear(duration: 0.3))
Text("Pressing")
.opacity(pressState.isPressing ? 1 : 0 )
.offset(x: 0, y: pressState.isPressing ? (pressState.isLongPress ? -100 : -80) : -20)
.animation(Animation.linear(duration: 0.5))
Text("Long press")
.opacity(pressState.isLongPress ? 1 : 0 )
.offset(x: 0, y: pressState.isLongPress ? -80 : 0)
.animation(Animation.linear(duration: 0.5))
}
Group{
Image(systemName: pressState.isLongPress ? "face.smiling.fill" : (pressState.isPressing ? "circle.fill" : "circle"))
.offset(x: 0, y: -100)
.font(.system(size: 60))
.opacity(pressState.isLongPress ? 1 : (pressState.isPressing ? 0.6 : 0.2))
.foregroundColor(pressState.isLongPress ? .orange : (pressState.isPressing ? .yellow : .white))
.rotationEffect(.degrees(pressState.isLongPress ? 360 : 0), anchor: .center)
.animation(Animation.linear(duration: 1))
Button(action: {
showClick = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
self.showClick = false
})
}, label: {
ZStack {
Circle()
.fill(self.pressState.isPressing ? Color.blue : Color.orange)
.frame(width: 100, height: 100, alignment: .center)
Text("touch me")
}}).simultaneousGesture(press)
}.offset(x: 0, y: 110)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

UIIMagePickerController not working properly with Swift 3

I'm getting crazy with this.
While migrating a simple UIIMagePicker implementation I have everything working properly , no issues, no warning.
Running on both simulator and device the PickerController just don't take into consideration the new image and won't apply to the UImageView.
This is my code:
#IBOutlet weak var profilePictureImageView: UIImageView!
let picker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
}
//Opening Camera to take a new picture
#IBAction func takeNewPictureButtonDidTouch(_ sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = .photo
picker.modalPresentationStyle = .fullScreen
present(picker,animated: true,completion: nil)
} else {
noCamera()
}
}
//Opening the library to select an existing picture
#IBAction func openPicturesLibraryButtonDidTouch(_ sender: AnyObject) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
picker.modalPresentationStyle = .popover
present(picker, animated: true, completion: nil)
}
//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : AnyObject])
{
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage //2
profilePictureImageView.contentMode = .scaleAspectFill //3
profilePictureImageView.image = chosenImage //4
dismiss(animated:true, completion: nil) //5
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func noCamera(){
let alertVC = UIAlertController(
title: "No Camera",
message: "Sorry, this device has no camera",
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style:.default,
handler: nil)
alertVC.addAction(okAction)
present(
alertVC,
animated: true,
completion: nil)
}
}
set delegate to self in viewdidload

Resources