Great content man! I’ve been developing iOS apps for 6 years, but now decided to learn SwiftUI from this playlist. Great course and I like your style of coding and the small details you mention to keep the code clean and modular. Keep up the good work bro🌹
@andresraigoza20822 жыл бұрын
I'm Amazed at how short and efficient this code can be. This is so cool!!!. Thank you so much for sharing!!! 😀
@penguinwolf01252 жыл бұрын
16:40 You saying combine is the future of iOS development because you didn't know that a few months later Async Await was coming to our lives 😂 I love the way you teach, keep going!!
@codyclay882 жыл бұрын
This is great, Nick. I come from an Angular/RxJS background so I am super happy to hear that I can take a lot of those skills and apply it to SwiftUI. This was a very well explained video and answered the exact questions I was having. Hope you have a blessed rest of your day, brother!
@SwiftfulThinking2 жыл бұрын
That's awesome to hear. Thanks Cody!
@littlechef3692 Жыл бұрын
great tutorial with real inputs for production environment.. keep it up man
@ortezan41862 жыл бұрын
Looked through this video 2 times and mostly understood what you are explaining. Week later, reopened project and .... rewatching again. 😥Its hard to become developer
@cruiseqe23 жыл бұрын
Enjoying the series but have a question about this episode. As you have a func filterCoins with two parameters (text:, coins:), I would have expected you to have mentioned them on the line .map(filterCoins), but you didn't, for some reason! I don't understand how you can get away with that!
@AZMerf3 жыл бұрын
Ha. I have the same question. It doesn’t show as optional so why does this function not complain?
@obelix84773 жыл бұрын
tldr: Functions, like filterCoins, are first class types in Swift, similar to boolean, String, Double. Because functions are types, Swift can infer a function's signature. This is the magic of Swift and type inference. When you declare a variable you don't have to declare the variable's type, if Swift can infer the type. let friend = "Oelbaum" [T] This means the variable named myFilterFunction is not a string. It's not a boolean. The variable myFilterFunction can hold a multi-line, complex function. However, the function MUST accept a string and an array of CoinModels. Inside the function you can do whatever you want, but then the function MUST return another array of some type. Back to the .map in your subscriber. Here Swift says if you are going to use the .map, you MUST give me a function that takes a string and an array of CoinModels. Also, your function must return another array. Do you have such a thing in your code? Yes! the function filterCoins IS a function with this very specific signature. Swift infers the two parameters, because it's Swift.
@cruiseqe23 жыл бұрын
@@obelix8477 Thank you very much for your very comprehensive explanation.
@SwiftfulThinking3 жыл бұрын
Swift is very smart. Short and elegant code 🥳😇
@danyjamous59869 ай бұрын
A completion is a way to define a function, so we replaced a function by another one. It's like righting filtercoins inside .map which is what it expects
@nizamitagiyev7052 жыл бұрын
Hey Nick! Greate playlist, THX! But I bit confused why you decide to combine fetching coins data and search logic. One of the principles OOP is SRP tell us that "Every module, class or function in a computer program should have responsibility over a single part of that program". Is combining fetching and searching doesn't brake that principle? And one more moment, before we combined logics loading of the coins worked perfectly, but after combining is not 100% to getting data when run app on iPhone...
@varunbhalla19 Жыл бұрын
Combine follows FRP not OOP just like Rx. It focuses on combining or operating over values/events that are received over time from single or multiple sources.
@magicinternetmoney87152 жыл бұрын
Bossman 💪🏼
@cruiseqe23 жыл бұрын
I know that you mentioned that the name of the coin is not visible, well, a little time ago, I changed the leftColumn variable to read private var leftColumn: some View { HStack(spacing: 0) { Text("\(coin.rank)") .font(.caption) .foregroundColor(Color.theme.secondaryText) .frame(minWidth: 30) CoinImageView(coin: coin) .frame(width: 30, height: 30) VStack(alignment: .leading) { Text(coin.symbol.uppercased()) .font(.headline) .foregroundColor(Color.theme.accent) Text(coin.name) .font(.caption) .foregroundColor(Color.theme.secondaryText) } .frame(width: 130, alignment: .leading) .padding(.leading, 15) } } Which will show the name of the coin underneath the symbol.
@SwiftfulThinking3 жыл бұрын
Nice solution Mark!
@Awesome奥深2 жыл бұрын
Fantastic, i got some inspiration from you video.
@MAHOSSAN1 Жыл бұрын
can you please write the unit test case for search function with combine latest ?. Good and clear explanation . Thanks
@NishantNarola3 жыл бұрын
how can i do pagination in the home screen list, lets say per page 20 as i am new to swift ui
@SwiftfulThinking3 жыл бұрын
Hey Nishant! You could start by updating the page number in the URL request!
@NishantNarola3 жыл бұрын
how do i dismiss keyboard when tap outside screen and also when i am backspacing and textfield is empty then also it should get dismissed
@AZMerf3 жыл бұрын
Would it make any sense to also check to see if there are returned values? In other words, if the user types “ggg” and the search returns nothing (assuming), and then the user types a fourth “g”, why bother doing the search again since it’s going to come up empty.
@SwiftfulThinking3 жыл бұрын
Hey Merrill, if we were performing an complex/elastic search (something that's making API calls and costing money), then this would be a great solution. But here, we are doing the filtering locally (because we have all the data already) so we *could* definitely do that... but it's not going to improve performance that much.
@TheCstriker3 жыл бұрын
How is the view displaying the full list of coins if you reassign the value of all coins when filtering? Meaning after you tap the X on the search field
@rajanmaheshwari Жыл бұрын
The dataService.allCoins has full coins and the coins variable is reassigned whenever a publisher is called again. So every time in the beginning, the coins variable always has full coins. So in short the filter function's coin array parameter is always having full coins and then it is filtered.
@Nunny253 жыл бұрын
like magic :-) When I finished typing and I can see result - the keyboard is still visible. How can I close it. By "x.mark" button is not possible, because I erase text and I see all list again.
@SwiftfulThinking2 жыл бұрын
It might be a good time to use the new @FocusState idk
@the_kingdom2 жыл бұрын
@@SwiftfulThinking Where & how exactly should we use @FocusState so the keyboard will be dismissed (if no 'x' is present) like when someone uses the delete/backspace button to delete all text that they just entered into the search box. The 'x' is gone and the keyboard is still present. Looks like a few people have this same question.
@vishwaj2111 Жыл бұрын
@@the_kingdom I used the @FocusState variable in the HomeView, with a .onTapGesture on the "content layer" (VStack) to be set to 'false'. Now I can cancel the keyboard whenever I tap on anywhere outside of the search box. Also just fyi, I have another @FocusState variable in the SearchBarView attached to the search TextFiled to bring back the keyboard to be able to type the search phrases.😀 ... Ideally though, there should be a cancel button next to the search bar to dismiss the keyboard (like most of the popular apps)
@williamwildsmith51622 жыл бұрын
At 13:00 in the video, if you wanted to keep the text and coins parameters in the map line, what would you type in? PS: Nick, you are going to go far!
@cinquain03 жыл бұрын
Great content
@SwiftfulThinking3 жыл бұрын
Thanks again James
@MarcoDonati3 жыл бұрын
Hi Nick, really great code! Just one doubt: I'd have put the .debounce operator right after the $searchText publisher. Putting it after the combine could give the impression that we debounce on the combination of the two publishers, so also on the coin download (this is obviously not happening but...). what do you think?
@obelix84773 жыл бұрын
Nice catch. But in his code, download only happens once, when the dataService is first initialized. After that, no other code ever updates the dataService.$allCoins with new data. So, in effect, debounce is only applied when the searchText subscriber is activated? In Nick's code, there isn't any situation where the dataServices publisher (the allCoins variable) is called in rapid succession. That is, you are not going to ask the internet to send you 250 coins more than once. Even if you do ask for it, to update mid-day prices, for example, you probably won't ask for data several times within a 1/2 second. If you did add a "refresh prices" button to your screen, and a users pushed it repeatedly, wouldn't you want the debounce? Wouldn't you want your interface to only refresh once with the latest set of coin prices, and not dozens of times?
@MarcoDonati3 жыл бұрын
@@obelix8477 Hi! Thanks for your answer, I agree with everything you said, it was just a thought. Except maybe... if I had to put a "refresh price" button, first thing in the action would be to cancel previous subscription, so debouching that could be not needed... (?) So many things to try...:-)
@SwiftfulThinking3 жыл бұрын
Hi Marco / NoSoFamous Dogg! This is a thread to be honest. These are the types of conversations professional devs would have 😝 I'm not going to answer it just yet, because we're actually going to add more to this subscriber later on 😈