Wednesday, May 31, 2017

Tuesday, May 30, 2017

How to Create a Short How-to Video Tutorial for Instagram

Ensure High-Quality Android Code With Static Analysis Tools

How to Create a Mountain Landscape in Flat Style in Adobe Illustrator

Get Started With Vue in Our New Course

How to Apply a Website Redesign Checklist in 10 Easy Steps

How to Use a BigCommerce Theme to Design Your Online Store

Unity Terrain Engine Tools

How to Create a Floral Portrait Photo Manipulation in Adobe Photoshop

How to Create an Artistic Watercolor Background Effect (With a Photoshop Action)

How to Keep a Mac Efficient and Well Maintained—Part 4

Monday, May 29, 2017

How to Use Gradient Mesh to Create Strawberries in a Milk Splash in Adobe Illustrator

Get Started With Ionic Services: Push

How to Protect Cells, Sheets, and Workbooks in Excel

Building Your Startup: Approaching Major Feature Enhancements

The Pool Window in Cubase—Part 3

The Pool Window in Cubase—Part 3

How to Fix Missing Files

Sometimes when working with huge projects, there are cases where the project files go missing. 

This might be because you renamed the folder containing the files, or moved the folder to save space or it could be due to another reason. Unless you specify  Cubase that the files have been moved to another location, Cubase will accept the files as missing and will continue the project without the missing files.

Cubase has an in-built function that helps find the missing files that are being used in a given project and it can re-link them into the project.

To do this, open the Find Missing Files option from the Media menu. In the dialog box that appears, you'll find the list of the files that are missing from the project. 

Select either of the three options:

  1. Locate: With this option, select the location of the file manually. Use this option if you're sure of the location of the missing file or if you have moved the file to a specific location. This option helps manually select the file and re-link it to the project. If you have renamed the file to something else, this option is the best bet to re-link it back to the project
  2. Folder: Selects the folder in which the file was moved. If you have moved the file to a new folder without renaming it, you can re-link it using this method. Select the folder and Cubase automatically detects the correct file and link it to the project
  3. Search: With this option, select a disk or a folder in which Cubase can search and find the file that is missing. Specify whether the search term is case-sensitive or not. Once the drive or folder is , click on Start and Cubase will search the specific location and find the files for you. If there are more missing files in the project and they are in the location that you specified, they'll also be re-linked into the project. Once the missing files are found, click on Accept

Sometimes, if the file that is missing was created by an edit, you can use the Reconstruct option in the Pool window. This re-creates the files by using the original file and processing it to create the missing file.

Cubase also has an option to remove the files that are missing in the project. Select Remove Missing Files in the Pool window and Cubase will remove the missing files from the Pool and from the project.

This option is very useful when you have to share your project with someone else. By removing the missing files from the project, once the other person opens the project, there will be no warnings saying that some files are missing from the session. Doing this will help reduce the size of a project and enable easy sharing.

Auditioning Clips

Auditioning clips in Cubase is easy and it's possible to audition clips in many different ways. The three main methods are described below:

  1. Spacebar: The easiest method to audition a clip. Just as in Pro Tools, use the spacebar to audition a clip. You need to activate the Playback Toggle Triggers Local Preview option found under File > Preferences > Transport. To stop the preview, press the spacebar again
  2. Audition Button: Use the Audition button on the top left corner of the Pool Window to audition the audio. To stop the audio, click the same button again
  3. Waveform: An interesting way to audition clips. Click on the waveform and the playback starts from the place you clicked. It plays from that position to the end of the clip. To stop the playback, just click anywhere in the Pool window or on the Audition button

To loop a clip in the audition stage, click on the Loop button besides the Audition button.

The clip loops until the Stop button or Loop button is pressed again. In this mode, if you click on the waveform of the clip, the playback starts from the point that you clicked on the waveform and again start from the beginning once the clip has been played back.

You can adjust the level of the playback by adjusting the fader on the right side of the audition button. 

The default playback route is via the Control Room, if the Control Room is set up, else the audio will be routed through the main bus itself.

Conclusion

In this tutorial, I've shown you how to fix the missing files in a project and to audition clips in the Pool Window

Including these methods in projects speeds up workflow. Let me know in the comments below how you use the Pool Window.


5 Camera Settings for the Best Drone Camera Footage

How to Draw a Mushroom

Best MailChimp Templates to Level Up Your Business Email Newsletter

Friday, May 26, 2017

How to Create a Graffiti Effect in Adobe Photoshop

How to Make a Video Tutorial

Programming With Yii: Generating Documentation

How to Plan a Successful Small Business Exit Strategy

Create an Intelligent App With Google Cloud Speech and Natural Language APIs

Extending HTML by Creating Custom Tags

How to Create a Colorful Salad Plate in Adobe Illustrator

10 Best Keynote Presentation Templates

4 Useful Things You Can Do With the Touch Bar

Rigging of Hulk: Part 3

Thursday, May 25, 2017

How to Create a Dark Futuristic City in Adobe Photoshop

How to Create a Color Dust Action in Adobe Photoshop

How to Define State With Angular UI-Router

Dynamic Page Templates in WordPress, Part 2

How to Add Slicers to Pivot Tables in Excel in 60 Seconds

How to Handle Exceptions in Elixir

How to Handle Exceptions in Elixir

Exception handling is a great practice for any software development methodology. Whether it's for test-based development, agile sprints, or a hacking session with just a good old todo list, we all can benefit from ensuring our bases are covered with a robust approach to defect handling. 

It's paramount to ensure errors are taken care of, whilst being aesthetically pleasing and of course not becoming a big problem logically with cryptic messages for the end user to try and glean meaning from. If you do that, you certainly are on a great route to make a solid, stable and sticky app that users enjoy working with and will recommend highly to others.

Ideally for us, Elixir provides extensive exception handling via several mechanisms such as try/catch, throws, and the {:error, reason} tuple.

To display an error, use raise in your interactive shell to get a first taste:

We can also add a type to this like so:

How Error Handling Works in Elixir

Some of the ways errors are dealt with in Elixir may not be obvious at first glance.

  • Firstly about processes—in using spawn, we can create independent processes. That means a failure on one thread should not affect any other process, unless there was a linkage in some manner. But by default, everything will stay stable.
  • To notify the system of a failure in one of these processes, we can use the spawn_link macro. This is a bidirectional link, which means that if a linked process terminates, an exit signal will be triggered.
  • If the exit signal is anything other than :normal, we know we have a problem. And if we trap the exit signal with Process.flag(:trap_exit, true), the exit signal will be sent to the process's mailbox, where the logic can be placed on how to handle the message, thus avoiding a hard crash.
  • Finally we have Monitors, which are similar to spawn_links, but these are unidirectional links, and we can create them with Process.monitor
  • The process which invokes the Process.monitor will receive the error messages on failure.

