Top Apps For Finding Recipes For Ingredients You Already Have
Feb 20, 2020 Although this is technically a recipe app, ChefTap has an impressively intuitive built-in grocery-list organization tool to make your favorite saved recipes come to life. ChefTap automatically clips recipes from any site and saves them into the app's permanent archive without any cutting and pasting, highlighting text, or hidden third-party sites involved. This app is a recipe manager with search and import possibilities of components. Create your own virtual cookbook with unique functions and add thousands of recipes there according to your taste. When you found a new recipe just add it to My Cookbook.
Do you ever look through your pantry and fridge wondering what you could possibly make with what seems to be an impossible mystery basket off of “Chopped”? Well, there’s an app for that – several, in fact! As a culinary academy student, you’re learning what flavors and textures work together. Here are seven apps that can help:
- Alongside the basics like a menu planner, grocery list, and recipe clipping, BigOven also gives you access to around 350,000 recipes in the app as well as a scanner for handwritten recipes.
- Get dinner on the table with less fuss and more fun! The Allrecipes Dinner Spinner app gives you instant access whether you are at home, in the store or on the go to Allrecipes’ amazing collection of recipes, photos, videos, collections, ratings and reviews created and shared by 50 million home cooks.
1. SuperCook
SuperCook is to the rescue, helping you waste less food and eat fantastic meals. This website is simple and effective, and there’s no need to download or install anything on your phone.
Start by selecting ingredients you already have on hand from several categories (such as meat, seasoning and dairy).
As you add available ingredients, SuperCook suggests recipes, updating results for each new item you include.
From there, you can narrow down your results by selecting the type of meal you want to make (such as soups, salads, casseroles, you name it), type of cuisine and the star ingredient.
Once you get into the habit of using SuperCook, you’ll probably find yourself doing the same things again and again. If you want to save your ingredients and favorite recipes, you can make a profile.
2. Allrecipes Dinner Spinner
Allrecipes is available on multiple devices, including tablet and smartphone. You can find recipes by browsing through categories such as dietary restrictions, ingredients, cuisine type, meal type, season and cooking technique.
Searching by ingredient allows you to set your parameters based on what you have available.
The easiest search is with the “dinner spinner,” a tool that lets you quickly spin through a combination of options by dish type, ingredients on-hand, and how long before the meal is ready.
In fact, the app lets you list ingredients to include or omit in recipe results. That way, if you don’t have chicken in the fridge, the app won’t show any recipes that contain chicken, even if you have all of the other necessary ingredients for a certain dish.
Save your recipes and ingredients by creating an account – you can log in anywhere, including on your phone, tablet or computer.
3. BigOven
Mac osx apps & download. With more than 500,000 recipes in its database, BigOven is certainly, well, big.
This app lets you navigate and brainstorm in a number of ways. For instance, check out the Ideas section to browse through meal inspiration. There you’ll find categories like “Use Up Leftovers,” which curates recipes based on reusing ingredients.
The Collections area includes recipe ideas for healthy breakfasts, healthy snacks, meat-free, soups, low-carb, and more. Most recipes come with nutritional facts that include the number of calories per serving.
The Grocery List section allows you to sort by ingredient and keep tabs on what you’ll need to make a certain meal. Quickly add items to your list for easy shopping the next time you’re out.
The Planner lets you come up with dishes for the future so you’re not stuck trying to compose a meal with random ingredients again.
4. Epicurious
Epicurious is an app that’s both beautiful to look at and easy to use. You can toggle through ingredients to find recipe ideas, many of which feature photos of the finished dish and instructional videos to help you along the way.
Quickly browse recipes by adding filters such as “leftovers,” “dinner,” and any dietary restrictions such as “gluten free,” “dairy free,” “keto friendly” and so on.
Next, add the main ingredient you wish to search for in the search area, and then sort your list by the highest rated recipes, the percentage of users who would make it again, and other criteria.
The app also includes a kitchen timer to help you cook ingredients to perfection even without a recipe, and a tool that finds local, seasonal ingredients.
Recipe App Ios Mac Download
5. Cookpad
Cookpad is part recipe finder, part social platform. You can search for recipes by ingredients and share what you’re making.
Invented a fantastic recipe you want to share? Post it publicly along with an image so other users can test it out. List the ingredients, snap an image, and write your story. If people like what you’re posting, they can follow you.
Of course, you can also follow people who make recipes that match your preferences, and even ask them questions.
To start a conversation, go to the chat area and turn on notifications so you know when others reply. You can also search conversations to see what others are talking about, and join in.
And people are talking on Cookpad from around the world! Founded more than 20 years ago in Japan, the app has more than 100 million users in 23 countries. In addition to English, Cookpad is available in Spanish, French, Italian, and 20 other languages.
Other search terms you can use include dietary restrictions, recipe names and holidays. Basically, any category you can think of.
6. Tasty
Tasty became popular for its overhead food videos with instructions for each step as you prepare a dish. But it’s also a handy tool to search for recipes you can make with whatever you already have on hand.
Search by ingredients, then add filters such as “dinner,” “brunch,” and any dietary restrictions. You can also search by occasion, whether it’s date night, weeknight, or game day.
For the easiest meals, search for “5 ingredients or less” and “under 30 minutes.”
Once you make your selection, the recipe video plays, displaying ingredient measures and other instructions right on the screen, in sync with the video. For efficiency, the videos play at a faster speed, but you can pause and unpause the videos as you go.
Some of Tasty’s most-watched videos are reportedly those featuring cheese, steak, bacon and pasta—perhaps ingredients you have on hand now?
7. America’s Test Kitchen
America’s Test Kitchen (ATK) is America’s most-beloved home cook television program, featuring episodes such as, “The Perfect Cookie,” “Just Add Apples,” and “All Chocolate, All The Time.” So it’s no surprise that the ATK app is quickly becoming the digital tool of choice for serious home cooks.
The catch? It’s only available to members of ATK’s online cooking school. Still, for the serious home cook, it’s a great option, with full courses featuring special instruction from ATK and Escoffier chefs. So be sure to use this app only when you have time to learn and refine your technique.
Search by main ingredient, such as pasta or vegetables, level of difficulty, and recipe type. Keep track of the courses you’ve completed, and take advantage of your exclusive access to world-class chefs and instructors.
Recommended Posts
by Khoa Pham
I started iOS development when iOS 7 had been announced. And I have learned a bit, through working, advice from colleagues and the iOS community.
![Running ios app on mac Running ios app on mac](/uploads/1/3/4/2/134205937/121944623.jpg)
In this article, I’d like to share a lot of good practices by taking the example of a simple recipes app. The source code is at GitHub Recipes.
The app is a traditional master detail application that showcases a list of recipes together with their detailed information.
There are thousands of ways to solve a problem, and the way a problem is tackled also depends on personal taste. Hopefully, throughout this article you’ll learn something useful — I did learn a lot when I did this project.
I’ve added links to some keywords where I felt further reading would be beneficial. So definitely check them out. Any feedback is welcome.
So let’s get started…
Here is a high level overview of what you’ll be building.
Getting started
Let’s decide on the tool and project settings that we use.
Xcode and Swift version
At WWDC 2018, Apple introduced Xcode 10 with Swift 4.2. However, at the time of writing, Xcode 10 is still in beta 5. So let’s stick with the stable Xcode 9 and Swift 4.1. Xcode 4.2 has some cool features — you can play with it through this awesome Playground. It does not introduce huge changes from Swift 4.1, so we can easily update our app in the near future if required.
You should set the Swift version in the Project setting instead of the target settings. This means all targets in the project share the same Swift version (4.1).
Minimum iOS version to support
As of summer 2018, iOS 12 is in public beta 5 and we can’t target iOS 12 without Xcode 10. In this post, we use Xcode 9 and the base SDK is iOS 11. Depending on the requirement and user bases, some apps need to support old iOS versions. Although iOS users tend to adopt new iOS versions faster than those who use Android, there are a some that stay with old versions. According to Apples advice, we need to support the two most recent versions, which are iOS 10 and iOS 11. As measured by the App Store on May 31, 2018, only 5% of users use iOS 9 and prior.
Targeting new iOS versions means we can take advantages of new SDKs, which Apple engineers improve every year. The Apple developer website has an improved change log view. Now it is easier to see what has been added or modified.
Ideally, to determine when to drop support for old iOS versions, we need analytics about how users use our app.
Organising the Xcode project
When we create the new project, select both “Include Unit Tests” and “Include UI Tests” as it a recommended practice to write tests early. Recent changes to the XCTest framework, especially in UI Tests, make testing a breeze and are pretty stable.
Before adding new files to the project, take a pause and think about the structure of your app. How do we want to organize the files? We have a few options. We can organize files by feature/module or role/types. Each has its pros and cons and I’ll discuss them below.
By role/type:
- Pros: There is less thinking involved about where to put files. It’s also easier to apply scripts or filters.
- Cons: It’s hard to correlate if we would want to find multiple files related to the same feature. It would also take time to reorganise files if we want to make them into reusable components in the future.
By feature/module
- Pros: It makes everything modular and encourages composition.
- Cons: It may get messy when many files of different types are bundled together.
Staying modular
Personally, I try to organize my code by features/components as much as possible. This makes it easier to identify related code to fix, and to add new features easier in the future. It answers the question “What does this app do?” instead of “What is this file?” Here is a good article regarding this.
A good rule of thumb is to stay consistent, no matter which structure you choose. ?
Recipes app structure
The following is the app structure that our recipe app uses:
Source
Contains source code files, split into components:
- Features: the main features in the app
- Home: the home screen, showing a list of recipes and an open search
- List: shows a list of recipes, including reloading a recipe and showing an empty view when a recipe does not exist
- Search: handle search and debouncing
- Detail: shows detail information
Library
Contains the core components of our application:
- Flow: contains FlowController to manage flows
- Adapter: generic data source for
UICollectionView
- Extension: convenient extensions for common operations
- Model: The model in the app, parsed from JSON
Resource
Contains plist, resource, and Storyboard files.
Code conventions
I agree with most of the style guides in raywenderlich/swift-style-guide and github/swift-style-guide. These are straightforward and reasonable to use in a Swift project. Also, check out the official API Design Guidelines made by the Swift team at Apple on how to write better Swift code.
Whichever style guide you choose to follow, code clarity must be your most important goal.
Indentation and the tab-space war is a sensitive topic, but again, it depends on taste. I use four spaces indentation in Android projects, and two spaces in iOS and React. In this Recipes app, I follow consistent and easy-to-reason indentation, which I have written about here and here.
Documentation
Good code should explain itself clearly so you don’t need to write comments. If a chunk of code is hard to understand, it’s good to take a pause and refactor it to some methods with descriptive names so it’s the chunk of code is more clear to understand. However, I find documenting classes and methods are also good for your coworkers and future self. According to the Swift API design guidelines,
Write a documentation comment for every declaration. Insights gained by writing documentation can have a profound impact on your design, so don’t put it off.
It’s very easy to generate comment template
///
in Xcode with Cmd+Alt+/
. If you plan to refactor your code to a framework to share with others in the future, tools like jazzy can generate documentation so other people can follow along.Marking sections of code
The use of
MARK
can be helpful to separate sections of code. It also groups functions nicely in the Navigation Bar. You can also use extension
groups, related properties and methods.For a simple
UIViewController
we can possible define the following MARKs:Source control
Git is a popular source control system right now. We can use the template
.gitignore
file from gitignore.io/api/swift. There are both pros and cons in checking in dependencies files (CocoaPods and Carthage). It depends on your project, but I tend to not commit dependencies (node_modules, Carthage, Pods) in source control to not clutter the code base. It also makes reviewing Pull requests easier.Whether or not you check in the Pods directory, the Podfile and Podfile.lock should always be kept under version control.
I use both iTerm2 to execute commands and Source Tree to view branches and staging.
Dependencies
I have used third party frameworks, and also made and contributed to open source a lot. Using a framework gives you a boost at the start, but it can also limit you a lot in the future. There may be some trivial changes that are very hard to work around. The same thing happens when using SDKs. My preference is to pick active open source frameworks. Read the source code and check frameworks carefully, and consult with your team if you plan to use them. A bit of extra caution does no harm.
In this app, I try to use as few dependencies as possible. Just enough to demonstrate how to manage dependencies. Some experienced developers may prefer Carthage, a dependency manager as it gives you complete control. Here I choose CocoaPods because its easy to use, and it has worked great so far.
There’s a file called
.swift-version
of value 4.1
in the root of the project to tell CocoaPods that this project uses Swift 4.1. This looks simple but took me quite some time to figure out. ☹️Getting into the project
Let’s craft some launch images and icons to give the project a nice look.
API
The easy way to learn iOS networking is through public free API services. Here I use food2fork. You can register for an account at http://food2fork.com/about/api. There are many other awesome APIs in this public-api repository.
It’s good to keep your credentials in a safe place. I use 1Password to generate and store my passwords.
Before we start coding, let’s play with the APIs to see which kinds of requests they require and responses they return. I use the Insomnia tool to test and analyze API responses. It’s open source, free, and works great. ?
Launch screen
The first impression is important, so is the Launch Screen. The preferred way is using
LaunchScreen.storyboard
instead of a static Launch image.To add a launch image to
Asset Catalog
, open LaunchScreen.storyboard
, add UIImageView
, and pin it to the edges of UIView
. We should not pin the image to the Safe Area as we want the image to be full screen. Also, unselect any margins in the Auto Layout constraints. Set the contentMode
of the UIImageView
as Aspect Fill
so it stretches with the correct aspect ratio.App icon
A good practice is to provide all the necessary app icons for each device that you support, and also for places like Notification, Settings, and Springboard. Make sure each image has no transparent pixels, otherwise it results in a black background. This tip is from Human Interface Guidelines - App Icon.
Keep the background simple and avoid transparency. Make sure your icon is opaque, and don’t clutter the background. Give it a simple background so it doesn’t overpower other app icons nearby. You don’t need to fill the entire icon with content.
We need to design square images with a size greater than 1024 x 1024 so each is able to downscale to smaller images. You can do this by hand, script, or use this small IconGenerator app that I made.
The IconGenerator app can generate icons for iOS in iPhone, iPad, macOS and watchOS apps. The result is the
AppIcon.appiconset
that we can drag right into the Asset Catalog. Asset Catalog is the way to go for modern Xcode projects.Linting code with SwiftLint
Regardless of what platform we develop on, it’s good to have a linter to enforce consistent conventions. The most popular tool for Swift projects is SwiftLint, made by the awesome people at Realm.
To install it, add
pod 'SwiftLint', '~> 0.
25' to the Podf
ile. It's also a good practice to specify the version of the dependencies so pod inst
all won’t accidentally update to a major version that could break your app. Then add a .swiftlint.
yml with your preferred configuration. A sample configuration can be found here.Finally, add a new Run Script Phrase to execute
swiftlint
after compiling.Type-safe resource
I use R.swift to safely manage resources. It can generate type-safe classes to access font, localisable strings, and colors. Whenever we change resource file names, we get compile errors instead of a implicit crash. This prevents us inferring with resources that are actively in use.
Show me the code
Let’s dive into the code, starting with the model, flow controllers and service classes.
Designing the model
It may sound boring but clients are just a prettier way to represent the API response. The model is perhaps the most basic thing and we use it a lot in the app. It plays such an important role but there can be some obvious bugs related to malformed models and assumptions about how a model should be parsed that need to be considered.
We should test for every model of the app. Ideally, we need automated testing of models from API responses in case the model has changed from the backend.
Starting from Swift 4.0, we can conform our model to Codable to easily serialise to and from JSON. Our Model should be immutable:
We can use some test frameworks if you like fancy syntax or an RSpec style. Edit app metadata mac. Some third party test frameworks may have issues. I find
XCTest
good enough.Better navigation with FlowController
Before, I used Compass as a routing engine in my projects, but over time I’ve found that writing simple Routing code works too.
The FlowController is used to manage many
UIViewController
related components to a common feature. You may want to read FlowController and Coordinator for other use cases and to get a better understanding.There is the
AppFlowController
that manages changing rootViewController
. For now it starts the RecipeFlowController
.RecipeFlowController
manages (in fact it is) the UINavigationController
, that handles pushing HomeViewController, RecipesDetailViewController, SafariViewController
.The
UIViewController
can use delegate
or closure
to notify FlowController
about changes or next screens in the flow. For delegate
there may be a need to check when there are two instances of the same class. Here we use closure
for simplicity.Auto Layout
Auto Layout has been around since iOS 5, it gets better each year. Although some people still have a problem with it, mostly because of confusing breaking constraints and performance, but personally, I find Auto Layout to be good enough.
I try to use Auto Layout as much as possible to make an adaptive UI. We can use libraries like Anchors to do declarative and fast Auto Layout. However in this app, we’ll just use the
NSLayoutAnchor
since it is from iOS 9. The code below is inspired by Constraint. Remember that Auto Layout in its simplest form involves toggling translatesAutoresizingMaskIntoConstraints
and activating isActive
constraints.There are actually many other layout engines available on GitHub. To get a sense over which one would be suitable to use, check out the LayoutFrameworkBenchmark.
Architecture
Architecture is probably the most hyped and discussed topic. https://tqxwyt.weebly.com/blog/how-to-get-macos-mojave-apps-to-close-immediately. I’m a fan of exploring architectures, you can view more posts and frameworks about different architectures here.
To me, all architectures and patterns define roles for each object and how to connect them. Remember these guiding principles for your choice of architecture:
- encapsuate what varies
- favor composition over inheritance
- program to interface, not to implementation
After playing around with many different architectures, with and without Rx, I found out that simple MVC is good enough. In this simple project, there is just
UIViewController
with logic encapsulated in helper Service
classes,Massive View Controller
You may have heard people joking about how massive
UIViewController
is, but in reality, there is no massive view controller. It’s just us writing bad code. However there are ways to slim it down.In the recipes app I use,
Service
to inject into the view controller to perform a single taskGeneric View
to move view and controls declaration to theView
layerChild view controller
to compose child view controllers to build more features
Here is a very good article with 8 tips to slim down big controllers.
Access Control
The SWIFT documentation mentions that “access control restricts access to parts of your code from code in other source files and modules. This feature enables you to hide the implementation details of your code, and to specify a preferred interface through which that code can be accessed and used.”
Everything should be
private
and final
by default. This also helps the compiler. When seeing a public property, we need to search for it across the project before doing anything further with it. If the property is used only within a class
, making it private
means we don't need to care if it breaks elsewhere.Declare properties as
final
where possible.Declare properties as
private
or at least private(set)
.Lazy properties
For properties that can be accessed at a later time, we can declare them as
lazy
and can use closure
for fast construction.We can also use
make
functions if we plan to reuse the same function for multiple properties.This also matches advice from Strive for Fluent Usage.
Begin names of factory methods with “make”, For example,
x.makeIterator()
.Code snippets
Some code syntax is hard to remember. Consider using code snippets to auto generate code. This is supported by Xcode and is the preferred way by Apple engineers when they demo.
I made a repo with some useful Swift snippets that many enjoy using.
Networking
Networking in Swift is kind of a solved problem. There are tedious and error-prone tasks like parsing HTTP responses, handling request queues, handling parameter queries. I’ve seen bugs about PATCH requests, lowercased HTTP methods, … We can just use Alamofire. There’s no need to waste time here.
For this app, since it’s simple and to avoid unnecessary dependencies. We can just use
URLSession
directly. A resource usually contains URL, path, parameters and the HTTP method.A simple network service can just parse
Resource
to URLRequest
and tells URLSession
to executeUse dependency injection. Allow caller to specify
URLSessionConfiguration
. Here we make use of Swift default parameter to provide the most common option.I also use URLQueryItem which was from iOS 8. It makes parsing parameters to query items nice and less tedious.
How to test Networking code
We can use URLProtocol and URLCache to add a stub for network responses or we can use frameworks like Mockingjay which swizzles
URLSessionConfiguration
.I myself prefer using the protocol to test. By using the protocol, the test can create a mock request to provide a stub response.
Implementing cache for offline support
I used to contribute and use a library called Cache a lot. What we need from a good cache library is memory and disk cache, memory for fast access, disk for persistency. When we save, we save to both memory and disk. When we load, if memory cache fails, we load from disk, then update memory again. There are many advanced topics about cache like purging, expiry, access frequency. Have a read about them here.
In this simple app, a homegrown cache service class is enough and a good way to learn how caching works. Everything in Swift can be converted to
Data
, so we can just save Data
to cache. Swift 4 Codable
can serialize object to Data
.The code below shows us how to use
FileManager
for disk cache.To avoid malformed and very long file names, we can hash them. I use MD5 from SwiftHash, which gives dead simple usage
let key = MD5(key)
.How to test Cache
Since I design
Cache
operations to be asynchronous, we need to use test expectation
. Remember to reset the state before each test so the previous test state does not interfere with the current test. The expectation
in XCTestCase
makes testing asynchronous code easier than ever. ?Loading remote Images
I also contribute to Imaginary so I know a bit about how it works. For remote images, we need to download and cache it, and the cache key is usually the URL of the remote image.
In our recipese app, let’s build a simple ImageService based on our
NetworkService
and CacheService
. Basically an image is just a network resource that we download and cache. We prefer composition so we’ll include NetworkService
and CacheService
into ImageService
.We usually have
UICollectionView
and UITableView
cells with UIImageView
. And since cells are reused, we need to cancel any existing request task
before making a new request.Making image loading more convenient for UIImageView
Let’s add an extension to
UIImageView
to set the remote image from the URL. I use associated object
to keep this ImageService
and to cancel old requests. We make good use of associated object
to attach ImageService
to UIImageView
. The point is to cancel the current request when the request is triggered again. This is handy when the image views are rendered in a scrolling list.Generic DataSource for UITableView and UICollectionView
We use
UITableView
and UICollectionView
in almost in every app and almost perform the same thing repeatedly.- show refresh control while loading
- reload list in case of data
- show error in case of failure.
There are many wrappers around
UITableView
and UICollection
. Each adds another layer of abstraction, which gives us more power but applies restrictions at the same time.In this app, I use
Adapter
to get a generic data source, to make a type safe collection. Because, in the end, all we need is to map from the model to the cells.I also utilize Upstream based on this idea. It’s hard to wrap around
UITableView
and UICollectionView
, as many times, it is app specific, so a thin wrapper like Adapter
is enough.Mac Ios Download
Controller and View
I ditched Storyboard because of many limitations and many issues. Instead, I use code to make views and define constraints. It is not that hard to follow. Most of the boilerplate code in
UIViewController
is for creating views and configuring the layout. Let's move those to the view. You can read more about that here.Handling responsibilities with a child View Controller
The View controller container is a powerful concept. Each view controller has a separation of concern and can be composed together to create advanced features. I have used
RecipeListViewController
to manage the UICollectionView
and show a list of recipes.There is the
HomeViewController
which embeds this RecipeListViewController
Composition and Dependency Injection
I try to build components and compose code whenever I can . We see that
ImageService
makes use of the NetworkService
and CacheService
, and RecipeDetailViewController
makes use of Recipe
and RecipesService
Ideally objects should not create dependencies by themselves. The dependencies should be created outside and passed down from root. In our app the root is
AppDelegate
and AppFlowController
so dependencies should start from here.App Transport Security
Since iOS 9, all apps should adopt App Transport Security
App Transport Security (ATS) enforces best practices in the secure connections between an app and its back end. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt; it is also on by default in iOS 9 and OS X v10.11. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one.
In our app, some images are obtained over an
HTTP
connection. We need to exclude it from the security rule, but only for that domain only.A custom Scrollable View
For the detail screen, we can use
UITableView
and UICollectionView
with different cell types. Here, the views should be static. We can stack using UIStackView
. For more flexibility, we can just use UIScrollView
.We pin the
UIScrollView
to the edges. We pin the contentView
left and right anchor to self
, while pinning the contentView
top and bottom anchor to UIScrollView
.Recipe App Ios Mac Pc
The views inside
contentView
have top and bottom constraints, so when they expand, they expand contentView
https://tqxwyt.weebly.com/blog/run-downloaded-apps-on-mac. as well. UIScrollView
uses Auto Layout info from this contentView
to determine its contentSize
. Here is how ScrollableView
is used in RecipeDetailView
.Adding search functionality
From iOS 8 onwards, we can use the UISearchController to get a default search experience with the search bar and results controller. We’ll encapsuate search functionality into
SearchComponent
so that it can be pluggable.Starting from iOS 11, there ‘s a property called
searchController
on the UINavigationItem
which makes it easy to show the search bar on the navigation bar.In this app, we need to disable
hidesNavigationBarDuringPresentation
for now, as it is quite buggy. Hopefully it gets resolved in future iOS updates.Understanding Presentation context
Understanding presentation context is crucial for view controller presentation. In search, we use the
searchResultsController
.We need to use definesPresentationContext on the source view controller (the view controller where we add the search bar into). Without this we get the
searchResultsController
to be presented over full screen !!!When using the currentContext or overCurrentContext style to present a view controller, this property controls which existing view controller in your view controller hierarchy is actually covered by the new content. When a context-based presentation occurs, UIKit starts at the presenting view controller and walks up the view controller hierarchy. If it finds a view controller whose value for this property is true, it asks that view controller to present the new view controller. If no view controller defines the presentation context, UIKit asks the window’s root view controller to handle the presentation.
The default value for this property is false. Some system-provided view controllers, such as UINavigationController, change the default value to true.
Debouncing search actions
We should not execute search requests for every key stroke the user types in the search bar. Therefore some kind of throttling is needed. We can use
DispatchWorkItem
to encapsulate the action and send it to the queue. Later we can cancel it.Testing debouncing with Inverted expectation
To test
Debouncer
we can use XCTest
expectation in inverted mode. Read more about it in Unit testing asynchronous Swift code.To check that a situation does not occur during testing, create an expectation that is fulfilled when the unexpected situation occurs, and set its isInverted property to true. Your test will fail immediately if the inverted expectation is fulfilled.
Testing user interface with UITests
Sometimes small refactoring can have a large effect. A disabled button can lead to unusable screens afterward. UITest helps ensuring integrity and functional aspects of the app. Test should be declarative. We can use the Robot pattern.
Here are some of my articles regarding testing.
Main thread guard
Accessing the UI from the background queue can lead to potential problems. Earlier, I needed to use MainThreadGuard, now that Xcode 9 has Main Thread Checker, I just enabled that in Xcode.
The Main Thread Checker is a standalone tool for Swift and C languages that detects invalid usage of AppKit, UIKit, and other APIs on a background thread. Updating UI on a thread other than the main thread is a common mistake that can result in missed UI updates, visual defects, data corruptions, and crashes.
Measuring performances and issues
We can use Instruments to thoroughly profile the app. For quick measurement, we can head over to the
Debug Navigator
tab and see CPU, Memory and Network usage. Check out this cool article to learn more about instruments.Prototyping with Playground
Playground is the recommended way to prototype and build apps. At WWDC 2018, Apple introduced Create ML which supports Playground to train model. Check out this cool article to learn more about playground driven development in Swift.
Where to go from here
Thanks for making it this far. I hope you’ve learnt something useful. The best way to learn something is to just do it. If you happen to write the same code again and again, make it as a component. If a problem gives you a hard time, write about it. Share your experience with the world, you will learn a lot.
I recommend checking out the article Best places to learn iOS development to learn more about iOS development.
If you have any questions, comments or feedback, don’t forget to add them in the comments. And if you found this article useful, don’t forget to clap. ?
If you like this post, consider visiting my other articles and apps ?