{"id":2393,"date":"2021-12-19T14:24:34","date_gmt":"2021-12-19T19:24:34","guid":{"rendered":"https:\/\/michaelrowe01.com\/?p=2393"},"modified":"2022-12-15T06:46:01","modified_gmt":"2022-12-15T11:46:01","slug":"swiftui-fun-and-bugs","status":"publish","type":"post","link":"https:\/\/michaelrowe01.com\/index.php\/uncategorized\/swiftui-fun-and-bugs\/","title":{"rendered":"SwiftUI Fun and Bugs"},"content":{"rendered":"\n<p>Well I fixed the bug!  The issue was the sequence of the code sequence between the ContactPicker and VStack within the Navigation View.  I hadn&#8217;t realized that this was issue (Obviously).  Here&#8217;s a video of the real way it should work.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"2305\" style=\"aspect-ratio: 1581 \/ 2305;\" width=\"1581\" controls src=\"https:\/\/michaelrowe01.com\/wp-content\/uploads\/2021\/12\/Screen-Recording-2021-12-19-at-14.19.11.mov\"><\/video><\/figure>\n\n\n\n<p>As you can see the UI is now working as you would expect.  <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\n\/\/  AddNewRecipientView.swift\n\/\/  Card Tracker\n\/\/\n\/\/  Created by Michael Rowe on 1\/1\/21.\n\/\/  Copyright \u00a9 2021 Michael Rowe. All rights reserved.\n\/\/\n\nimport SwiftUI\nimport SwiftUIKit\nimport ContactsUI\nimport Contacts\nimport CoreData\n\n\/* Thanks to @rlong405 and @nigelgee for initial guidance in getting past the early issues. *\/\n\nstruct AddNewRecipientView: View {\n    @Environment(\\.managedObjectContext) var moc\n    @Environment(\\.presentationMode) var presentationMode\n\n    @State private var lastName: String = \"\"\n    @State private var firstName: String = \"\"\n    @State private var addressLine1: String = \"\"\n    @State private var addressLine2: String = \"\"\n    @State private var city: String = \"\"\n    @State private var state: String = \"\"\n    @State private var zip: String = \"\"\n    @State private var country: String = \"\"\n\n    @State var showPicker = false\n\n    init() {\n        let navBarApperance = UINavigationBarAppearance()\n        navBarApperance.largeTitleTextAttributes = &#91;\n            .foregroundColor: UIColor.systemGreen,\n            .font: UIFont(name: \"ArialRoundedMTBold\", size: 35)!]\n        navBarApperance.titleTextAttributes = &#91;\n            .foregroundColor: UIColor.systemGreen,\n            .font: UIFont(name: \"ArialRoundedMTBold\", size: 20)!]\n        UINavigationBar.appearance().standardAppearance = navBarApperance\n        UINavigationBar.appearance().scrollEdgeAppearance = navBarApperance\n        UINavigationBar.appearance().compactAppearance = navBarApperance\n    }\n\n    var body: some View {\n        NavigationView {\n            GeometryReader { geomtry in\n                ContactPicker(showPicker: $showPicker, onSelectContact: {contact in\n                    firstName = contact.givenName\n                    lastName = contact.familyName\n                    if contact.postalAddresses.count > 0 {\n                        if let addressString = (\n                            ((contact.postalAddresses&#91;0] as AnyObject).value(forKey: \"labelValuePair\")\n                             as AnyObject).value(forKey: \"value\"))\n                            as? CNPostalAddress {\n                            \/\/ swiftlint:disable:next line_length\n                            let mailAddress = CNPostalAddressFormatter.string(from: addressString, style: .mailingAddress)\n                            addressLine1 = \"\\(addressString.street)\"\n                            addressLine2 = \"\"\n                            city = \"\\(addressString.city)\"\n                            state = \"\\(addressString.state)\"\n                            zip = \"\\(addressString.postalCode)\"\n                            country = \"\\(addressString.country)\"\n                            print(\"Mail address is \\n\\(mailAddress)\")\n                        }\n                    } else {\n                        addressLine1 = \"No Address Provided\"\n                        addressLine2 = \"\"\n                        city = \"\"\n                        state = \"\"\n                        zip = \"\"\n                        country = \"\"\n                        print(\"No Address Provided\")\n                    }\n                    self.showPicker.toggle()\n                }, onCancel: nil)\n                VStack {\n                    Text(\"\")\n                    HStack {\n                        VStack(alignment: .leading) {\n                            TextField(\"First Name\", text: $firstName)\n                                .customTextField()\n                        }\n                        VStack(alignment: .leading) {\n                            TextField(\"Last Name\", text: $lastName)\n                                .customTextField()\n                        }\n                    }\n                    TextField(\"Address Line 1\", text: $addressLine1)\n                        .customTextField()\n                    TextField(\"Address Line 2\", text: $addressLine2)\n                        .customTextField()\n                    HStack {\n                        TextField(\"City\", text: $city)\n                            .customTextField()\n                            .frame(width: geomtry.size.width * 0.48)\n                        Spacer()\n                        TextField(\"ST\", text: $state)\n                            .customTextField()\n                            .frame(width: geomtry.size.width * 0.18)\n                        Spacer()\n                        TextField(\"Zip\", text: $zip)\n                            .customTextField()\n                            .frame(width: geomtry.size.width * 0.28)\n                    }\n                    TextField(\"Country\", text: $country)\n                        .customTextField()\n                    Spacer()\n                }\n            }\n            .padding(&#91;.leading, .trailing], 10 )\n            .navigationTitle(\"Recipient\")\n            .navigationBarItems(trailing:\n                                    HStack {\n                Button(action: {\n                    let contactsPermsissions = checkContactsPermissions()\n                    if contactsPermsissions == true {\n                        self.showPicker.toggle()\n                    }\n                }, label: {\n                    Image(systemName: \"person.crop.circle.fill\")\n                        .font(.largeTitle)\n                        .foregroundColor(.green)\n                })\n                Button(action: {\n                    saveRecipient()\n                    self.presentationMode.wrappedValue.dismiss()\n                }, label: {\n                    Image(systemName: \"square.and.arrow.down\")\n                        .font(.largeTitle)\n                        .foregroundColor(.green)\n                })\n                Button(action: {\n                    self.presentationMode.wrappedValue.dismiss()\n                }, label: {\n                    Image(systemName: \"chevron.down.circle.fill\")\n                        .font(.largeTitle)\n                        .foregroundColor(.green)\n                })\n            }\n            )\n        }\n    }\n\n    func saveRecipient() {\n        print(\"Saving...\")\n        if firstName != \"\" {\n            let recipient = Recipient(context: self.moc)\n            recipient.firstName = firstName\n            recipient.lastName = lastName\n            recipient.addressLine1 = addressLine1.capitalized(with: NSLocale.current)\n            recipient.addressLine2 = addressLine2.capitalized(with: NSLocale.current)\n            recipient.state = state.uppercased()\n            recipient.city = city.capitalized(with: NSLocale.current)\n            recipient.zip = zip\n            recipient.country = country.capitalized(with: NSLocale.current)\n        }\n        do {\n            try moc.save()\n        } catch let error as NSError {\n            print(\"Save error: \\(error), \\(error.userInfo)\")\n        }\n    }\n\n    func checkContactsPermissions() -> Bool {\n        let authStatus = CNContactStore.authorizationStatus(for: .contacts)\n        switch authStatus {\n        case .restricted:\n            print(\"User cannot grant premission, e.g. parental controls are in force.\")\n            return false\n        case .denied:\n            print(\"User has denided permissions\")\n            \/\/ add a popup to say you have denied permissions\n            return false\n        case .notDetermined:\n            print(\"you need to request authorization via the API now\")\n        case .authorized:\n            print(\"already authorized\")\n        @unknown default:\n            print(\"unknown error\")\n            return false\n        }\n        let store = CNContactStore()\n        if authStatus == .notDetermined {\n            store.requestAccess(for: .contacts) {success, error in\n                if !success {\n                    print(\"Not authorized to access contacts. Error = \\(String(describing: error))\")\n                    exit(1)\n                }\n                print(\"Authorized\")\n            }\n        }\n        return true\n    }\n}\n\nstruct AddNewRecipientView_Previews: PreviewProvider {\n    static var previews: some View {\n        AddNewRecipientView()\n            .environment(\\.managedObjectContext, PersistentCloudKitContainer.persistentContainer.viewContext)\n    }\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Well I fixed the bug! The issue was the sequence of the code sequence between the ContactPicker and VStack within the Navigation View. I hadn&#8217;t realized that this was issue (Obviously). Here&#8217;s a video of the real way it should work. As you can see the UI is now working as you would expect.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"hide_page_title":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[590,82,527],"class_list":["post-2393","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-cardtracker","tag-code","tag-swiftui"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p2aMa8-CB","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/posts\/2393","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/comments?post=2393"}],"version-history":[{"count":1,"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/posts\/2393\/revisions"}],"predecessor-version":[{"id":2395,"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/posts\/2393\/revisions\/2395"}],"wp:attachment":[{"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/media?parent=2393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/categories?post=2393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaelrowe01.com\/index.php\/wp-json\/wp\/v2\/tags?post=2393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}