For a sample error, try adding a number to an atom and you will get the following:

To ensure the end user does not get errored out, we can use the try, catch and rescue methods provided by Elixir.

Try/Rescue

First in our toolbox for exception handling is try/rescue, which catches errors produced by using raise so is really best suited for developer errors, or exceptional circumstances such as input error.

try/rescue is similar in usage to a try/catch block you may have seen in other programming languages. Let's look at an example in action:

Here we utilize the try/rescue block and the aforementioned raise to catch the RuntimeError

This means the ** (RuntimeError) default output of raise is not displayed, and is replaced with a nicer formatted output from the IO.puts call. 

As a best practice, you must use the error message to give the user useful output in plain English, which helps them with the issue. We'll look at that more in the next example.

Multiple Errors in a Try/Rescue

A major benefit of Elixir is that you can catch multiple outcomes in one of these try/rescue blocks. Look at this example:

Here we have caught two errors in the rescue

  1. If the file is unable to read.
  2. If the :source_file symbol is missing. 

As mentioned before, we can use this for making easy-to-understand error messages for our end user. 

This powerful and minimal syntax approach of Elixir makes writing multiple checks very accessible for us to check many possible points of failure, in a neat and concise way. This helps us to ensure we don't need to write elaborate conditionals making long-winded scripts that may be hard to visualize fully and debug correctly during later development or for a new developer to join.

As always when working in Elixir, KISS is the best approach to take. 

After

There are situations when you will require a specific action performed after the try/rescue block, regardless of if there was any error. For Java or PHP developers, you may be thinking of the try/catch/finally or Ruby's begin/rescue/ensure.

Let's take a look at a simple example of using after.

Here you see the after being used to constantly make a message display (or this could be any function you wished to throw in there).

A more common practice you will find this used on is where a file is being accessed, for example here:

Throws

As well as the raise and try/catch methods we have outlined earlier, we also have the throw and catch macros.

Using the throw method exits execution with a specific value we can look for in our catch block and use further like so:

So here we have the ability to catch anything we throw inside the try block. In this case, the conditional if x == 3 is the trigger for our do: throw(x).

The output from the iteration produced from the for loop gives us a clear understanding of what has occurred programmatically. Incrementally we have stepped forward, and execution has been halted on the catch.  

Because of this functionality, sometimes it can be hard to picture where the throw catch would be implemented in your app. One prime place would be in usage of a library where the API does not have adequate functionality for all outcomes presented to the user, and a catch would suffice to rapidly navigate around the issue, rather than having to develop much more within the library to handle the issue and return appropriately for it.

Exits

Finally in our Elixir error handling arsenal we have the exit. Exiting is done not through the gift shop, but explicitly whenever a process dies. 

Exits are signaled like so:

Exit signals are triggered by processes for one of the following three reasons:

  1. A normal exit: This happens when a process has completed its job and ends execution. Since these exits are totally normal, usually nothing needs to be done when they happen, much like a exit(0) in C. The exit reason for this kind of exit is the atom :normal.
  2. Because of unhandled errors: This happens when an uncaught exception is raised inside the process, with no try/catch/rescue block or throw/catch to deal with it.
  3. Forcefully killed: This happens when another process sends an exit signal with the reason :kill, which forces the receiving process to terminate.

Stack Traces

At any given update juncture on throw, exit or errors, calling the System.stacktrace will return the last occurrence in the current process. 

The stack trace can be formatted quite a bit, but this is subject to change in newer versions of Elixir. For more information on this, please refer to the manual page.

To return the stack trace for the current process, you can use the following:

Making Your Own Errors

Yep, Elixir can do that also. Of course, you always have the built-in types such as RuntimeError at your disposal. But wouldn't it be nice if you could go a step further?

Creating your own custom error type is easy by using the defexception macro, which will conveniently accept the :message option, to set a default error message like so:

Here's how to use it in your code:

Conclusion

Error handling in a meta-programming language like Elixir has a whole heap of potential implications for how we design our applications and make them robust enough for the rigorous bashing of the production environment. 

We can ensure the end user is always left with a clue—a simple and easy-to-understand guiding message, which won't make their task difficult but rather the inverse. Error messages must always be written in plain English and give plenty of information. Cryptic error codes and variable names are no good to the average users, and can even confuse developers!

Going forward, you can monitor the exceptions raised in your Elixir application and set up specific logging for certain trouble spots, so you can analyze and plan your fix, or you can look at using an off-the-shelf solution.

Third-Party Services

Improve the accuracy of our debugging work and enable monitoring for your apps' stability with these third-party services available for Elixir:

  • AppSignal can be very beneficial for the quality assurance phase of the development cycle. 
  • GitHub repo bugsnex is a great project for using the API interface with Bugsnag to further detect defects in your Elixir app.
  • Monitor uptime, system RAM and errors with Honeybadger, which provides production error monitoring so you don't need to babysit your app.

Extending Error Handling Further

Going forward, you may wish to further extend the error handling capabilities of your app and make your code easier to read. For this, I recommend you check out this project for elegant error handling on GitHub

I hope you have gained a further insight from this guide and will be able to practically handle any exception case you need in your Elixir app now! 


6 Preprocessor Features Coming to Native CSS

How to Create a Set of Veil and Hijab Avatars in Adobe Illustrator

Tuesday, May 23, 2017

How to Create a 3D Colorful Illuminated Text Effect in Adobe Photoshop

Top 20+ Premium WordPress Themes (Most Popular For 2017)

Confused About "em" and "rem"? Try Our New Course

How to Keep a Mac Efficient and Well Maintained—Part 3

How to Choose the Best Products to Sell Online in 2017

How to Create a Vintage Music Festival Flyer in Adobe InDesign

Working With MeSH Files in Python: Linking Terms and Numbers

Working With MeSH Files in Python: Linking Terms and Numbers

This tutorial shows how we can use different aspects of Python (i.e. dictionaries, lists, and regular expressions) together to solve different issues. It also shows how we can use Python to link the relationships in the MeSH file, making it easier to understand its hierarchy and structure.

Before moving ahead with this tutorial, you might be wondering what we mean by MeSH. So let's start by defining this term first, and then go into a bit more detail on its structure.

What Is MeSH?

MeSH is an acronym for Medical Subject Headings. It is considered the U.S. National Library of Medicine's controlled vocabulary (thesaurus), which gives uniformity and consistency to the indexing and cataloging of biomedical literature. MeSH, a distinctive feature of MEDLINE, is arranged in a hierarchical manner called the MesH Tree Structure, and is updated annually.

