{"id":410307,"date":"2024-06-29T21:18:15","date_gmt":"2024-06-29T21:18:15","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=410307"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=410307","title":{"rendered":"<span>How to Make an E-commerce App in SwiftUI<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>In this guide, I&#8217;m going to walk you through how to create a simple e-commerce app using SwiftUI and Firebase. The app will include basic functionalities such as product listing, shopping cart, and user authentication.<\/p>\n<p>Before we get started, you should have the following installed:<\/p>\n<ul>\n<li>\n<p>Xcode<\/p>\n<\/li>\n<li>\n<p>Firebase SDK<\/p>\n<\/li>\n<li>\n<p>CocoaPods (for installing Firebase SDK)<\/p>\n<\/li>\n<\/ul>\n<h3>Step 1: Setting up the Xcode Project<\/h3>\n<p>First, I&#8217;ll create a new Xcode project. I&#8217;ll select the &#171;App&#187; option under &#171;iOS&#187;.<\/p>\n<pre><code class=\"bash\">File -> New -> Project -> iOS -> App<\/code><\/pre>\n<p>I&#8217;ll name it &#171;EcommerceApp&#187; and choose SwiftUI for the interface and Swift for the language.<\/p>\n<h3>Step 2: Setting up Firebase<\/h3>\n<ol>\n<li>\n<p>I&#8217;ll go to the <a href=\"https:\/\/console.firebase.google.com\/\" rel=\"noopener noreferrer nofollow\">Firebase console<\/a>.<\/p>\n<\/li>\n<li>\n<p>Click &#171;Add project&#187;, then follow the on-screen instructions to create a new project.<\/p>\n<\/li>\n<\/ol>\n<p>Once my project is ready, I need to add an iOS app to it.<\/p>\n<ol>\n<li>\n<p>In the Project Overview page, I&#8217;ll click the iOS icon to add an iOS app to my Firebase project.<\/p>\n<\/li>\n<li>\n<p>I&#8217;ll fill in the iOS bundle ID which is found in my Xcode project settings. Then, follow the steps to download the <code>GoogleService-Info.plist<\/code> file.<\/p>\n<\/li>\n<li>\n<p>I&#8217;ll drag the downloaded <code>GoogleService-Info.plist<\/code> file into my Xcode project root.<\/p>\n<\/li>\n<\/ol>\n<p>Now, it&#8217;s time to install the Firebase SDK using CocoaPods. I&#8217;ll open the Terminal, navigate to my project root, and type:<\/p>\n<pre><code class=\"bash\">pod init<\/code><\/pre>\n<p>This command will create a <code>Podfile<\/code>. I&#8217;ll open it and add:<\/p>\n<pre><code class=\"bash\">pod 'Firebase\/Auth' pod 'Firebase\/Firestore'<\/code><\/pre>\n<p>Then, I&#8217;ll run:<\/p>\n<pre><code class=\"bash\">pod install<\/code><\/pre>\n<p>Now, I&#8217;ll open the <code>.xcworkspace<\/code> file.<\/p>\n<p>In the <code>AppDelegate.swift<\/code>, I&#8217;ll import Firebase and add <code>FirebaseApp.configure()<\/code> in <code>didFinishLaunchingWithOptions<\/code>:<\/p>\n<pre><code class=\"swift\">import UIKit import Firebase  @main class AppDelegate: UIResponder, UIApplicationDelegate {   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {     FirebaseApp.configure()     return true   }   \/\/ ... }<\/code><\/pre>\n<h3>Step 3: Creating User Authentication<\/h3>\n<p>First, I need to create a simple login view. In the Firebase Console, I&#8217;ll enable the Email\/Password sign-in method in the Authentication section.<\/p>\n<p>In <code>ContentView.swift<\/code>, I&#8217;ll add:<\/p>\n<pre><code class=\"swift\">import SwiftUI import FirebaseAuth  struct ContentView: View {   @State private var email = \"\"   @State private var password = \"\"      var body: some View {     VStack {       TextField(\"Email\", text: $email)         .padding()         .autocapitalization(.none)       SecureField(\"Password\", text: $password)         .padding()       Button(action: {         Auth.auth().signIn(withEmail: email, password: password) { authResult, error in           if let error = error {             print(error.localizedDescription)           }         }       }) {         Text(\"Login\")       }       .padding()     }   } }<\/code><\/pre>\n<h3>Step 4: Product Listing<\/h3>\n<p>Let&#8217;s assume I have a <code>products<\/code> collection in Firestore, where each document has <code>name<\/code>, <code>price<\/code>, and <code>description<\/code> fields.<\/p>\n<p>I will create a <code>Product<\/code> struct and a <code>ProductView<\/code>:<\/p>\n<pre><code class=\"swift\">struct Product: Identifiable {   var id: String   var name: String   var price: Double   var description: String }  struct ProductView: View {   var product: Product      var body: some View {     VStack(alignment: .leading) {       Text(product.name)         .font(.headline)       Text(product.description)         .font(.subheadline)       Text(\"$\\(product.price)\")         .font(.title)     }     .padding()   } }<\/code><\/pre>\n<p>Then, I&#8217;ll create a <code>ProductListView<\/code> to fetch and list the products:<\/p>\n<pre><code class=\"swift\">import FirebaseFirestore  struct ProductListView: View {   @State private var products = [Product]()      var body: some View {     List(products) { product in       ProductView(product: product)     }     .onAppear() {       fetchProducts()     }   }      func fetchProducts() {     Firestore.firestore().collection(\"products\").getDocuments() { querySnapshot, error in       if let error = error {         print(error.localizedDescription)         return       }              self.products = querySnapshot?.documents.compactMap { document -> Product? in         let data = document.data()                  guard let name = data[\"name\"] as? String,               let price = data[\"price\"] as? Double,               let description = data[\"description\"] as? String         else {           return nil         }                  return Product(id: document.documentID, name: name, price: price, description: description)       } ?? []     }   } }<\/code><\/pre>\n<h3>Step 5: Shopping Cart<\/h3>\n<p>First, I&#8217;ll create a <code>Cart<\/code> model and a <code>CartView<\/code>. In the <code>CartView<\/code>, I&#8217;ll list all the products in the cart and calculate the total price:<\/p>\n<pre><code class=\"swift\">struct CartProduct: Identifiable {   var id: String   var product: Product   var quantity: Int }  struct CartView: View {   @State private var cartProducts = [CartProduct]()      var body: some View {     VStack {       List(cartProducts) { cartProduct in         HStack {           Text(cartProduct.product.name)           Spacer()           Text(\"x\\(cartProduct.quantity)\")           Text(\"$\\(cartProduct.product.price * Double(cartProduct.quantity))\")         }         .padding()       }              Text(\"Total: $\\(cartProducts.reduce(0) { $0 + $1.product.price * Double($1.quantity) })\")         .font(.headline)         .padding()     }   }      func fetchCart() {     \/\/ Here, I'll fetch cart products from Firestore...   } }<\/code><\/pre>\n<p>In the <code>ProductView<\/code>, I&#8217;ll add an &#171;Add to Cart&#187; button:<\/p>\n<pre><code class=\"swift\">struct ProductView: View {   var product: Product      var body: some View {     VStack(alignment: .leading) {       Text(product.name)         .font(.headline)       Text(product.description)         .font(.subheadline)       Text(\"$\\(product.price)\")         .font(.title)       Button(action: {         addToCart(product)       }) {         Text(\"Add to Cart\")       }     }     .padding()   }      func addToCart(_ product: Product) {     \/\/ Here, I'll add the product to the cart in Firestore...   } }<\/code><\/pre>\n<p>In both <code>fetchCart()<\/code> and <code>addToCart(_:)<\/code>, I&#8217;ll need to implement the logic to interact with Firestore. The cart could be a subcollection in each user document, where each document in the cart collection represents a cart product, with <code>productId<\/code>, <code>quantity<\/code>, and <code>addedAt<\/code> fields.<\/p>\n<h3>Conclusion<\/h3>\n<p>While this is a simplified example, it covers the core features of an e-commerce app: user authentication, product listing, and a shopping cart. Check out <a href=\"https:\/\/iosapptemplates.com\/\" rel=\"noopener noreferrer nofollow\">iOS app templates<\/a> for ready-to-use codebases if you want to save time and energy.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/749488\/\"> https:\/\/habr.com\/ru\/articles\/749488\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>In this guide, I&#8217;m going to walk you through how to create a simple e-commerce app using SwiftUI and Firebase. The app will include basic functionalities such as product listing, shopping cart, and user authentication.<\/p>\n<p>Before we get started, you should have the following installed:<\/p>\n<ul>\n<li>\n<p>Xcode<\/p>\n<\/li>\n<li>\n<p>Firebase SDK<\/p>\n<\/li>\n<li>\n<p>CocoaPods (for installing Firebase SDK)<\/p>\n<\/li>\n<\/ul>\n<h3>Step 1: Setting up the Xcode Project<\/h3>\n<p>First, I&#8217;ll create a new Xcode project. I&#8217;ll select the &#171;App&#187; option under &#171;iOS&#187;.<\/p>\n<pre><code class=\"bash\">File -> New -> Project -> iOS -> App<\/code><\/pre>\n<p>I&#8217;ll name it &#171;EcommerceApp&#187; and choose SwiftUI for the interface and Swift for the language.<\/p>\n<h3>Step 2: Setting up Firebase<\/h3>\n<ol>\n<li>\n<p>I&#8217;ll go to the <a href=\"https:\/\/console.firebase.google.com\/\" rel=\"noopener noreferrer nofollow\">Firebase console<\/a>.<\/p>\n<\/li>\n<li>\n<p>Click &#171;Add project&#187;, then follow the on-screen instructions to create a new project.<\/p>\n<\/li>\n<\/ol>\n<p>Once my project is ready, I need to add an iOS app to it.<\/p>\n<ol>\n<li>\n<p>In the Project Overview page, I&#8217;ll click the iOS icon to add an iOS app to my Firebase project.<\/p>\n<\/li>\n<li>\n<p>I&#8217;ll fill in the iOS bundle ID which is found in my Xcode project settings. Then, follow the steps to download the <code>GoogleService-Info.plist<\/code> file.<\/p>\n<\/li>\n<li>\n<p>I&#8217;ll drag the downloaded <code>GoogleService-Info.plist<\/code> file into my Xcode project root.<\/p>\n<\/li>\n<\/ol>\n<p>Now, it&#8217;s time to install the Firebase SDK using CocoaPods. I&#8217;ll open the Terminal, navigate to my project root, and type:<\/p>\n<pre><code class=\"bash\">pod init<\/code><\/pre>\n<p>This command will create a <code>Podfile<\/code>. I&#8217;ll open it and add:<\/p>\n<pre><code class=\"bash\">pod 'Firebase\/Auth' pod 'Firebase\/Firestore'<\/code><\/pre>\n<p>Then, I&#8217;ll run:<\/p>\n<pre><code class=\"bash\">pod install<\/code><\/pre>\n<p>Now, I&#8217;ll open the <code>.xcworkspace<\/code> file.<\/p>\n<p>In the <code>AppDelegate.swift<\/code>, I&#8217;ll import Firebase and add <code>FirebaseApp.configure()<\/code> in <code>didFinishLaunchingWithOptions<\/code>:<\/p>\n<pre><code class=\"swift\">import UIKit import Firebase  @main class AppDelegate: UIResponder, UIApplicationDelegate {   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {     FirebaseApp.configure()     return true   }   \/\/ ... }<\/code><\/pre>\n<h3>Step 3: Creating User Authentication<\/h3>\n<p>First, I need to create a simple login view. In the Firebase Console, I&#8217;ll enable the Email\/Password sign-in method in the Authentication section.<\/p>\n<p>In <code>ContentView.swift<\/code>, I&#8217;ll add:<\/p>\n<pre><code class=\"swift\">import SwiftUI import FirebaseAuth  struct ContentView: View {   @State private var email = \"\"   @State private var password = \"\"      var body: some View {     VStack {       TextField(\"Email\", text: $email)         .padding()         .autocapitalization(.none)       SecureField(\"Password\", text: $password)         .padding()       Button(action: {         Auth.auth().signIn(withEmail: email, password: password) { authResult, error in           if let error = error {             print(error.localizedDescription)           }         }       }) {         Text(\"Login\")       }       .padding()     }   } }<\/code><\/pre>\n<h3>Step 4: Product Listing<\/h3>\n<p>Let&#8217;s assume I have a <code>products<\/code> collection in Firestore, where each document has <code>name<\/code>, <code>price<\/code>, and <code>description<\/code> fields.<\/p>\n<p>I will create a <code>Product<\/code> struct and a <code>ProductView<\/code>:<\/p>\n<pre><code class=\"swift\">struct Product: Identifiable {   var id: String   var name: String   var price: Double   var description: String }  struct ProductView: View {   var product: Product      var body: some View {     VStack(alignment: .leading) {       Text(product.name)         .font(.headline)       Text(product.description)         .font(.subheadline)       Text(\"$\\(product.price)\")         .font(.title)     }     .padding()   } }<\/code><\/pre>\n<p>Then, I&#8217;ll create a <code>ProductListView<\/code> to fetch and list the products:<\/p>\n<pre><code class=\"swift\">import FirebaseFirestore  struct ProductListView: View {   @State private var products = [Product]()      var body: some View {     List(products) { product in       ProductView(product: product)     }     .onAppear() {       fetchProducts()     }   }      func fetchProducts() {     Firestore.firestore().collection(\"products\").getDocuments() { querySnapshot, error in       if let error = error {         print(error.localizedDescription)         return       }              self.products = querySnapshot?.documents.compactMap { document -> Product? in         let data = document.data()                  guard let name = data[\"name\"] as? String,               let price = data[\"price\"] as? Double,               let description = data[\"description\"] as? String         else {           return nil         }                  return Product(id: document.documentID, name: name, price: price, description: description)       } ?? []     }   } }<\/code><\/pre>\n<h3>Step 5: Shopping Cart<\/h3>\n<p>First, I&#8217;ll create a <code>Cart<\/code> model and a <code>CartView<\/code>. In the <code>CartView<\/code>, I&#8217;ll list all the products in the cart and calculate the total price:<\/p>\n<pre><code class=\"swift\">struct CartProduct: Identifiable {   var id: String   var product: Product   var quantity: Int }  struct CartView: View {   @State private var cartProducts = [CartProduct]()      var body: some View {     VStack {       List(cartProducts) { cartProduct in         HStack {           Text(cartProduct.product.name)           Spacer()           Text(\"x\\(cartProduct.quantity)\")           Text(\"$\\(cartProduct.product.price * Double(cartProduct.quantity))\")         }         .padding()       }              Text(\"Total: $\\(cartProducts.reduce(0) { $0 + $1.product.price * Double($1.quantity) })\")         .font(.headline)         .padding()     }   }      func fetchCart() {     \/\/ Here, I'll fetch cart products from Firestore...   } }<\/code><\/pre>\n<p>In the <code>ProductView<\/code>, I&#8217;ll add an &#171;Add to Cart&#187; button:<\/p>\n<pre><code class=\"swift\">struct ProductView: View {   var product: Product      var body: some View {     VStack(alignment: .leading) {       Text(product.name)         .font(.headline)       Text(product.description)         .font(.subheadline)       Text(\"$\\(product.price)\")         .font(.title)       Button(action: {         addToCart(product)       }) {         Text(\"Add to Cart\")       }     }     .padding()   }      func addToCart(_ product: Product) {     \/\/ Here, I'll add the product to the cart in Firestore...   } }<\/code><\/pre>\n<p>In both <code>fetchCart()<\/code> and <code>addToCart(_:)<\/code>, I&#8217;ll need to implement the logic to interact with Firestore. The cart could be a subcollection in each user document, where each document in the cart collection represents a cart product, with <code>productId<\/code>, <code>quantity<\/code>, and <code>addedAt<\/code> fields.<\/p>\n<h3>Conclusion<\/h3>\n<p>While this is a simplified example, it covers the core features of an e-commerce app: user authentication, product listing, and a shopping cart. Check out <a href=\"https:\/\/iosapptemplates.com\/\" rel=\"noopener noreferrer nofollow\">iOS app templates<\/a> for ready-to-use codebases if you want to save time and energy.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/749488\/\"> https:\/\/habr.com\/ru\/articles\/749488\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-410307","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/410307","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=410307"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/410307\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=410307"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=410307"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=410307"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}