<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Chase on Medium]]></title>
        <description><![CDATA[Stories by Chase on Medium]]></description>
        <link>https://medium.com/@jpmtech?source=rss-940b7d9329f2------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*mYfG5N898gEyAgzyzW1YkA.jpeg</url>
            <title>Stories by Chase on Medium</title>
            <link>https://medium.com/@jpmtech?source=rss-940b7d9329f2------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 13 Jul 2026 13:23:07 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@jpmtech/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[SwiftUI Text Input]]></title>
            <link>https://medium.com/@jpmtech/swiftui-text-input-f9cae9eaca48?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/f9cae9eaca48</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Wed, 16 Apr 2025 11:02:25 GMT</pubDate>
            <atom:updated>2025-08-18T12:26:36.640Z</atom:updated>
            <content:encoded><![CDATA[<p>SwiftUI’s TextField is a fundamental UI component for gathering user input, offering versatile customization and seamless integration within your app. This article will explore the essentials of working with TextFields, from basic implementation to advanced styling.</p><p>I would love it if you would support me by watching the video that I made for this content:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fa3owfGFNSFU%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Da3owfGFNSFU&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fa3owfGFNSFU%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/089c95606c1e3e9b4877ee08083fb247/href">https://medium.com/media/089c95606c1e3e9b4877ee08083fb247/href</a></iframe><figure><img alt="All the textfields that we will build in this tutorial with the text of Learn TextFields in SwiftUI" src="https://cdn-images-1.medium.com/max/1024/1*diR4zVQ3CKVlj2XXV43ONA.png" /></figure><p>Before we get started, please take a couple of seconds to <strong><em>follow me</em></strong> and 👏 clap for the article so that we can help more people learn about this useful content.</p><p>I would GREATLY appreciate it if you would <strong>subscribe</strong> to my YouTube channel so that I can keep putting out great free content: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a></p><h3>Basic TextField</h3><p>Starting off with the most basic implementation of a TextField, we have a state variable that holds some text, and then display that text to the user</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            TextField(&quot;Enter Text&quot;, text: $text)<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A textfield on the screen with a keyboard displayed" src="https://cdn-images-1.medium.com/max/1024/1*iKeafCPJMfFX3ifVym5JZA.png" /></figure><h3>Changing the scroll direction in a TextField</h3><p>In this next implementation, we will change the scroll direction from the default horizontal direction to vertical. This will allow the TextField to expand vertically when the content reaches the edge of the component.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // Adding an axis here allows the text to scroll in whatever direction you specify.<br>            // The default behavior is horizontal, adding vertical lets the field expand vertically instead of the usual horizontal scrolling behavior<br>            TextField(&quot;Enter Text&quot;, text: $text, axis: .vertical)<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A screenshot of the vertical scrolling TextField in SwiftUI" src="https://cdn-images-1.medium.com/max/1024/1*yAOmb4haQiSfZsMXSkolog.png" /></figure><h3>Adding a prompt to a TextField</h3><p>Adding a prompt to a TextField helps users better understand what they should enter into the field.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // Adding a prompt can help your users understand what kind of input is expected in this field<br>            TextField(&quot;Street Address&quot;, text: $text, prompt: Text(&quot;123 Main St.&quot;))<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A screenshot of the TextField with a street address prompt" src="https://cdn-images-1.medium.com/max/1024/1*z_FSMGrhX7lgVwJSxqRmBg.png" /></figure><h3>TextField with a trailing closure</h3><p>The next text field allows you to pass a trailing closure as a parameter. However, it appears that only the text is displayed and not the image. Don’t worry though, we will cover how to fix that in a future article.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // Another way to add a label to a text field<br>            // Even though you can pass anything in the view, this will still only display text<br>            TextField(text: $text) {<br>                HStack {<br>                    Image(systemName: &quot;rectangle.and.pencil.and.ellipsis&quot;)<br>                    Text(&quot;Enter Text&quot;)<br>                }<br>            }<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A screenshot of the trailing closure TextField" src="https://cdn-images-1.medium.com/max/1024/1*iKeafCPJMfFX3ifVym5JZA.png" /></figure><h3>Passing a value to a text field</h3><p>In the next example, we are using the API for the text field that gives us a “value” parameter instead of a “text” parameter. This value takes in things like numbers or dates and can even give you automatic validation and formatting for whatever local the user is in. For more on these features, check out another article I wrote on those topics here:</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var amount = 0.0<br>    <br>    var body: some View {<br>        VStack {<br>            // Using the built in formatters is a great way to automatically get validation<br>            // and limit the type of expected input for a TextField.<br>            // Notice that this implementation uses &quot;value&quot; instead of &quot;text&quot; in the API<br>            TextField(&quot;Enter Currency Amount&quot;, value: $amount, format: .currency(code: Locale.current.currency?.identifier ?? &quot;USD&quot;))<br><br>            TextField(&quot;Enter Number&quot;, value: $amount, format: .number.precision(.fractionLength(0)))<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A screenshot of the TextField displaying a number instead of text" src="https://cdn-images-1.medium.com/max/1024/1*WfezfT_bh9USNgHhNg0Z6A.png" /></figure><h3>Describing the type of keyboard</h3><p>In our next example, we are telling the app what kind of digital keyboard we expect to use with this input field. Swift has several built-in options that can help guide your users to enter the correct data in the correct field. However, this modifier only applies to digital keyboards, so if your user has a hardware keyboard (attached to an iPad for example), then this keyboard suggestion may not be shown to the user. Just keep that in mind when you are coding your own projects.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // You can help the user input the correct text by giving them a keyboard that displays automatically<br>            // However, if they connect a physical keyboard, the digital keyboard won&#39;t display so keep that in mind when you use it<br>            TextField(&quot;Enter Phone Number&quot;, text: $text)<br>                .keyboardType(.phonePad)<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A screenshot of the custom digital keyboard with our TextField" src="https://cdn-images-1.medium.com/max/1024/1*goqHof89Ygc5sKJf-8mrTw.png" /></figure><h3>Adding a content type to your TextField</h3><p>By adding a content type, you are helping the auto-fill feature understand what kind of data is expected in this input. This can also be helpful in guiding your users to entering the correct data. Again with this option, Swift has several data-types built-in. Feel free to give this one a shot and see which ones you can use to improve your own apps. In the screenshot below, I don’t have the auto-fill suggestions turned on in my simulator so you won’t be able to see the suggestion on my device but it should work on your device if you have the auto-fill suggestions turned on.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // Using the textContentType modifier helps the user by allowing the systems auto-fill feature<br>            // to recognize the type of content and try to automatically fill in the correct data<br>            TextField(&quot;Email&quot;, text: $text)<br>                .textContentType(.emailAddress)<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="A screenshot of the textContentType in a TextField" src="https://cdn-images-1.medium.com/max/1024/1*saxjI1mzeHiZbPveMt90Bg.png" /></figure><h3>Securing data in a TextField</h3><p>Technically this is its own component and not a TextField, but since it acts very similar to a TextField and because, as developers, we should care about the privacy of our users data, I have decided to add this type here. We have also decided to help out the auto-fill feature by passing a content type of password to re-enforce what kind of data should be entered here.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // If you to accept secure text in your app, you will want to use the secure field<br>            SecureField(&quot;Password&quot;, text: $text)<br>                .textContentType(.password)<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="a screenshot of the secure password field filled in with fake data" src="https://cdn-images-1.medium.com/max/1024/1*2Ay6yIxL0-GVNf6yhFYvBQ.png" /></figure><h3>Styling a TextField</h3><p>With SwiftUI there isn’t much we can do in the way of styling a TextField. I have added examples for some of the most common use cases below (such as adding a border to the TextField) and one not so common use case just to make life more fun.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var text = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            // The only built-in styling for a text field is plain (which is what every field is by default)<br>            // or roundedBorder, which allows you to see where the edges of the field are<br>            TextField(&quot;Enter Text&quot;, text: $text)<br>                .textFieldStyle(.roundedBorder)<br>            <br>            // You can also add your own custom styling to a textfield if you want more control over how it looks<br>            TextField(&quot;Enter Text&quot;, text: $text)<br>                .padding(5)<br>                .overlay(<br>                    RoundedRectangle(cornerRadius: 7)<br>                        .stroke(.secondary.opacity(0.5), lineWidth: 1)<br>                )<br><br>            // if you want a fun looking TextField, this is the one you can use<br>            TextField(&quot;Enter Text&quot;, text: $text)<br>                .padding()<br>                .background(<br>                    RadialGradient(<br>                        gradient: Gradient(colors: [.blue, .purple, .red]),<br>                        center: .center,<br>                        startRadius: 0,<br>                        endRadius: 200<br>                    )<br>                )<br>                .foregroundStyle(.white)<br>                .clipShape(RoundedRectangle(cornerRadius: 7))<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><figure><img alt="a screenshot of a few different ways to style TextFields" src="https://cdn-images-1.medium.com/max/1024/1*8uCuXwX3Z-BVdL-VfcFh1A.png" /></figure><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to support my work check out my YouTube channel here: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f9cae9eaca48" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an iOS Stickers App]]></title>
            <link>https://medium.com/@jpmtech/building-an-ios-stickers-app-e4f0bb6bcb2c?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/e4f0bb6bcb2c</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[xcode]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Mon, 14 Apr 2025 11:02:29 GMT</pubDate>
            <atom:updated>2025-04-14T11:02:29.228Z</atom:updated>
            <content:encoded><![CDATA[<p>Sticker apps are surprisingly still a thing, and surprisingly easy to build and update! In this tutorial, we will walk through how to build one from scratch.</p><figure><img alt="A screenshot from the sticker app that we will build in this tutorial" src="https://cdn-images-1.medium.com/max/1024/1*GfxWGxvctOXMuzzi_NulMw.png" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><p>I would GREATLY appreciate it if you would <strong>subscribe</strong> to my YouTube channel so that I can keep putting out great free content: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a></p><h3>Jumping right in</h3><p>This really is so easy and needs so little information that we are going to jump right in to the code.</p><p>Let’s start by creating a new project and choose an iOS Sticker Pack App (as you can see in the image below). We will then click Next, give it a name, and store it on our computer and then click Create.</p><figure><img alt="A screenshot of the new project window with the iOS Sticker Pack App option highlighted" src="https://cdn-images-1.medium.com/max/1024/1*OKFqIxLX0NuWIuiRufuAUw.png" /></figure><p>The next thing you will need are a few images to display in your sticker pack. Once you have your images ready, you can choose Stickers from the project navigator, then select the Sticker Pack folder and simply drag and drop your images to the image area. I have added a couple images for my Medium profile as the for our example app (as you can see in the image below).</p><figure><img alt="A screenshot of the demo stickers app with a couple sample images included" src="https://cdn-images-1.medium.com/max/1024/1*_VwnMy8vzIzR1qDcbQlhhg.png" /></figure><p>Before you run the app you may want to add an app icon so that you the app will show up in the simulator or on your device.</p><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to support my work check out my YouTube channel here: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e4f0bb6bcb2c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Buttons in SwiftUI]]></title>
            <link>https://medium.com/@jpmtech/buttons-in-swiftui-afa87eabd8d7?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/afa87eabd8d7</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Wed, 09 Apr 2025 11:01:40 GMT</pubDate>
            <atom:updated>2025-04-09T11:01:40.123Z</atom:updated>
            <content:encoded><![CDATA[<p>Go from creating a basic button to advanced button styling in less 5 minutes.</p><figure><img alt="A button we will build in this article that says Learn SwiftUI Buttons" src="https://cdn-images-1.medium.com/max/1024/1*jQUHZv_CCaUTXFEfvxLupg.png" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><p>I would GREATLY appreciate it if you would <strong>subscribe</strong> to my YouTube channel so that I can keep putting out great free content: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a></p><h3>Initial Setup</h3><p>Since our focus in this article is on the various APIs for a button, we won’t run any code in the button action, but each button will have a comment to help guide you on where you will do that work in each button example. These brackets that have the code comment in them are called trailing closures. If you have ever used a lambda in Kotlin or and anonymous function in JavaScript, trailing closures operate in a very similar way. They are a block of code that can be run when the button is clicked.</p><p>All of these buttons are to be used inside another view. For example, if you place a button inside of the ContentView, it should look like the following. For the sake of simplicity, these wrapping views have been left out throughout the examples below to help us focus on the button code itself.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    var body: some View {<br>        VStack {<br>            Button(&quot;Click Me&quot;) {<br>                // do some work here<br>            }<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><h3>Basic Button</h3><p>Starting out with the most basic button, we can pass a string to our button and easily get a default button added to the screen.</p><pre>Button(&quot;Click Me&quot;) {<br>    // do some work here<br>}</pre><figure><img alt="an example of a basic button in SwiftUI" src="https://cdn-images-1.medium.com/max/1024/1*iWlxTae4zNvgpqXDuoipow.png" /></figure><h3>Button with an SF Symbol</h3><p>Our next button is slightly more advanced because we are adding an SF Symbol to the button itself. SF Symbols are icons that are built-in to the operating system itself, which means you can use them for free since your app runs on the operating system.</p><pre>Button(&quot;Settings&quot;, systemImage: &quot;gear&quot;) {<br>    // do some work here<br>}</pre><figure><img alt="An example of a button with an SF Symbol" src="https://cdn-images-1.medium.com/max/1024/1*WGW5SUwV3cLHlV8U1G25DQ.png" /></figure><h3>Button with an SF Symbol and a role</h3><p>A role helps guide the intent of the button for the user. For example, when we add a destructive role to the button, the button turns red to help indicate to the user that clicking this button does something destructive.</p><pre>Button(&quot;Delete Me&quot;, systemImage: &quot;trash&quot;, role: .destructive) {<br>    // do some work here<br>}</pre><figure><img alt="an example of a button with an SF Symbol and a destructive role" src="https://cdn-images-1.medium.com/max/1024/1*QQ7iwHLZAMaRaYAWpqIAoA.png" /></figure><h3>Button Styles</h3><p>There are several different button styles that are built-in to SwiftUI that you can use for free. Each of these styles gives the button a slightly different appearance, and they can be combined with any other button options that we have already demonstrated above to give an even more unique appearance. If you want to learn more about creating your own button styles, feel free to check out another article I wrote on that same topic here: <a href="https://medium.com/@jpmtech/create-a-custom-buttonstyle-in-swiftui-98f66231f2c0">https://medium.com/@jpmtech/create-a-custom-buttonstyle-in-swiftui-98f66231f2c0</a></p><pre>Button(&quot;Click Me&quot;) {<br>    // do some work here<br>}<br>.buttonStyle(.borderedProminent)<br><br>Button(&quot;Click Me&quot;) {<br>    // do some work here<br>}<br>.buttonStyle(.bordered)<br><br>Button(&quot;Click Me&quot;) {<br>    // do some work here<br>}<br>.buttonStyle(.plain)</pre><figure><img alt="A screenshot of the built in button styles that we just coded" src="https://cdn-images-1.medium.com/max/1024/1*shXKWW2hz70Q8sjz9gqGcg.png" /></figure><h3>Button with a custom label</h3><p>All of the buttons above look good and would fit in well with any system app. But what if we wanted our button to stand out, and look completely unique. In that case, we can specify a custom label. This custom label can be any view, and can have any properties we want. For example, the button below has a VStack and a linear gradient and we are event changing the font, padding, colors, and scale. If you are looking for a button that stands out in a crowd, this is the button API that you will want to use.</p><pre>Button {<br>    // do some work here<br>} label: {<br>    VStack {<br>        Text(&quot;Learn SwiftUI Buttons&quot;)<br>        Image(systemName: &quot;wand.and.stars&quot;)<br>            .imageScale(.large)<br>    }<br>    .font(.title)<br>    .fontWeight(.bold)<br>}<br>.padding()<br>.foregroundStyle(.white)<br>.background(LinearGradient(colors: [.red, .orange, .indigo, .blue, .cyan], startPoint: .bottomLeading, endPoint: .topTrailing))<br>.clipShape(RoundedRectangle(cornerRadius: 7))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qqvmaCHumhTWXffA5LHSEw.png" /></figure><p>We can use this same method to create a button that is an icon only button that changes it’s icon with a piece of state.</p><pre>struct RecordingButton: View {<br>    @State var isRecording = false<br>    <br>    var body: some View {<br>        Button {<br>            isRecording.toggle()<br>        } label: {<br>            Image(systemName: isRecording ? &quot;stop.circle&quot; : &quot;play.circle&quot;)<br>        }<br>    }<br>}</pre><figure><img alt="An icon only button that indicates a play symbol" src="https://cdn-images-1.medium.com/max/1024/1*aO9AUbsC_8mlfWITHw7Omg.png" /></figure><figure><img alt="a icon only button that is a stop symbol with a circle around it" src="https://cdn-images-1.medium.com/max/1024/1*Yp1XDTAV1L_nJyOn_5B2Qg.png" /></figure><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to support my work check out my YouTube channel here: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=afa87eabd8d7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Enumerate a ForEach in SwiftUI]]></title>
            <link>https://medium.com/@jpmtech/enumerate-a-foreach-in-swiftui-0d4723b9a7df?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/0d4723b9a7df</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Mon, 07 Apr 2025 11:02:12 GMT</pubDate>
            <atom:updated>2025-04-07T11:02:12.106Z</atom:updated>
            <content:encoded><![CDATA[<p>This quick and easy fix can save you time and effort and let you get back to solving harder problems faster.</p><figure><img alt="The text of ForEach Enumerated" src="https://cdn-images-1.medium.com/max/970/1*cysxSjWPMnBaFl4sX8ZO8A.png" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><p>I would GREATLY appreciate it if you would <strong>subscribe</strong> to my YouTube channel so that I can keep putting out great free content: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a></p><h3>Using Enumerated in a ForEach in SwiftUI with a basic array</h3><p>In our first example, we will iterate over an array that holds simple types. This allows us to use the ForEach and have access to the index for the array inside our view. While this example is fairly easy to follow, it isn’t a great real world example. For a more real world example, we can jump to the next section.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    let people = [&quot;Chase&quot;, &quot;John&quot;, &quot;Jane&quot;, &quot;Joe&quot;, &quot;Jenny&quot;, &quot;Jack&quot;]<br>    <br>    var body: some View {<br>        List {<br>            Section {<br>                // Starting from the outside and moving in:<br>                // Wrapping the enumeration with an Array gives you an array of tuples that your ForEach can itterate over.<br>                // The enumeration creates a tuple of the offset (index) and the element (object) that we will itterate over.<br>                // The offset used in the ID parameter is the name of the first element in the tuple from the enumeration and is the index for the array.<br>                ForEach(Array(people.enumerated()), id: \.offset) { index, person in<br>                    Text(&quot;\(person), \(index)&quot;)<br>                }<br>            } header: {<br>                Text(&quot;Iterating over simple types&quot;)<br>            }<br>        }<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><h3>Using an Enumerated in a ForEach in SwiftUI with an array of objects</h3><p>In this example we are using a custom object inside of our array. This is a much more realistic example. In this example we are using the id parameter from each User object as the id parameter. Just like the first example we have access to the index in our view. We also have access to the properties from our object if we need them.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct User: Identifiable {<br>    let id = UUID()<br>    let name: String<br>}<br><br>struct ContentView: View {<br>    let users = [<br>        User(name: &quot;Chase&quot;),<br>        User(name: &quot;John&quot;),<br>        User(name: &quot;Jane&quot;),<br>        User(name: &quot;Joe&quot;),<br>        User(name: &quot;Jenny&quot;),<br>        User(name: &quot;Jack&quot;)<br>    ]<br>    <br>    var body: some View {<br>        List {<br>            Section {<br>                // Starting from the outside and moving in:<br>                // Wrapping the enumeration with an Array gives you an array of tuples that your ForEach can itterate over.<br>                // The enumeration creates a tuple of the offset (index) and the element (object) that we will itterate over.<br>                // The element used in the ID parameter is the name of the second element in the tuple from the enumeration and is the object that we want to itterate over.<br>                ForEach(Array(users.enumerated()), id: \.element.id) { index, user in<br>                    Text(&quot;\(user.name), \(index)&quot;)<br>                }<br>            } header: {<br>                Text(&quot;Iterating over objects&quot;)<br>            }<br>        }<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to support my work check out my YouTube channel here: <a href="https://www.youtube.com/@jpmtechdev">https://www.youtube.com/@jpmtechdev</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0d4723b9a7df" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Create a Custom Single Select Button in SwiftUI]]></title>
            <link>https://medium.com/@jpmtech/create-a-custom-single-select-button-in-swiftui-4bb16310ae46?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/4bb16310ae46</guid>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Wed, 02 Apr 2025 11:02:07 GMT</pubDate>
            <atom:updated>2025-07-01T22:49:59.610Z</atom:updated>
            <content:encoded><![CDATA[<p>There are a few components in SwiftUI that just don’t exist even though developers and designers want to use them, a single-select button is one of them. Let’s add one to our project.</p><p>I would love it if you would support my work by watching the video I made for this content:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fz8khvmG72yY%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dz8khvmG72yY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fz8khvmG72yY%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b4e4b45508d5844b7fe3de2866d4985/href">https://medium.com/media/5b4e4b45508d5844b7fe3de2866d4985/href</a></iframe><figure><img alt="A screenshot of the radio buttons that we will make in this tutorial with option 2 selected" src="https://cdn-images-1.medium.com/max/1024/1*odi1typ0JJVeNO4f8nuFjw.png" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content. If you are looking for how to create a multi-select button (similar to a checkbox) check out another article I wrote here: <a href="https://medium.com/@jpmtech/create-a-custom-multi-select-button-in-swiftui-ebe1de8cd8aa">https://medium.com/@jpmtech/create-a-custom-multi-select-button-in-swiftui-ebe1de8cd8aa</a></p><h3>Jumping right in</h3><p>The code below is the power house for the project. This code creates a custom SwiftUI view that allows us to create most any kind of single-select button that we could dream up.</p><pre>struct SingleSelectButtonView&lt;T: Identifiable &amp; Hashable, Content: View&gt;: View {<br>    let options: [T]<br>    @Binding var selection: T?<br>    @ViewBuilder let content: (T) -&gt; Content<br><br>    /*<br>     init methods aren&#39;t required for SwiftUI to work, however in this example,<br>     I wanted to see only the variables at the call site (not the parameter names for the views).<br>     */<br>    init(<br>        _ options: [T],<br>        _ selection: Binding&lt;T?&gt;,<br>        @ViewBuilder _ content: @escaping (T) -&gt; Content<br>    ) {<br>        self.options = options<br>        self._selection = selection<br>        self.content = content<br>    }<br><br>    var body: some View {<br>        // I have chosen to use a Group here to allow the parent component decide how this view should be displayed<br>        Group {<br>            ForEach(options, id: \.self) { option in<br>                Button {<br>                    selection = option<br>                } label: {<br>                    content(option)<br>                }<br>                .buttonStyle(.plain)<br>            }<br>        }<br>    }<br>}</pre><h3>Create a Radio Button in SwiftUI</h3><p>In our example below we have a couple of usage examples. The first is placing the SingleSelectButtonView in an HStack as a quick example of the power of using a Group in our custom component. This gives us a horizontal set of buttons, and each time one is selected, the button changes state and gets selected while any other button that was selected gets removed.</p><p>The second example in this code block we show just how easy it is to make a radio button using our SingleSelectButtonView.</p><pre>import SwiftUI<br><br>struct CustomOption: Identifiable, Hashable {<br>    let id = UUID()<br>    let text: String<br>}<br><br>struct ContentView: View {<br>    let customOptions = [CustomOption(text: &quot;Option 1&quot;), CustomOption(text: &quot;Option 2&quot;), CustomOption(text: &quot;Option 3&quot;), CustomOption(text: &quot;Option 4&quot;), CustomOption(text: &quot;Option 5&quot;)]<br>    @State var selectedOptions = [CustomOption?]()<br>    @State var singleSelectedOption: CustomOption?<br>    <br>    var body: some View {<br>        VStack {<br>            // This gives us a horizontal stack of buttons that turn blue when selected<br>            HStack {<br>                SingleSelectButtonView(customOptions, $singleSelectedOption) { item in<br>                    Text(String(describing: item.text))<br>                        .padding(.horizontal, 10)<br>                        .padding(.vertical, 5)<br>                        .background(singleSelectedOption == item ? .blue : .gray.opacity(0.3))<br>                        .foregroundColor(singleSelectedOption == item ? .white : .primary)<br>                        .cornerRadius(8)<br>                }<br>            }<br>            <br>            // Radio button example<br>            SingleSelectButtonView(customOptions, $singleSelectedOption) { item in<br>                HStack {<br>                    Image(systemName: singleSelectedOption == item ? &quot;largecircle.fill.circle&quot; : &quot;circle&quot;)<br>                        .foregroundStyle(singleSelectedOption == item ? .blue : .primary)<br>                    Text(item.text)<br>                }<br>            }<br>            <br>            Text(&quot;Selected: \(singleSelectedOption?.text ?? &quot;None&quot;)&quot;)<br>        }<br>        .padding()<br>    }<br>}</pre><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to see apps that have been built with native mobile development, you can check out my apps here: <a href="https://jpmtech.io/apps">https://jpmtech.io/apps</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4bb16310ae46" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Create a Custom Multi-Select Button in SwiftUI]]></title>
            <link>https://medium.com/@jpmtech/create-a-custom-multi-select-button-in-swiftui-ebe1de8cd8aa?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/ebe1de8cd8aa</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Mon, 31 Mar 2025 11:02:07 GMT</pubDate>
            <atom:updated>2025-07-01T22:49:13.500Z</atom:updated>
            <content:encoded><![CDATA[<p>There are a few components in SwiftUI that just don’t exist even though developers and designers want to use them, a multi-select button is one of them. Let’s add one to our project.</p><p>I would love it if you would support my work by watching the video I made on this content:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fdc0Y95kpuf8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Ddc0Y95kpuf8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fdc0Y95kpuf8%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/a5bf1443ed42f963ee73ee97b133d9d5/href">https://medium.com/media/a5bf1443ed42f963ee73ee97b133d9d5/href</a></iframe><figure><img alt="a screenshot of the example that we will build in this tutorial with options 1, 3, and 5 selected" src="https://cdn-images-1.medium.com/max/1024/1*BpweySN6EG2rWIBMdhijqA.png" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><h3>Jumping right in</h3><p>The code below is the power house for the project. This code creates a custom SwiftUI view that allows us to create most any kind of multi-select button that we could dream up.</p><pre>struct MultiSelectButtonView&lt;T: Identifiable &amp; Hashable, Content: View&gt;: View {<br>    let options: [T]<br>    @Binding var selection: [T?]<br>    @ViewBuilder let content: (T) -&gt; Content<br><br>    /*<br>     init methods aren&#39;t required for SwiftUI to work, however in this example,<br>     I wanted to see only the variables at the call site (not the parameter names for the views).<br>     */<br>    init(<br>        _ options: [T],<br>        _ selection: Binding&lt;[T?]&gt;,<br>        @ViewBuilder _ content: @escaping (T) -&gt; Content<br>    ) {<br>        self.options = options<br>        self._selection = selection<br>        self.content = content<br>    }<br>    <br>    var body: some View {<br>        // I have chosen to use a Group here to allow the parent component decide how this view should be displayed<br>        Group {<br>            ForEach(options, id: \.self) { option in<br>                Button {<br>                    if selection.contains(option) {<br>                        selection.removeAll { $0 == option }<br>                    } else {<br>                        selection.append(option)<br>                    }<br>                } label: {<br>                    content(option)<br>                }<br>                .buttonStyle(.plain)<br>            }<br>        }<br>    }<br>}</pre><h3>Create a Checkbox in SwiftUI</h3><p>In our example below we have a couple of usage examples. The first is placing the MultiSelectButtonView in an HStack as a quick example of the power of using a Group in our custom component. This gives us a horizontal set of buttons, and each time one is selected, the button changes state and gets added to our array of selected options.</p><p>The second example in this code block we show just how easy it is to make a checkbox using our MultiSelectButtonView.</p><pre>import SwiftUI<br><br>struct CustomOption: Identifiable, Hashable {<br>    let id = UUID()<br>    let text: String<br>}<br><br>struct ContentView: View {<br>    let customOptions = [CustomOption(text: &quot;Option 1&quot;), CustomOption(text: &quot;Option 2&quot;), CustomOption(text: &quot;Option 3&quot;), CustomOption(text: &quot;Option 4&quot;), CustomOption(text: &quot;Option 5&quot;)]<br>    @State var selectedOptions = [CustomOption?]()<br>    <br>    var body: some View {<br>        VStack {<br>            // This gives us a horizontal stack of buttons that turn blue when selected<br>            HStack {<br>                MultiSelectButtonView(customOptions, $selectedOptions) { item in<br>                    Text(String(describing: item.text))<br>                        .padding(.horizontal, 10)<br>                        .padding(.vertical, 5)<br>                        .background(selectedOptions.contains(item) ? .blue : .gray.opacity(0.3))<br>                        .foregroundColor(selectedOptions.contains(item) ? .white : .primary)<br>                        .cornerRadius(8)<br>                }<br>            }<br>            <br>            // This gives us an example of a checkbox<br>            MultiSelectButtonView(customOptions, $selectedOptions) { item in<br>                HStack {<br>                    Image(systemName: selectedOptions.contains(item) ? &quot;checkmark.square.fill&quot; : &quot;square&quot;)<br>                        .foregroundStyle(selectedOptions.contains(item) ? .blue : .primary)<br>                    Text(String(describing: item.text))<br>                }<br>            }<br>            <br>            Text(&quot;Selected: \(selectedOptions.map { String(describing: $0!.text) }.joined(separator: &quot;, &quot;))&quot;)<br>        }<br>        .padding()<br>    }<br>}</pre><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to see apps that have been built with native mobile development, you can check out my apps here: <a href="https://jpmtech.io/apps">https://jpmtech.io/apps</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ebe1de8cd8aa" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Clean Up Your Sheet API]]></title>
            <link>https://medium.com/@jpmtech/clean-up-your-sheet-api-7763b796cd94?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/7763b796cd94</guid>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Mon, 24 Mar 2025 23:53:22 GMT</pubDate>
            <atom:updated>2025-03-24T23:53:22.539Z</atom:updated>
            <content:encoded><![CDATA[<p>If you are like most developers, you probably have more parameters than are required to get a working sheet in SwiftUI. Please pardon the potty humor and let’s work together and get that API cleaned up.</p><figure><img alt="an image of a poop emoji standing in front of a sheet" src="https://cdn-images-1.medium.com/max/1024/1*QUYmumzU6zIoQRpTat3cJw.jpeg" /><figcaption>Generated by the Image Playgrounds app</figcaption></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><h3>Most Sheet APIs</h3><p>Many developers (including myself) have writing code that is similar to the following. In this example, we are passing a binding to the sheet. Once in the sheet view, we are using that binding to close the sheet. There isn’t really much wrong with this implementation except that our sheet view has an unnecessarily long API, and it would probably be worse if this was more than a quick tutorial. So what do we do to fix it?</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var isShowingMyCustomSheet = false<br>    <br>    var body: some View {<br>        VStack {<br>            Button(&quot;Toggle the Sheet&quot;) {<br>                isShowingMyCustomSheet.toggle()<br>            }<br>        }<br>        .padding()<br>        .sheet(isPresented: $isShowingMyCustomSheet) {<br>            // our long sheet API<br>            MySheetView(isShowingMyCustomSheet: $isShowingMyCustomSheet)<br>        }<br>    }<br>}<br><br>struct MySheetView: View {<br>    @Binding var isShowingMyCustomSheet: Bool<br>    <br>    var body: some View {<br>        VStack {<br>            HStack {<br>                Spacer()<br>                Button {<br>                    isShowingMyCustomSheet.toggle()<br>                } label: {<br>                    Image(systemName: &quot;xmark&quot;)<br>                }<br>            }.padding()<br>            <br>            Spacer()<br>            // If you want this image for your project, you can save the title <br>            // image from this article to your project file<br>            Image(.poopEmojiCharacter)<br>                .resizable()<br>                .scaledToFit()<br>            Spacer()<br>        }<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><h3>Environment variables for the win</h3><p>In this cleaned up version of the sheet view, we swapped the Binding to the parents state variable with an environment variable. This environment variable is meant to dismiss any view. The dismiss environment variable works with sheets and NavigationStacks, and is a great tool to have in your developer toolbelt.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @State var isShowingMyCustomSheet = false<br>    <br>    var body: some View {<br>        VStack {<br>            Button(&quot;Toggle the Sheet&quot;) {<br>                isShowingMyCustomSheet.toggle()<br>            }<br>        }<br>        .padding()<br>        .sheet(isPresented: $isShowingMyCustomSheet) {<br>            // Our short sheet API<br>            MySheetView()<br>        }<br>    }<br>}<br><br>struct MySheetView: View {<br>    @Environment(\.dismiss) var dismiss<br>    <br>    var body: some View {<br>        VStack {<br>            HStack {<br>                Spacer()<br>                Button {<br>                    dismiss()<br>                } label: {<br>                    Image(systemName: &quot;xmark&quot;)<br>                }<br>            }.padding()<br>            <br>            Spacer()<br>            // If you want this image for your project, you can save the title <br>            // image from this article to your project file<br>            Image(.poopEmojiCharacter)<br>                .resizable()<br>                .scaledToFit()<br>            Spacer()<br>        }<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to see apps that have been built with native mobile development, you can check out my apps here: <a href="https://jpmtech.io/apps">https://jpmtech.io/apps</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7763b796cd94" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Push Notification Service Extension in Swift]]></title>
            <link>https://medium.com/@jpmtech/push-notification-service-extension-in-swift-b1a0b68051d6?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/b1a0b68051d6</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Mon, 24 Feb 2025 12:01:53 GMT</pubDate>
            <atom:updated>2025-02-24T12:01:53.604Z</atom:updated>
            <content:encoded><![CDATA[<p>Get ready to give your push notifications superpowers! Did you know that you can change the push notification content once it gets to a users device?! Let’s learn how together.</p><figure><img alt="A super powered notification with lightning bolts and neon lighting coming out of a phone screen" src="https://cdn-images-1.medium.com/max/1024/1*6zGiblGYS9L_JgQSXzF-fA.jpeg" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><h3>Initial Setup</h3><p>If you have not yet setup push notifications in your app or if you need a refresher with push notifications, you will want to start with another article I wrote that has everything you need to know to get started with push notifications: <a href="https://medium.com/@jpmtech/your-complete-guide-to-push-notifications-in-swiftui-8a13f5588662">https://medium.com/@jpmtech/your-complete-guide-to-push-notifications-in-swiftui-8a13f5588662</a></p><h3>Why I needed to modify notifications on device</h3><p>You may be asking, why wouldn’t you just make the modifications for the push notification in the back-end service, which is a valid question. However, in an app that I am building for a client, we are using two different third party sources that can both send notifications. Neither source had a spot in their configuration to specify the sound that the notification could play, and neither source knew about the badge count that was sent in the notification from the other service. These issues of constantly incorrect badge counts and no sounds for notifications, are what led me to learn about the super power of changing the content of a notification on device and may also be beneficial for others to learn how to do the same thing.</p><h3>Adding a Notification Service Extension</h3><p>A notification service extension is a target that gives our app the ability to intercept the push notification as it comes in, but before it is displayed to the user. To add a notification service extension to your app, go to File -&gt; New -&gt; Target and search for notification, then choose Notification Service Extension:</p><figure><img alt="A screenshot of us adding the notification service extension to our app" src="https://cdn-images-1.medium.com/max/1024/1*OwkDSJdo1cXwa_BMx3f0og.png" /></figure><p>Give your extension a name (I called mine NotificationServiceExtension), then click Finish.</p><figure><img alt="a screenshot of naming the notification service extension" src="https://cdn-images-1.medium.com/max/1024/1*RGZi1IQ4Tr2BWZMmQod4lA.png" /></figure><p>Xcode will then ask if you want to activate your new target, and you can choose the default (which is currently Activate).</p><h3>Configure Your Project</h3><p>Like we mentioned in the initial setup step, if your project hasn’t been set up for push notifications, now is the chance to go ahead and do that. Once that is done there are a couple other settings we will need to make sure we add so that our notification service extension works as expected. Go into the Signing and Capabilities section for your app target. Once there we will need to ensure we have the Background Mode capability for Remote Notifications. We will also need to add the App Group capability and add a new group name. These names typically start with the word “group.” then follow the reverse domain name notation (similar to your Bundle ID) followed by your app name (since these app groups must also be unique). For example, I named my App Group: “group.io.jpmtech.push-notifications-example”, a useful bonus tip is that you copy the name before clicking save, you won’t have to type it again in the next step and can be confident that the strings match in both places.</p><figure><img alt="a screenshot of the settings we will change on our app target" src="https://cdn-images-1.medium.com/max/708/1*Hwg4wwy5n5kWDNdmCclGGQ.png" /></figure><p>Next we will go over to the NotificationServiceExtension target and again go to the Signing and Capabilities section and add an App Group capability and we can paste the name from app target, or it may populate automatically in which case you can simply check the box to turn it on.</p><figure><img alt="A screenshot of the app group checked in our notification service extension" src="https://cdn-images-1.medium.com/max/708/1*0-920_Nu3Ycnfjdm7Eq_eQ.png" /></figure><h3>Modify Push Notifications on Device</h3><p>With the setup and configuration out of the way, we are ready to modify our push notification content. There is one last thing that you will need to know before we jump into the code and start modifying push notifications. Our payload for the notification must include &quot;mutable-content&quot;: 1 this tells our extension that it is allowed to change the content in the push notification. If this field is left off, or set to zero, we will not be able to change the content of the push notification.</p><p>Going to the sample code that Apple gives us for free when we added our notification service extension, we can see that we are attempting to make a copy of the the content in the notification if it is mutable. If the content is mutable (meaning that we have added the mutable content flag and it’s value is set to 1) then we can change the content in the push notification. The example code shows us out of the box how we can modify the title. We can also modify anything else that a push notification might have like the sound, badge count, etc. We can also use these methods to decrypt any data or download any images that may be included in the push notification payload.</p><pre>//  NotificationService.swift<br>import UserNotifications<br><br>class NotificationService: UNNotificationServiceExtension {<br><br>    var contentHandler: ((UNNotificationContent) -&gt; Void)?<br>    var bestAttemptContent: UNMutableNotificationContent?<br><br>    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -&gt; Void) {<br>        self.contentHandler = contentHandler<br>        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)<br>        <br>        if let bestAttemptContent = bestAttemptContent {<br>            // Modify the notification content here...<br>            bestAttemptContent.title = &quot;\(bestAttemptContent.title) [modified]&quot;<br>            <br>            contentHandler(bestAttemptContent)<br>        }<br>    }<br>    <br>    override func serviceExtensionTimeWillExpire() {<br>        // Called just before the extension will be terminated by the system.<br>        // Use this as an opportunity to deliver your &quot;best attempt&quot; at modified content, otherwise the original push payload will be used.<br>        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {<br>            contentHandler(bestAttemptContent)<br>        }<br>    }<br><br>}</pre><p>If you want to learn more about what you can do with the Push Notification Extension, feel free to check out Apples docs here: <a href="https://developer.apple.com/documentation/usernotifications/modifying-content-in-newly-delivered-notifications">https://developer.apple.com/documentation/usernotifications/modifying-content-in-newly-delivered-notifications</a></p><h3>Testing our Notification Service Extension</h3><p>When testing the service extension, you won’t be able to add break points or print statements like you are use to with the rest of your project. You will also want to use the “Testing remote push notifications” section from <a href="https://medium.com/@jpmtech/your-complete-guide-to-push-notifications-in-swiftui-8a13f5588662">my other article</a> to ensure you are sending a notification from a remote service since the notification service extension won’t register a notification payload that has been dragged and dropped onto the simulator. Just be sure to add the &quot;mutable-content&quot;: 1 flag to the payload before sending it. When you send the payload, you should see the title appear on the device with the content “[modified]” appended to the end of the title.</p><h3>Bonus tip</h3><p>If you are having a hard time getting this to work on the simulator, make sure you have everything set up correctly in the configuration steps and then reset the simulator you are testing with (using the Erase All Content and Settings option in the simulators Device menu), and try sending the notification again.</p><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech">https://medium.com/@jpmtech</a>. If you want to see apps that have been built with native mobile development, you can check out my apps here: <a href="https://jpmtech.io/apps">https://jpmtech.io/apps</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b1a0b68051d6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Use One Image Instead of Many in SwiftUI]]></title>
            <link>https://medium.com/@jpmtech/how-to-use-one-image-instead-of-many-in-swiftui-c48d086584f4?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/c48d086584f4</guid>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Wed, 19 Feb 2025 12:02:21 GMT</pubDate>
            <atom:updated>2025-02-23T18:56:10.488Z</atom:updated>
            <content:encoded><![CDATA[<p>Learn how to use one image for light or dark mode, and the same image for small or large icons.</p><figure><img alt="an image full of several different types of icons that you might see in an app" src="https://cdn-images-1.medium.com/max/1024/1*eGp1FrwugPH1Z8LaRbyGfw.jpeg" /><figcaption>Image generated by Gemini</figcaption></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><h3>Option 1: The Easy Way</h3><p>The easiest way to use one image and have it auto-magically work everywhere is to use SF Symbols. SF Symbols is a massive library of already built symbols that you get for free. These symbols are already setup for light/dark mode, some have multiple colors that they can display at once, they are designed to look great at any scale, you can create your own fully custom SF Symbols from scratch, and some of the symbols are already setup to animate with a simple modifier. If you want to learn more about SF Symbols and how to use them in your app, check out this article: <a href="https://medium.com/@jpmtech/using-sf-symbols-in-your-app-designs-6f7fb4c3e63e">https://medium.com/@jpmtech/using-sf-symbols-in-your-app-designs-6f7fb4c3e63e</a></p><h3>Option 2: The slightly less easy way</h3><p>But what if we really wanted to use a custom image, and didn’t want to learn about how great SF Symbols are, and we just want to add an image to our app and be done with it. SwiftUI and Xcode also make that easy. Below is the image that I will use for the demo project. I chose to use an SVG so that it would easily and cleanly scale, however, Medium doesn’t allow SVGs to be uploaded in an article. I apologize that the image shared is not the exact same image, but it should get you close enough to learn what you need to in order to re-create this in your own project.</p><figure><img alt="a green alien head with antennas" src="https://cdn-images-1.medium.com/max/592/1*kEeDB5heMxJSeDUfm6QXAw.png" /></figure><p>In our Xcode Assets file, we will add a new image asset and make a few changes to the settings. First we will change the name to match what we want it to be (the default name is “image”). Next we will change the Render As setting to be a “Template Image”, this setting gives us the ability to change the color of the image and allows it to work with light/dark mode colors or system colors if we wanted to use this in a Button for example. Since I am uploading an SVG that image type is infinitely re-scalable so I also checked the box for Preserving Vector Data to make sure that all the data is there at any scale. I also changed the Scales option to be a Single Scale, because I want the same image to be displayed no matter what the pixel density of the device is and with the scalability of an SVG I know that image will be clear at any scale.</p><figure><img alt="a screenshot of the image settings in the Xcode Assets file" src="https://cdn-images-1.medium.com/max/1024/1*BSrWnGEmV7KMASLWvRRecw.png" /></figure><p>With those settings changes in place, we are ready to start using our image in code. As you can see in the code below, we can use system colors and change the color and size of our image. It even works with system features like automatically changing colors to match the text on a button.</p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    var body: some View {<br>        VStack(spacing: 20) {<br>            Image(.alien)<br>                .resizable()<br>                .scaledToFit()<br>                .foregroundStyle(.red)<br>            <br>            Image(.alien)<br>                .resizable()<br>                .scaledToFit()<br>                .frame(width: 250)<br>                .foregroundStyle(.green)<br>            <br>            Image(.alien)<br>                .resizable()<br>                .scaledToFit()<br>                .frame(width: 100)<br>                .foregroundStyle(.blue)<br>            <br>            Button {<br>                // do something here<br>            } label: {<br>                HStack {<br>                    Image(.alien)<br>                        .resizable()<br>                        .scaledToFit()<br>                        .frame(width: 40)<br>                    <br>                    Text(&quot;Click me&quot;)<br>                }<br>            }.buttonStyle(.borderedProminent)<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="https://medium.com/@jpmtech">https://medium.com/@jpmtech</a>. If you want to see apps that have been built with native mobile development, you can check out my apps here: <a href="https://jpmtech.io/apps">https://jpmtech.io/apps</a>. Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c48d086584f4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AppStorage in SwiftUI]]></title>
            <link>https://medium.com/@jpmtech/appstorage-in-swiftui-7a653341640f?source=rss-940b7d9329f2------2</link>
            <guid isPermaLink="false">https://medium.com/p/7a653341640f</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Chase]]></dc:creator>
            <pubDate>Mon, 17 Feb 2025 12:02:22 GMT</pubDate>
            <atom:updated>2025-02-17T12:02:22.053Z</atom:updated>
            <content:encoded><![CDATA[<p>Are you ready to learn the fastest and easiest way of storing data in your SwiftUI app? In this article we will go over how to use this property wrapper for quick and easy access to user defaults.</p><figure><img alt="The text of AppStorage in reference to the SwiftUI property wrapper" src="https://cdn-images-1.medium.com/max/971/1*uFbod4wcM9GIHec9AJH5WQ.png" /></figure><p>Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.</p><h3>Jumping straight to the code</h3><p>AppStorage is a property wrapper that gives us quick and easy access to UserDefaults in SwiftUI. At the top of the following code, you can see we are calling “@AppStorage” which looks for the “customKey” we pass to the method inside the UserDefaults storage. If the key exists it will give us the value back, if it doesn’t exist then it will use the default value we are giving it (which in our example is an empty string). To update that same value with a new one, we can simply set it to a new value (like we are doing in our “Save your name” button below.</p><p>If you decide to use AppStorage in your app, don’t forget to add the PrivacyManifest file to your app or your app review may get denied. Learn how to set that up here: <a href="https://medium.com/@jpmtech/privacy-manifest-for-your-ios-app-bce634c1b619">https://medium.com/@jpmtech/privacy-manifest-for-your-ios-app-bce634c1b619</a>. If you want to learn more about UserDefaults, feel free to check another article I wrote on that topic: <a href="https://medium.com/@jpmtech/userdefaults-in-swift-31384fa8aef7">https://medium.com/@jpmtech/userdefaults-in-swift-31384fa8aef7</a></p><pre>//  ContentView.swift<br>import SwiftUI<br><br>struct ContentView: View {<br>    @AppStorage(&quot;myCustomKey&quot;) var myCustomValue = &quot;&quot;<br>    <br>    var body: some View {<br>        VStack {<br>            Button(&quot;Save your name&quot;) {<br>                myCustomValue = &quot;Little Johnny&quot;<br>            }<br>            <br>            if !myCustomValue.isEmpty {<br>                Text(&quot;Hi \(myCustomValue)!&quot;)<br>            }<br>        }<br>        .padding()<br>    }<br>}<br><br>#Preview {<br>    ContentView()<br>}</pre><p>App storage can hold several basic data types (anything that UserDefaults can store). However, <a href="https://developer.apple.com/documentation/foundation/userdefaults/1617187-sizelimitexceedednotification">it is limited in how much data you can store</a> (though it appears this only applies to tvOS) and the <a href="https://developer.apple.com/documentation/foundation/userdefaults">kind of data you want to store</a> (the system was designed to store small pieces of data that your app might need at startup, such as playback speed or volume).</p><h3>Bonus Tip</h3><p>If you want to see all the information that is stored in UserDefaults at once, you can add the following lines of code to any view in your app. This will give you the path to the Preferences file for your app. Opening the plist file in that folder will show you the data that can be accessed in UserDefaults.</p><pre>.onAppear {<br>    print(URL.libraryDirectory.appending(path: &quot;Preferences&quot;).path())<br>}</pre><p>If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.</p><p>If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: <a href="/@jpmtech.">https://medium.com/@jpmtech.</a> If you want to see apps that have been built with native mobile development, you can check out my apps here: <a href="https://jpmtech.io/apps.">https://jpmtech.io/apps.</a> Thank you for taking the time to check out my work!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7a653341640f" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>