MeSH is thus a nomenclature of medical terms available from the U.S. National Library of Medicine, that aims to create new knowledge by exploiting the relationships among terms that annotate the biomedical literature.  

People searching MEDLINE/PubMed and other databases make use of MeSH to assist with subject searching. The National Library of Medicine (NLM) indexers use MeSH to describe the subject content of journal articles for MEDLINE. Catalogers use MeSH to describe books and audiovisuals in the NLM and other library collections. So MeSH can be used for numerous tasks involving indexing, tagging, searching, retrieving, analyzing, coding, merging, and sharing biomedical text.

MeSH File Structure

MeSH descriptors are organized into 16 categories:

  • A: anatomy
  • B: organisms 
  • C: diseases
  • D: drugs and chemicals
  • E: analytical, diagnostic and therapeutic techniques and equipment
  • F: psychiatry and psychology
  • G: phenomena and processes 
  • H: disciplines and occupations
  • I: anthropology, education, sociology, and social phenomena
  • J: technology, industry, agriculture
  • K: humanities
  • L: information science
  • M: named groups
  • N: health care
  • V: publication characteristics
  • Z: geographicals

You can find more information about the categories from the U.S. National Library of Medicine. As we can see, each category is further divided into subcategories. This structure is, however, not considered an authoritative subject classification system, but rather as an arrangement of descriptors for the guidance and convenience of people who are assigning subject headings to documents or are searching for literature. It is thus not an exhaustive classification of the subject and contains only the terms that have been selected for inclusion in this thesaurus.

Here's some more information on the MeSH Tree Structures:

Because of the branching structure of the hierarchies, these lists are sometimes referred to as "trees". Each MeSH descriptor appears in at least one place in the trees, and may appear in as many additional places as may be appropriate. Those who index articles or catalog books are instructed to find and use the most specific MeSH descriptor that is available to represent each indexable concept. 

Downloading a MeSH File

For the purpose of this tutorial, we need a MeSH file to work with in Python. You can find MeSH file on the NLM download site.

Let's go ahead and download the latest ASCII MeSH file. We can first go to the MeSH FTP Archive: http://ift.tt/28NhyNm, and then choose the 2017 directory. In the asciimesh/ directory, you will find three .bin files: c2017.bind2017.bin, and q2017.bin. Let's download d2017.bin. You can download the file from: http://ift.tt/2rOr33x(27.5 MB).

Linking Terms to Numbers

Let's jump into the core of this article. What we are trying to do is read a MeSH file (i.e. the .bin file you just downloaded), browse through the entries, find all the MeSH numbers for each entry, and list the terms along with their relevant numbers. 

The first thing we would normally do is read the .bin file, as follows:

Notice that we have used the rb mode, meaning that we are reading binary with no line-break translation.

We also need to define an output file where we would store the results (output):

At this point, we want to check the lines that start with MH = (MeSH term) and MN = (MeSH number). I shouldn't do this now, but will show you a snapshot of the MeSH file to have some idea of the structure and to remove any confusions (MH and MN are surrounded by red rectangles, respectively).

A snapshot of the MeSH file

To check lines that start with MH = and MN =, we need to use regular expressions. So, if we want to check the lines that start with MH = followed by any characters, we would do as shown in the code below (I'll get to what line is in a moment). Notice that I have used b instead of r for the regular expression, since we are applying the pattern on a byte object and not a string object, so we should use a byte pattern.

The same thing would apply for the MeSH number, but this time for lines starting with MN =.

Coming back to line, this refers to the lines in the MeSH file. So we would be walking through the file line by line, looking for the MeSH terms and numbers. As you can see from the above MeSH file snapshot, the MeSH term comes before the MeSH number. So, in our code, the MeSH number will always be the number corresponding to the previously captured MeSH term. We will thus do the following:

Let's go through the above code step by step. If we look at the regular expression MH = (.+)$, this is basically telling us to find the literal MH = followed by at least one character. (.) means any character, and + means that it has to be one or more characters, and return everything to the end of the line ($). 

The parenthesis around .+, that is (.+), is a capture group so we can retrieve the result. So, for the MeSH term surrounded by a red rectangle in the above snapshot, the retrieved term will be Calcomycin. The reason we are using if-statements is that some lines will neither start with MH = nor MN =.

For the captured MeSH term and MeSH number, we create a new key-value pair for a dictionary object, as shown in this line of code: numbers[str(number)] = term.

It is important to note that a single MeSH term might have more than one MeSH number. So we concatenate every new MeSH number with the relevant term into a string, as shown in this portion of the code:

Thus in this case we will be having a dictionary object with key-value pairs that consist of a MeSH term as the key, and the concatenation collection of all corresponding MeSH numbers as the value.

What we want to do now is list the different keys (terms), and have the relevant values (numbers) listed under the relevant term. To list the different terms, we do the following:

Finally, we will list the term and its relevant numbers as follows:

Before showing the output of the program, let's put it all together.

Putting It All Together

In this section, I will show you what our full Python program that links the MeSH term to its numbers looks like:

Output

You can download the output from Dropbox (1.77 MB). Taking a sample of the output as shown below, we can see how a MeSH term (Pterygopalatine Fossa) is listed with its MeSH numbers that are grouped immediately underneath.

Conclusion

The tutorial showed how we can use different aspects of Python (i.e. dictionaries, lists, and regular expressions) together to solve different issues. It also shows how we can use Python to work with MeSH files for linking some parts of this complex file in a way that makes it easier to understand its hierarchy and structure, as we did here by linking the MeSH term to its relevant MeSH numbers.


How to Create a Spring Meadow in Adobe Illustrator

SpriteKit Basics: Sprites

How to Create a Paint Splatter Photo Effect (With a Photoshop Action)

Monday, May 22, 2017

How to Make an Explanation (aka Explainer) Video

Get Started With Ionic Services: Auth

How to be an Online Session Musician: Part 2

How to be an Online Session Musician: Part 2

In the previous tutorial How To Be An Online Session Musician: Part 1 I looked at what’s involved with this line of work. In this tutorial I’ll show you what you need to get started. 

The Studio

It is not necessarily the case that you'll need a purpose-built studio but it does depend on the work you do. 

Recording keyboards, for example, don’t require microphones and that means that they can be used almost anywhere. 

If microphones are involved, however, such as for work involving acoustic instruments or voice-overs then you’ll need a dedicated space. A dedicated space could be somewhere reasonably isolated and acoustically-treated that will further improve the probability of quality recordings.

The other advantage to having a work-space is efficiency; if everything’s set up, you can get started quickly and get more done.

About Recording and Production

Knowledge is power. The more you know about related topics then the more quickly, productively, and efficiently you will work. 

If you don’t know your way around the most basic DAW, then this probably isn’t for you. If you don’t know what DAW refers to, then this definitely isn’t for you just yet, but keep reading, because I'll explain later on.

File Formats

In terms of quality, CD standard is what you’re aiming for as a minimum. In technical terms, this is audio sampled at a rate of 44.1KHz, and to a depth of 16 bits. My default setting is 44.1KHz at 24 bits. 

You can use higher settings than this but there’s little to be gained by doing so. Furthermore, the file sizes balloon accordingly and increase subequent upload and download times.

Export work as .wav files; mp3 is fine for demos but not good enough as a finished product.

Hardware, Quality and Cost

You should consider the sort of hardware you’ll need as a minimum to get started, assuming that you haven’t got some or all of this already. Important for any musician is budget.

‘You get what you pay for’ is an age-old maxim meaning that higher cost implies higher quality. There’s still something to be said for this, but it’s not as true as it used to be. 

Companies such as Behringer and SE Electronics produce great gear at very reasonable prices so don’t worry if you can’t afford hideously expensive high-end hardware. Ultimately, what you need is good quality, reliable equipment.

When looking to buy, ensure that you research, read reviews, watch videos and buy the best that falls within your budget. You can always upgrade later.

Here’s a basic, albeit extensive, shopping list.

Laptop or desktop computer

The more powerful the better. Consider the processing power, memory and hard drive. A solid-state drive will be faster and quieter,

Ensure it has a decent set of inputs and outputs. Mac or PC doesn’t matter as much as it used to as most DAWs are now available for both systems.

Storage

Music projects are memory-heavy things, and will eat up your computer’s on-board memory. A 1TB drive may sound huge but you’ll be amazed how quickly you’ll fill it. 

Buy an external hard drive to store work there. Not only will it keep space free on the computer, helping to ensure it runs efficiently, it means that if it crashes all of the work is safe on an external drive. 

As always, go for the biggest drive you can afford.

Backup

Before a catastrophic failure occurs, and you lose all of the work, consider how you'll protect the work produced. 

In addition to my work being stored on an external drive, everything’s backed up to a further separate drive. It’s like insurance, you don’t need it right up until the moment that you do.

Recording Interface

Consider how many inputs you’ll need and then buy the best one you can afford. If you’re using condenser mics ensure it can provide phantom power.

Microphones

The sort of work you do determines the mics you’ll need. For example, use large diaphragm condensers for voice-over work, small diaphragm condensers for acoustic recording and dynamic mics for speaker cabinets.

Monitor Speakers

The speakers in a laptop won’t do the job and neither will in-ear buds. If you want to produce quality work you must be able to hear with clarity what you’re doing. Invest accordingly.

Recording Software

A Digital Audio Workstation (or DAW) is a must. Choose the one that best suits your needs and budget. Here are some examples:

  • Logic and Pro Tools are industry-standard, and good all-rounders, but take some learning
  • Reaper is well worth considering as a cheaper alternative, and is easier to learn
  • If you’re more into producing beats, look at Reason and Ableton
  • If you’re just getting started, and/or your budget’s limited, GarageBand is amazing for the price

Plugins

DAWs come bundled with these. If, however, they don’t cover the sort of thing you’ll be doing, invest accordingly. 

For example, I do a lot of guitar work, so I use BIAS FX by Positive Grid to provide my sounds. If you’re not sure what to get, web-shops such Plugin Alliance and Plugin Boutique allow you to browse by brand or type.

Internet Connectivity

This sounds like a no-brainer, but it’s a must. And the faster, the better. Though this will depend on your location and local broadband infrastructure.

Online Storage

Some files will exceed the limit of the online session service employed; for example, Fiverr’s limit is 150MB. 

Such files are also far too large to email, so an online storage facility is ideal. A way that works is:

  1. Upload files to online storage
  2. email a link to the client, and 

When the client’s downloaded the files, you can remove them, thus freeing up your account.

I would therefore definitely recommend using Google Drive or Dropbox; better still, their basic accounts are free.

Conclusion

Being an online session musician requires more than just instrumental skill. In summary, you’ll need the following:

  • A dedicated workspace
  • Recording and production knowledge helps
  • Reliable equipment
  • A decent computer
  • Lots of external storage
  • File backup facility
  • A suitable recording interface
  • Quality monitor speakers
  • Microphones for acoustic work
  • An appropriate DAW
  • Specialist plugins
  • Online storage

In the next tutorial, I’ll describe how to deal with clients, managing orders and overseeing the whole process.


New Course: Add MailChimp Signup to Your WordPress Site

BigCommerce Review (2017): What is BigCommerce and Why Use it?

How to Create an Illustration of a Boy on a Scooter in Adobe Illustrator

Building Your Startup: Securing an API

The Must-Have Adobe Photoshop Assets for Designers and Digital Artists

How to Use CSS Variables for Animation

How to Use CSS Variables for Animation

When we mention CSS in discussions we often speak of it as a dumbed down language. A declarative language, lacking logic and insight; but that isn’t the true reality. For years developers have been craving variables in standard CSS, having been spoiled by pre-processors such as LESS and Sass for so long. Not only are CSS variables a real and tangible option for developers, they can also be used in animation scenarios. Still skeptical? Follow along to find out more!

Variable Basics

CSS variables are stored values intended for reuse throughout a stylesheet. They’re accessible using the custom var() function and set using custom property notation.

Variables defined within :root are global, whereas variables defined within a selector are specific to that selector.

In the example above any div will accept the variable, but we could get more specific with naming using targeting methods such as class and id for example.

The var() function can also accept fallback values too.

This can be useful in situations when a variable isn’t yet defined or when working with custom elements and the Shadow DOM.

CSS variables aren’t quite ready for prime time, but the outlook for the future is very bright with many leading browsers already implementing the spec. It’s only a matter of time until they can be used without any worries, and that time is approaching fast.

Variables for Animation

There are many options for combining CSS variables with animation. Think about contexts such as audio visualizations, JavaScript event-driven scenarios, and even CSS driven events such as hover, focus and target. In theory, an Apple Watch could be connected to an API whilst using a CSS variable-based animation of a beating heart. Then we have accelerometers, device tilt APIs and even gamepad APIs, but why should we consider animating with CSS Variables at all? Here are some reasons:

  • Easily debuggable.
  • No excessive DOM manipulation.
  • DOM node independent.
  • Theming
  • Works with SVG.

Operations in CSS are really the key part to the whole puzzle with animations. CSS functions such as calc can accept a value at runtime and execute operators such as multiplication, division, addition, subtraction, mutating values into a new ones. This helps make CSS variables dynamic.

CSS Variables in JavaScript

Now that we know what CSS variables look like and what they can do it’s time to gain an understanding how JavaScript fits into all this.

The methods shown above are used to set, get and remove property values. They can be used for our typical CSS properties (background-color, font-size etc), but they can also be used for CSS variables too. These options will set a new value for the globally defined property otherwise known as :root in CSS. 

They’re also the true secret to animating with CSS variables because our JS methods can get, set or remove a variable at run-time dynamically!

You can also set a new value for a specific element if desired. In the example snippet above we’re manipulating a variable that is attached to a div selector versus being attached globally.

Demos In the Wild

There are plenty of awesome and extremely talented developers building and experimenting with these concepts of reactive and theme-based animations using CSS variables. Here are just a few pens to dive into and discover what’s going on under the hood.

Sunset/Sunrise 

By David Khourshid.

This example shows the power of CSS variable animations used in a theme-based manner. It would generally be twice as much code to execute this demo without CSS variables and many times more if you desired to exceed two themes.

CSS Variables Animation

By GRAY GHOST.

Here’s another example using mouse events in JavaScript that drive the location of a circle.

Each time you move your mouse the JavaScript updates our declared variables, allowing the circle to move position in relation to your cursor. 

Alex the CSS Husky

By David Khourshid.

Here’s the same principle demonstrated above, but used in another context.

Notice what happens when you move your mouse around? Pretty cool huh?

Animation with CSS Variables

By Wes Bos.

How about updating the values of variables in other ways? Let’s take a look at the following demo by Wes Bos using sliders to update the positions of a picture.

Move the sliders around at your leisure. Notice the coolness that ensues? Simple, but simply magical and all it’s doing is updating the variables for the transform position each time the sliders are adjusted. Suuuuhhhweeet!

Single Div Accordion (Animated with CSS Variables)

By Dan Wilson.

How about something a little different for the musicians out there? Check out this hip accordion by Dan Wilson.

Whoa! Watch those keys move! This might seem a bit intimidating to go through, but at the core it’s just JavaScript updating CSS variables. Nothing more, nothing less.

CSS Variables + Transform = Individual Properties (with Inputs)

By Dan Wilson.

In this demo, use the input ranges to modify each transform property and witness how smooth they are even if you change a property mid transition.

Side Effects of CSS Variables

As CSS variables are always inheritable properties, they can cause a style recalculation of children, adversely effecting performance in the process. This will be something you have to measure, as opposed to guessing depending on your context.

Here’s a demo Shaw posted on the Animation at Work Slack group that was used for testing: CSS Variables Recalc Style Performance Test

During tests (Chrome 58. Mac 10.12) it was discovered that when the Set CSS Var button is triggered until the time the browser paints the background there’s 52.84ms of recalc time and 51.8ms rendering. Switching gears to the CSS Property test a very different result is discovered. From the time the Set CSS Property button is triggered until the background paints there’s roughly 0.43ms of recalc and 0.9ms rendering.

If you switch background out for color you’ll get equivalent measurements since currentColor might or might not exist in the children (shout out to David Khourshid). Any property that is inheritable will always cause a style recalc for any and all children. The property background-color is not inheritable, hence the tremendous difference with CSS variables which are always inheritable. Typically CSS properties that default to inherit will in most cases cause a large recalc of styles. It’s still important to note that changing CSS variables continually can be a performance drain. A good practice to avoid this is to animate CSS variables at the most specific level (or deepest level), in order to prevent a multitude of children affected. You can read more about reducing the scope and complexity of style calculations via Google’s Web Fundamentals page.

Conclusion

I encourage you all to dive in and test this demo for yourselves and make your own conclusion/changes/custom tests and share your results in the comments. The main takeaway in all of this is that CSS variables offer huge flexibility, but there will be performance implications for setting CSS variables on a parent with a vast amount children.

Special thanks to the gang in the Animations At Work Slack channel for the ongoing testing, feedback and discussions (David Khourshid, Joni Korpi, Dan Wilson and Shaw).

Resources


Friday, May 19, 2017

Envato Tuts+ Community Challenge: Created by You, May 2017

10 Top Reasons Why Your Website Needs a Redesign Now

New Short Course: Lightweight Carousels With Siema

Advanced Photo Manipulation Techniques: Blending and Lightning Effects

How to Create a Nintendo Switch in Adobe Illustrator

Securing iOS Data at Rest: Protecting the User's Data

Securing iOS Data at Rest: Protecting the User's Data

This is the first of three articles on securing user data at rest. In this post, we'll start off with the basics of protecting data on iOS so you can learn the current best practices for storing data securely with Swift.

Any app that saves the user's data has to take care of the security and privacy of that data. As we've seen with recent data breaches, there can be very serious consequences for failing to protect your users' stored data. In this tutorial, you'll learn some best practices for protecting your users' data.

Permissions

Before we get into storing your custom data, let's take a look at data that can be shared by system apps. 

For many iOS versions, it has been required to request app permissions to use and store some of the user's private data that is external to the app, such as when saving and loading pictures to the photo library. Starting in iOS 10, any APIs that access the user's private data require you to declare that access ahead of time in your project's info.plist file. 

There are many frameworks that can access data outside of your app, and each framework has a corresponding privacy key.

  • Bluetooth Sharing: NSBluetoothPeripheralUsageDescription
  • Calendar: NSCalendarsUsageDescription
  • CallKit: NSVoIPUsageDescription
  • Camera: NSCameraUsageDescription
  • Contacts: NSContactsUsageDescription
  • Health: NSHealthShareUsageDescription, NSHealthUpdateUsageDescription
  • HomeKit: NSHomeKitUsageDescription
  • Location: NSLocationAlwaysUsageDescription, NSLocationUsageDescription, NSLocationWhenInUseUsageDescription
  • Media Library: NSAppleMusicUsageDescription
  • Microphone: NSMicrophoneUsageDescription
  • Motion: NSMotionUsageDescription
  • Photos: NSPhotoLibraryUsageDescription
  • Reminders: NSRemindersUsageDescription
  • Speech Recognition: NSSpeechRecognitionUsageDescription
  • SiriKit: NSSiriUsageDescription
  • TV Provider: NSVideoSubscriberAccountUsageDescription

For example, here is an entry in info.plist to allow your app to load and store values to the calendar.

If a usage description is missing when the API tries to access the data, the app will simply crash.

The Data Protection API

For any user data that's internal to the app, the first thing to think about is whether you need to store the information, and what data is essential to the app. Keep as much of that essential data in working memory instead of in file storage. This is especially important for any personally identifiable information. 

But, if you must store data, it's a good idea to enable Apple's Data Protection.

Data Protection encrypts the contents of your app’s container. It relies on the user having a passcode, and thus the security of the encryption is tied to the strength of the passcode. With Touch ID and the upgraded file system encryption introduced in iOS 10.3, the data protection system has had many improvements. You can enable data protection across your app by turning on Data Protection in the Capabilities section of your project file. This updates your provisioning profile and entitlements file to include the Data Protection capability. Data Protection offers four levels of protection, depicted by the FileProtectionType structure:

  • none: no protection.
  • complete: data is not accessible while the device is locked. This is the recommended setting for most applications.
  • completeUnlessOpen: data is accessible when the device is unlocked, and continues to be accessible until the file is closed, even if the user locks the device. Files can also be created when the device is locked. This option is good for when you need to open a file to process and have the process continue even if the user puts the app into the background and locks the device. An example might be a job that uploads a file to a server.
  • completeUntilFirstUserAuthentication: when the device is booted, files are not accessible until the user first unlocks the device. After that, files are available even when the device is locked again. The option is good for files that need to be accessed sometime later in the background when the device is locked, such as during a background fetch job.

complete is the default level. To help avoid crashes when your code tries to access data that is locked, you can register for notifications via UIApplicationProtectedDataDidBecomeAvailable and UIApplicationProtectedDataWillBecomeUnavailable to find out when the data is available.

Additionally, you can also check the UIApplication.shared.isProtectedDataAvailable flag.

One important thing to keep in mind when enabling data protection is that if you are using any background services such as background fetch, that code may need access to your data in the background when the device is locked. For those files, you will need to set a protection level of completeUntilFirstUserAuthentication. You can control the protection level of each file individually when creating files and directories using the FileManager class.

You can also set the protection level when you write to a file. The Data object has a method that can write its data to a file, and you can set the protection level when you call this method.

You can also set the protection level when setting up your Core Data model.

To change the protection level of an existing file, use the following:

Data Integrity

Part of protecting your stored data includes checking its integrity. It's good practice not to blindly trust the data you are loading from storage; it may have been accidentally or maliciously altered. The NSSecureCoding protocol can be used to safely load and save your data objects from storage. It will make sure the objects you load contain the expected data. If you will be saving your own object, you can conform to the secure coding protocol inside your class.

The class must be inherited from NSObject. Then, to turn on secure coding, override the supportsSecureCoding protocol method.

If your custom object is deserialized with init?(coder aDecoder: NSCoder), the decodeObject(forKey:) method should be replaced with decodeObject(of:forKey:), which makes sure that the correct object types are unpacked from storage.

If you are using NSKeyedUnarchiver to load data from storage, make sure to set its requiresSecureCoding property.

Turning on secure coding for your save operations will prevent you from accidentally archiving an object that does not adhere to the secure coding protocol.

Beyond NSSecureCoding, it’s always good to implement your own data validation checks upon unpacking any archive or receiving any arbitrary input in general.

Data Trails

As iOS continues to evolve, there are always new features that have the potential to leak stored data. Starting in iOS 9, you can have your content indexed in the Spotlight search, and on iOS 10 you can expose your content to Widgets such as the Today Widget that shows up on the lock screen. Use caution if you would like to expose your content with these new features. You might end up sharing more than you planned to!

iOS 10 also adds a new Handoff feature where your copied pasteboard data is automatically shared between devices. Again, be careful not to expose any sensitive data in the pasteboard to Handoff. You can do this by marking the sensitive content as localOnly. You can also set an expiry date and time for the data.

Files that are saved to the device's storage can automatically get backed up, either in iTunes or in iCloud. Even though backups can be encrypted, it's a good idea to exclude any sensitive files that don't even need to leave the device. This can be done by setting the isExcludedFromBackup flag on the file.

The animation that happens when putting an app into the background is achieved by iOS taking a screenshot of your app which it then uses for the animation. When you look at the list of open apps on the app switcher, this screenshot is used there too. The screenshot gets stored on the device. 

It's a good idea to hide any views revealing sensitive data so that the data isn't captured in the screenshot. To do this, set up a notification when the application is going to the background and set the hidden property for the UI elements you want to exclude. They will be hidden before iOS captures the screen. Then when coming to the foreground, you can unhide the UI elements.

Remove your notifications when the view disappears.

Your app also has a keyboard cache for text fields that have auto-correct enabled. Text that the user types, along with newly learned words, are stored in the cache so that it is possible to retrieve various words that the user has previously entered in your application. The only way to disable the keyboard cache is to turn off the auto-correct option.

You should mark password fields as secure text entry. Secure text fields don't display the password or use the keyboard cache.

Debug logs are saved to a file and could be retrieved for production builds of your app. Even when you're coding and debugging your app, make sure not to log sensitive information such as passwords and keys to the console. You might forget to remove that information from the logs before submitting your code to the app store! While debugging, it's safer instead to use a breakpoint to view sensitive variables.

Network connections may also get cached to storage. More information about removing and disabling the network cache can be found in the article Securing Communications on iOS.

Destroying Data

You may already know that when a file on a computer is deleted, often the file itself is not removed; only the reference for the file is removed. To actually remove the file, you can overwrite the file with random data before removing it. 

The switch to solid state drives has made it hard to guarantee the data has been destroyed, and the best way to securely delete data is open to debate. However, this tutorial would not be complete without an example of how to wipe data from storage. Because of some other debates about the Swift optimizer, and because we hope to guarantee that each byte of the file is actually being overwritten, we are implementing this function in C. 

The implementation below can go inside a .c file. You will need to add the function definition or the file that contains the function into your bridging header in order to use the function from Swift. You may then want to call this function right before places where you use FileManager's removeFile methods. Perhaps you may want to implement the best practices described in this and the upcoming tutorials on an app update. You could then wipe the previous unprotected data during migration.

Conclusion

In this article, you have learned about setting permissions for the data that your app has access to, as well as how to ensure basic file protection and integrity. We also looked at some ways that user data could be leaked accidentally from your app. Your users put their trust in you to protect their data. Following these best practices will help you repay that confidence.

While you're here, check out some of our other posts on iOS app development!

  • iOS SDK
    Securing Communications on iOS
    Collin Stuart
  • Mobile Development
    Back-End as a Service for Mobile Apps
    Bala Durage Sandamal Siripathi
  • iOS SDK
    The Right Way to Share State Between Swift View Controllers
    Matteo Manferdini
  • Swift
    Swift From Scratch: Closures
    Bart Jacobs


Thursday, May 18, 2017

How to Use Android O's Autofill Framework

Swift Animation Basics

Advanced Photo Manipulation Techniques: Creating Realistic Smoke Effects

The Best Gmail Labs Features (To Improve Your Workflow Now)

How to Draw Bar Charts Using JavaScript and HTML5 Canvas

How to Design a Tropical Wedding Invite in Adobe InDesign

7 Tricks and Tips to Help You Become a ProcessWire Master

Quick Fixes for Rapid Image Correction in ON1 Photo 10

Wednesday, May 17, 2017

How to Create a Money Engraving Action: Photoshop in 60 Seconds

Quick Tip: Enumerations in Swift

Quick Tip: Enumerations in Swift

Enumerations are a common design pattern in many programming languages. While you may be familiar with enumerations in C and Objective-C, Swift's implementation of enumerations is significantly more powerful and flexible. In this quick tip, you'll learn what's special about enumerations in Swift, how to use them in your projects, and what makes them so powerful.

1. What Is an Enumeration?

Enumerations aren't new and they're certainly not unique to Swift. However, if you're familiar with enumerations in C, then you're going to love Swift's powerful take on enumerations.

If enums or enumerations are new to you, then you may not be familiar with what they have to offer. In Swift, enumerations are first class types that define a list of possible values for that type.

An example might be the possible states of a network connection. The possible states could be:

  • disconnected
  • connecting
  • connected

We could add a fourth state for the case the state is unknown. With this example in mind, let's see how to define and implement such an enumeration.

Basics

Like I said, enumerations are first class types in Swift. An enumeration definition looks very similar to a class or structure definition. In the example below, we define the ConnectionState enumeration.

The name of the enumeration is preceded by the enum keyword and followed by a pair of curly braces. The ConnectionState enumeration will define the possible states of a network connection. To define these states, we add member values or members to the enumeration's definition. The definition of a member value always starts with the case keyword.

In C or Objective-C, the above enumeration would look a bit different as illustrated in the example below. Each value of the enumeration corresponds with an integer, for example, ConnectionStateUnknown equals 0, ConnectionStateDisconnected equals 1, etc.

This isn't true in Swift. The members of an enumeration don't automatically correspond with an integer value. The members of the ConnectionState enumeration are values themselves and they are of type ConnectionState. This makes working with enumerations safer and more explicit.

Raw Values

It is possible to explicitly specify the values of the members of an enumeration. In the following example, the members of the ConnectionState enumeration have a raw value of type Int. Each member is assigned a raw value, corresponding with an integer.

Note that we specify the type of the raw values in the enumeration's definition and that no two member values can have the same raw value. If we only specify a value for the Unknown member, then Swift will automatically increment the value of the Unknown member and assign unique values to the other members of the enumeration. To better illustrate this, the below example is identical to the previous definition of the ConnectionState enumeration.

2. Working with Enumerations

Initialization

Using the ConnectionState enumeration is similar to using any other type in Swift. In the next example, we declare a variable, connectionState, and set its value to ConnectionState.Connecting.

The value of connectionState is ConnectionState.Connecting and the variable is of type ConnectionState.

Swift's type inference is very convenient when working with enumerations. Because we declared connectionState as being of type ConnectionState, we can now assign a new value by using the shorthand dot syntax for enumerations.

Control Flow

Using enumerations in an if or switch statement is straightforward. Remember that switch statements need to be exhaustive. Add a default case if necessary.

The following example demonstrates how the ConnectionState enum can be used. It also shows how to access the associated value of an enum member. The canConnect function accepts a ConnectionState instance and returns a Bool.

The canConnect function only returns true if the ConnectionState instance passed to the function is equal to .Connected and its associated value is an Int equal to 3000. Note that the associated value of the Connected member is available in the switch statement as a constant named port, which we can then use in the corresponding case.

3. Associated Values

Another compelling feature of Swift enums are associated values. Each member of an enum can have an associated value. Associated values are very flexible. For example, associated values of different members of the same enum don't need to be of the same type. Take a look at the following example to better understand the concept of associated values.

The Unknown and Disconnected members don't have an associated value. TheConnecting member has an associated value of type (Int, Double), specifying the port number and timeout interval of the connection. The Connected member has an associated value of type Int, specifying the port number.

It's important to understand that an associated value is linked to or associated with a member of the enumeration. The member's value remains unchanged. The next example illustrates how to create a ConnectionState instance with an associated value.

4. Methods and Value Types

Methods

Enumerations are pretty powerful in Swift. Enumerations can even define methods, such as an initializer to select a default member value if none was specified.

In this example, we initialize an instance of the ConnectionState enumeration without explicitly specifying a value for it. In the initializer of the enumeration, however, we set the instance to Unknown. The result is that the connectionState variable is equal to ConnectionState.Unknown.

Value Types

Like structures, enumerations are value types, which means that an enumeration is not passed by reference, like class instances, but by value. The following example illustrates this.

Even though we assign connectionState1 to connectionState2, the values of connectionState1 and connectionState2 are different at the end of the example.

When connectionState1 is assigned to connectionState2, Swift creates a copy of connectionState1 and assigns that to connectionState2. In other words, connectionState1 and connectionState2 refer to two different ConnectionState instances.

Conclusion

Enums in Swift are incredibly powerful compared to, for example, enums in C. One of the most powerful aspects of enumerations is that they are a first class types in Swift. Type safety is a key aspect of the Swift language and enumerations fit perfectly in that mindset.


Try Our Course on PHP Design Patterns With a Free Trial

How to Create Web Input Forms With Google Sheets

20 Best Minimal WordPress Themes: With Simple, Elegant Designs

What Is WP-CLI? A Beginner’s Guide

Advanced Photo Manipulation Techniques: Adding Cracks and Smoke

How to Draw a Butterfly Step by Step

Documentary in Motion: Advanced Slider Action

Understanding Particles and Dynamics in Maya—Part 8

Tuesday, May 16, 2017

How to Create a Split-Screen Slider With JavaScript

How to Create a Cute Cartoon Kitten in Adobe Illustrator

SpriteKit Basics: Nodes

How to Start Selling Products Online Successfully (In 2017)

How to Insert a YouTube Video into Powerpoint in 60 Seconds

How to Zip and Unzip Files in CodeIgniter

41 Creative YouTube Banner Templates

Advanced Photo Manipulation Techniques: Working With Patterns

How to Create a Charcoal Drawing from a Photo (With a Photoshop Action)

Monday, May 15, 2017

How To Record Vocals Like a Professional

Turn Your Google Docs Form Responses Into Beautiful Visualizations

Tips and Tricks for Augmented Reality With Unity and Vuforia

How to Create a Chromebook Recovery USB Drive Using Chrome OS

How to Create an 80s-Inspired Silver Text Effect in Adobe Photoshop

17+ Best PowerPoint Template Designs for 2017

Programming With Yii2: Building Community With Voting, Comments, and Sharing

Advanced Photo Manipulation Techniques: Document and Foreground Setup

The State of CSS Animation

Good Timing: Find The Best Times of Day to Fly Your Drone

How to Create a Modern Kitchen In Adobe Illustrator

Friday, May 12, 2017

How to Prepare Your Resume for Work in Photography and Video Production

Updated Primer for Creating Isometric Worlds, Part 2

How to Work With Session Data in CodeIgniter

How to Work With Session Data in CodeIgniter

As a CodeIgniter developer, it's really important for you to understand how to work with the core session library. Of course, you could always use the default $_SESSION syntax, but it's always recommended to use the wrapper instead.

Starting with how to load a session library, we’ll move to the discussion of how to add, retrieve, remove and destroy session variables. In the last segment, we’ll have a look at the different built-in session drivers at your disposal provided by the CodeIgniter framework itself.

How to Load a Session Library

If you want to work with sessions in CodeIgniter, the first thing you'll need is a built-in session library. Unless and until you develop a web application that doesn't require sessions at all, you shouldn't bother about the session library. While that's not the case most of the time, you can autoload the session library in CodeIgniter so that it enables session handling features for every web request.

Go ahead and open the file located at application/config/autoload.php. Find the following section.

The $autoload['libraries'] array holds the list of libraries that need to be autoloaded. As per our requirement, let's change it to look like this:

Also, there's another way you could have achieved that. You can use the following code somewhere in your controller file to load the session library.

That's pretty much it as far as initialization of the session library is concerned.

In the next couple of sections, we'll go through the different operations that you can do with the core session library. To demonstrate it, we'll build an example controller file that loads the session library and provides methods that will be discussed throughout this article.

Go ahead and create a file application/controllers/Example.php with the following contents.

That's a very basic controller file you should be familiar with as a CodeIgniter developer. Now, we're ready to move to the next couple of sections that provide insight into the session handling concepts.

How to Add, Retrieve and Remove Session Data

To start with, let's fetch the code of our __construct method.

Just in case you haven't autoloaded the session library, it'll do that in the first place. Apart from that, we've also loaded the url helper that allows us to use certain utility methods that we'll see later.

Next, grab the code of the index method.

As you've loaded the session library already, you can use $this->session to access the session object and access the methods that are supported. The set_userdata method is used to create a new session variable, and generally it takes two arguments—key and value.

You can also use the set_userdata method to create multiple variables in a single call. In that case, you just need to provide one argument, and it should be an array as shown below.

Users with sharp eyes would have noticed that you could also assign an array as a value of any session variable, as shown above in the interests example.

Now, let's see how to retrieve the value of any session variable. The userdata method is used to retrieve the value of any session variable, and usually it needs the key of the session variable that you're looking for as the first argument.

If you're looking for one of the array entries, you can use the following:

More often than not, you want to know how many variables in total are stored in an active session for debugging purposes, and you can do that as well.

Yes, the same userdata method comes to our rescue! If you don't pass any argument to the userdata method, it'll return all the session variables.

Finally, let's see how you can remove variables from the session. It's the unset_userdata method that you can use should you want to remove any session entries.

And here's the variation of the same method that shows how to remove multiple entries in a single go.

And that should delete the twitter_id and interests entries from the session.

Go ahead and test the index method to see things in action.

Useful Goodies: Flashdata and Tempdata

In the last section, we discussed the basics of session handling in CodeIgniter. In this section, we'll discuss couple of other utility methods provided by the session library.

In your day-to-day development, you often need to display messages in response to certain user actions. As an example, you want to display a success message when someone posts a comment on your site, and the message should be displayed only once. The set_flashdata method is a perfect candidate for this kind of use case.

In fact, set_flashdata is very similar to the set_userdata method in that it allows you to save a value in session. The only exception is that the session value set by the flashdata method is available for the next request only. In subsequent requests, you won't be able to access these variables anymore as they were cleared.

Grab the code of the setflash method.

You can create a new flashdata variable in the same way you would have created a regular session variable using the set_userdata method. On the other hand, you can also mark an existing session variable as a flashdata variable. In that case, you need to use the mark_as_flash method, as shown in the above code.

Finally, we redirect the user to the getflash method that shows how to use flashdata variables that were set in the setflash method. Let's have a quick look at the getflash method.

As expected, there's a flashdata method that allows you to fetch session variables stored as flashdata. If you call the flashdata method without any arguments, it'll return all flashdata variables similar to that of the userdata method.

Go ahead and test the setflash method. You'll be redirected to the getflash URL, and you'll see the message. If you refresh the getflash page, you won't see that message again!

Next, there’s another variation provided by the session library in this category—the tempdata session variables. If you want to create session variables for a specific time period, the set_tempdata method is the one you’re looking for.

For example, if you want to create a session variable that should be automatically deleted after a certain time period, you can use the set_tempdata method to create such a variable, as shown in the following method.

The third argument in the set_tempdata method indicates the number of seconds after which the variable will be deleted from the session.

You can also mark an existing session variable as tempdata using the mark_as_temp method provided that you’ve already created a session variable using the set_userdata method.

Finally, you can use the tempdata method to fetch the value of any tempdata variable.

So it’s nice to have such utility methods at your disposal in your day-to-day development lifecycle!

What You Should Not Forget: Session Destroy

Destroying the session is probably the last thing you would like to do when the user logs out. It makes sure that the session variables set so far are deleted from the active session and are no longer available for subsequent requests.

Let’s pull in the code of the destroy method and go through it.

It’s the sess_destroy method that helps us to destroy the active session. Of course, it’ll also delete tempdata and flashdata variables that were set in the active session.

Make sure you get yourself into the habit of destroying a session once it’s no longer useful in the current user context.

Cherry on the Top: Session Drivers

We’re into the last section of this article—the session drivers. More often than not, you don’t bother about configuring the session driver in your application as the default session driver, the file system, is configured already with the default setup.

So it’s the file system that holds all session-related data, and it’s widely used and is the accepted standard for session handling. Having said that, CodeIgniter also supports other session drivers that you could use should you wish to switch from the default file system session driver.

Here’s a list of all supported session drivers in CodeIgniter:

  • Files
  • Database
  • Redis
  • Memcached

The database session driver, as the name suggests, stores the session data in the database that you’ve configured for your CodeIgniter application.

On the other hand, the other two session drivers are in-memory storage mechanisms preferred for high-performance websites.

In the application/config/config.php file, you can configure the session driver that you would like to use in your application.

It tells CodeIgniter to use the database session driver, and the session data will be saved in the custom_sessions MySQL table.

Discussion of each and every session driver is beyond the scope of this article, but you can go through the official site documentation that provides an in-depth guide for each driver.

Conclusion

Session handling in CodeIgniter was the topic of today's tutorial, and we discussed it thoroughly by looking at every aspect of the subject.

Starting with basic session operations, we also went through those cool flashdata and tempdata methods, and it was the discussion of session drivers that concluded our article.

As always, you could shout out your queries and suggestions using the feed below!