amp

Iowa Writers’ House is gone, but need for literary community continues

When Andrea Wilson approached me five years ago with her idea of creating a space for writers in our community separate from any offered by the University of Iowa, I must admit I was a bit skeptical, if not defensive. Over a long coffee discussion, I shared with her a detailed look at the literary landscape of Iowa City and all of the things my organization, the Iowa City UNESCO City of Literature was doing to make those assets more visible and accessible.

Coronavirus closes the Iowa Writers’ House - for now

Despite this, Andrea mentioned the need for an “on ramp,” a way for people who don’t feel a part of that community to find their path, to access those riches. It was there, I thought to myself. She just hadn’t looked in the right place.

Then she built that ramp in the form of the Iowa Writers’ House. As she and her team defined what that ramp should look like, what role it should play, the Writers’ House evolved from being an idea with promise to a vital part of our literary infrastructure. She showed that people were hungry for further instruction. They desired more and different ways to connect with one another. These were things beyond the scope and mission of the UI and the City of Literature. She had found her niche, and filled it, nicely complementing what was offered by my organization and others.

But those services do not come without cost. Andrea and her team scrambled, using the house as a literary bed-and-breakfast that was used by many visiting writers. They scheduled workshops. They held fundraisers. But that thin margin disappeared with the onset of COVID-19. Unable to hold those workshops, to serve as a bed-and-breakfast, to provide meaningful in-person connections, the Writers’ House was unable to carry on in its current configuration.

We have every hope and expectation that the Iowa Writers’ House and Andrea will continue to be a part of our literary landscape in the future. This will come perhaps in another form, another space. Conversations have been underway for months about the needs of the literary community beyond the UI. Andrea has been a key part of those discussions, and the work that she and her team has done offer vital information about where those conversations need to go. Gaps have been identified, and while they won’t be filled in the same way, they will be filled.

These conversations join those that have been taking place in our community for decades about the need for space and support for writers and artists. As we all have realized over these past few weeks of isolation just how much we miss when we are not able to gather to create and to celebrate those creations, perhaps those conversations will accelerate and gain focus once we reconvene. The newly formed Iowa City Downtown Arts Alliance, of which we are proud to be a part, is an additional voice in that conversation.

In the meantime, we want to thank Andrea, Associate Director Alisha Jeddeloh, and the team at the Iowa Writers’ House, not just for identifying a need, but for taking the rare and valuable step of actually rolling up their sleeves and doing something to meet it.

John Kenyon is executive director of the Iowa City UNESCO City of Literature.




amp

WordCamp Las Vegas Near

The time is near, only 6 hours and some change to to get your tickets to WordCamp in Las Vegas! I have my tickets, and so do 125 other at the moment. If you have not purchased tickets and are going to be in the LV area, or planning on heading that way, well then […]

The post WordCamp Las Vegas Near appeared first on WPCult.





amp

Manon – Portfolio & Agency Theme

Manon is a true game-changer in the WordPress sphere. This unparalleled portfolio & agency theme lets you create a wonderfully fluid website that will surely stand out in the crowd. It comes completely decked-out with powerful features and a collection … Continued

The post Manon – Portfolio & Agency Theme appeared first on WeLoveWP.




amp

Joe wants you to Sample that: One C.R. man is on a mission to help local restaurants gain fans

When Joe Sample started posting photos of his takeout food stops in the days after Iowa restaurants were ordered shut down to dine-in service in March, he didn’t think much of it. He just wanted to get some good food while supporting restaurants.

“I have a lot of friends in the food business. My wife worked at Elevate Salon and Emil’s Deli, so she’s not working right now,” he said. “I felt it was a great way to support local businesses.”

But then a new Facebook group dedicated to promoting curbside, delivery and takeout food options in Cedar Rapids sprung up — this week, it had more than 15,000 members — and Sample started sharing photos there. The 46-year-old Cedar Rapids resident quickly found himself having a new experience — going viral.

In a pandemic, that phrase could have negative connotations, but this was the positive kind of viral spread. The kind where hundreds of people liked his photos and commented on them. Then a Cedar Rapids T-shirt maker, Ivory Pearl Designs, started selling “Be Like Joe” T-shirts and other people started showing up to order takeout in the shirts. Soon, restaurants were asking if he would come take a photo at their restaurant.

“I just started it to have fun and posted a few fun pictures, and then I started having restaurants reach out to me,” Sample said.

He decided to dedicate his stimulus check from the federal government to the effort. Sometimes, he said he hits up more than one restaurant a day.

“I’ve hit close to 60 restaurants,” he said.

He’s leaned into the enthusiasm and found ways to play up the efforts. One day he dressed as Oscar the Grouch while visiting’ Oscar’s Restaurant in Hiawatha. On another day, he and one of his daughters bought plastic pig noses to wear on a stop at the Blind Pig in Cedar Rapids. He wears a Superman costume to some stops.

“I was totally surprised at how viral it went,” he said. “Now I’m just trying to keep it exciting.”

In his day job, Sample is a salesman for American Building Components in Mount Pleasant. He normally spends a lot of time on the road, selling metal roofing, siding and steel frame structures around the Midwest. These days, he’s working from home, making sales over the phone instead. He said going out to get carryout is a chance to see other people and get out of the house.

“It brings some normalcy to my life,” he said.

He has two daughters at home, age 9 and 15, and one son, 22. When he’s not eating out, he likes to spend time outdoors with his family, fishing, camping, hunting and coaching soccer. He admits his last name is a bit on-the-nose for his newest hobby.

“A lot of people ask, ‘Is that really even your real name?’” he said with a laugh.

Sample was born and raised in Cedar Rapids, which fuels his desire to support his town.

“My dad had Sample Pharmacies when I was growing up. People helped support us, so I figured it was the least I could do, to support other local businesses,” he said. “I think the biggest thing is, we want to keep them here. There are so many great restaurants in Cedar Rapids, and we don’t want to lose half of them. I’m going to try to keep going with this until they open the places back up, as much as I can.”

He also has helped do deliveries of donated meals to area hospitals and long-term care facilities. That effort started when his younger daughter’s Girl Scout troop had dozens of boxes of unsold cookies and few options to sell them once the pandemic hit. Sample’s family purchased them and sent them to staff at Mercy Medical Center. Since then he’s dropped off boxes of pita, hummus and gyro meat from Pita’z Mediterranean and American Cuisine, trays of cinnamon rolls from Oscar’s and other places.

“People seem to be very supportive in Cedar Rapids,” he said.

He gave a lot of credit to the Cedar Rapids Facebook group, which was started by Lindsay Leahy, Brooke Murphy-Fitzgerald and Shannon Hanson. Others like it have sprung up in Marion, North Liberty and Iowa City.

“I think this has opened a lot of people’s eyes; it has given people an opportunity to try new things,” Sample said. “I’ve seen more restaurants on here than I’d ever tried before.”

He’s also started to promote nonprofits like the Freedom Festival. He is helping sell the $5 commemorative buttons — even though the 2020 festival was canceled, the buttons will help support the organization’s operations. And he helped with a Big Brothers Big Sisters fundraiser, an effort which inspired him so much he signed up as a volunteer.

He said he hopes his efforts, and others like it inspire others to support the community.

“Keep supporting local, do your best to stay healthy, and when restaurants open back up, keep going to them,” he said. “They’re going to need our help for a long time to come.”

Comments: (319) 398-8339; alison.gowans@thegazette.com



  • Food & Drink

amp

Collaboration creates Camp-in-a-Bag kits for mentoring program

“I pledge my Head to clearer thinking, my Heart to greater loyalty, my Hands to larger service, and my Health to better living, for my club, my community, my country, and my world.” — 4-H pledge

The Johnson County 4-H program is living up to these words, teaming up with Big Brothers Big Sisters of Johnson County to assemble Camp-in-a-Bag kits for the youngest “Littles” enrolled in the BBBS mentoring program.

Big Brothers Big Sisters creates one-on-one opportunities between adult volunteer mentors and at-risk youths ages 6 to 18. Known as “Bigs” and “Littles,” they meet for at least six hours a month for 18 months. But those in-person outings to movies, museums, restaurants, recreational activities and new adventures, as well as monthly events and school-based programs organized by the agency, are on hold during the COVID-19 pandemic.

So the kits became an outreach outlet.

“I was thinking about ways that we would be able to connect with our Littles, to let them know that we’re thinking about them,” said Dina Bishara, program specialist for Big Brothers Big Sisters of Johnson County. “And also in a very small way, to try to fill that gap that so many kids are experiencing right now. They’re used to the structure and activity of school and extracurricular activities and playing with friends.”

The bags contain more than six hours of STEAM — science, technology, engineering, arts and math — activities, from the pieces needed for building gliders and balloon flyers, to conducting scientific experiments, planting seeds, choosing healthy snacks and writing down their thoughts.

Those activities also reflect the other contributing partners: Johnson County Master Gardeners, Johnson County Extension and Outreach’s Pick a Better Snack program, O’Brien Family McDonalds and Forever Green Garden Center.

“(We wanted to) just give them something really fun and also educational and engaging, to help them spend time with their siblings, if they have them, and get their parents involved, if possible — and just really keep them connected to that learning and the fun, but also to Big Brothers Big Sisters,” Bishara said. “Camp-in-a-Bag helps us structure things in an intentional and thoughtful way.”

Partnering with 4-H, known for its summer camps, fairs and educational programs, “was a really great way to make sure that the activities we were including were really robust, so it was not going to be a hodgepodge, throw-some-things-in-a-bag,” Bishara added. “We really needed to be deliberate about it, to have the directions nicely laid out.”

The first wave is being distributed to 20 elementary-age children, and officials are hoping to expand the project.

“Funding is always a question,” Bishara said. “We would love to expand to 20 or 40 for more. ... We’d sure like to be able to target the kits to a little older kids, who have different interests.”

Bishara and Kate Yoder, who works with 4-H out of the Iowa State University Extension office in Johnson County, are eager to continue their collaborative efforts.

“It really great,” Yoder said. “When you work together, things comes together and amazing things happen. I’m excited to see what the future holds — what partnerships we can build on and grow.”

Comments: (319) 368-8508; diana.nollen@thegazette.com

To help

• What: Big Brothers Big Sisters Camp-in-a-Bag kit contributions

• Contact: Email Dina Bishara at dina@bbbsjc.org




amp

Marion coronavirus recovery task force wants residents to come out of this healthy and to ‘a vibrant economy’

MARION — Marion’s 14-member COVID-19 Economic Recovery Task Force is beginning to work on recommendations of how to get people back to work, while keeping everyone safe.

“It’s hard to know right now at the beginning the various outcomes that are going to come out of this,” Marion Mayor Nick AbouAssaly told task force members in a meeting held this week via Zoom.

“Community sectors will work independently and report to the steering committee with ideas, strategies or policy recommendations,” he said.

In turn, the task force will consider recommendations to the Marion City Council, and AbouAssaly said he will update the council on the task force meetings.

“Unfortunately, we have to accept that the virus is here to stay,” AbouAssaly said. “It’s part of our life for the time being. We have to be able to plan for getting back to doing things and leading our lives in a way that allows us to exist with the virus in our community.”

Elizabeth Cwik, a Marion resident who works for the Greater Cedar Rapids Community Foundation, said there’s a “strong interest” among task force members to provide accurate information to the public about the virus.

“I see clear, consistent messaging from a variety of sectors from the schools, government, businesses and nonprofits. Then that message gets through,” Cwik said. “If that message is, ‘We care, and we want you to come out whole, and we want there to be a vibrant economy to be continued with every citizen’s effort,’ I think that’s a valuable contribution to the recovery.”

In joining the task force, Dr. Jaclyn Price said she hopes to dispel inaccurate information about the coronavirus and help businesses find ways to safely bring their employees back to work.

“I anticipate businesses will be operating at reduced capacities,” she said. “Maybe doing appointments rather than walk-in business, and cleaning more routinely.”

If businesses require employees and customers to wear masks, it will protect others from asymptomatic spread of the virus, she said.

“We will still see virus activity until we get a vaccine or herd immunity,” Price said. “This is going to be a problem for months to come. We’re trying to find ways to open slowly, but also understanding if we reopen everything and have to close it again, that could be more detrimental to people’s psychology or finances of businesses.”

The Rev. Mike Morgan of Marion United Methodist Church said “greater conversation” with government, business, education and health care leaders will help.

“Marion has become a town that is proactive,” Morgan said. “We really seek to have good things happen to our citizenry rather than let things happen and we react to them. ... As a person in the faith community, it’s important for us to be tending to people’s emotional, psychological, spiritual and, to some degree, physical needs.”

Comments: (319) 368-8664; grace.king@thegazette.com

MARION TASK FORCE

Those serving on the Marion COVID-19 Economic Recovery Task Force, all Marion residents and volunteers, are:

• Nick AbouAssaly, Marion mayor

• Jill Ackerman, president, Marion Chamber of Commerce

• Shannon Bisgard, Linn-Mar schools superintendent

• Amber Bisinger, communications officer for the city

• Elizabeth Cwik, Greater Cedar Rapids Community Foundation

• Lee Eilers, executive committee member, Marion Economic Development Corp.

• Nick Glew, president, Marion Economic Development Corp.

• Amber Hoff, marriage and family therapist

• Steve Jensen, Marion City Council member

• Mike Morgan, pastor, Marion United Methodist Church

• Brent Oleson, Linn County supervisor

Lon Pluckhahn, Marion city manager

• Jaclyn Price, M.D., Mercy Clinic-Marion

• Brooke Prouty, program director, Marion Chamber of Commerce




amp

Coronavirus closes the Iowa Writers’ House — for now

IOWA CITY — Once upon a time, there was a house in a city that loved literature.

It was a quaint, two-story home in the heart of the historic district with brick stairs, pale yellow siding, a hipped red roof and a rich history: Its original owner was Emma J. Harvat, who in 1922 became the nation’s first female mayor for a city of more than 10,000.

Nearly a century later, in 2014, Andrea Wilson was working in advertising in Florida and pined for a more “altruistic purpose” for her life. So she planned a return to Iowa, where she grew up in Columbus Junction.

But this time Wilson would live in Iowa City, known for — among other things — pioneering academic creative writing pursuits at the University of Iowa’s famed Writers’ Workshop.

Wilson wanted to write and found the idea of the historic Harvat house so charming she bought it “sight unseen” from down in Miami, aiming to run it as a bed-and-breakfast. But when she arrived, Wilson discovered a need in her new community she aimed to fill. It had a surprising dearth of literary resources for those outside the university.

“There wasn’t any place for the public to take a class or meet other writers or really be part of a writing community where people could just express their humanity through words,” she said. “It became my passion project — to try to create that for this community. I thought if anywhere should have a place like that, it would be America’s only UNESCO City of Literature at the time.”

So in March 2015, Wilson debuted Iowa City’s first community-based literary center for writers — or those aspiring. She had hoped to open a communal writing space closer to downtown but didn’t have the funding. So she gave her home a third identity: the Iowa Writers’ House.

She continued to live there and maintain her bed-and-breakfast business, which funded the writing endeavor and kept its cozy corridors bustling with interesting characters.

Famed visiting writers included Leslie Jamison, American novelist and essayist with works on the New York Times bestseller list; Hope Edelman, whose six non-fiction books have published in 17 countries and translated in 11 languages; Alison Bechdel, an American cartoonist and MacArthur fellow; and Piedad Bonnett Velez, Colombian poet, playwright and novelist of international acclaim.

And over the years, the Iowa Writers’ House connected, served and motivated thousands with its workshops, seminars, readings and summer camps. It offered editing services, founded a Bicultural Iowa Writers’ Fellowship, and — among other things — inspired a growing network of friends and creatives to value their own stories and the stories of others.

“I said yes to everything anyone ever asked of me,” Wilson said. “We gave tours. I received visiting scholars. We hosted dinners for visiting poets and writers for the university. And a lot of that was all volunteer. We never had a steady funding stream like most literary centers do.”

So when the coronavirus in March reached Iowa City, later shuttering storefronts, canceling events, curtailing travel plans and crippling the economy, the Iowa Writers’ House momentum stopped, too.

“Once COVID hit, because all of our programming is live and people come to the house, we had to cancel it,” Wilson said.

She dropped most of the organization’s spring season. She lost all her projected bed-and-breakfast business. And in a message posted to the Iowa Writers’ House website last month, Wilson announced her hard but unavoidable news.

“As the situation pushes on, and with no programming in the foreseeable future, we must make drastic changes,” she wrote. “Organizations must weather the storm or adapt, and in the case of this little organization with a big heart, evolution is the only option.”

And so after five years of intimate conversations, communal meals, singing, laughing, crying and lots and lots of writing and reading — all done in the shadow of Harvat — the organization is leaving the historic space and “taking a break to assess our mission and consider our best options for the future.”

Wilson said she plans to focus on her own writing. And the Bicultural Iowa Writers’ Fellowship program will continue — allowing for the release later this year of a third volume of “We the Interwoven: An Anthology of Bicultural Iowa,” including six new authors with multilingual stories of living in Iowa.

News of the goodbye — at least for now — has been met with an outpouring of support and testimonials of the impact the Iowa Writers’ House has had,

“I grew up without a writing community, and it was a very lonely experience,” Erin Casey wrote to Wilson after learning of its pause.

Casey — on the Iowa Writers’ House team and director of The Writers’ Rooms, an offshoot of the house — said her involvement in the project shaped not only her career but her personal growth.

“You, and the Iowa Writers’ House, helped me become a stronger person who felt deserving of companionship, respect, and love,” she wrote. “Watching the house grow, the workshops fill, and the stories come in about how much the IWH touched people’s lives added to the joy. I finally found a place to call home.”

Casey said that while the future is unknown, its legacy is not.

“The IWH will live on in the hearts of the people you touched,” she wrote. “Writers have found friends, support, guidance …”

Although the project isn’t getting a fairy-tale ending, Wilson said the story isn’t over.

“The organization is leaving the space. I’m leaving the space. We’re going on an organizational break so we can determine what a sustainable future might be,” she said. “But it’s really the end of a chapter. And we don’t know what the next chapter will be.”

Comments: (319) 339-3158; vanessa.miller@thegazette.com




amp

Ahead of VP Pence’s Iowa visit, Joe Biden’s campaign calls out ‘consequential failure’ of Trump coronavirus response

Vice President Mike Pence owes Iowans more than a photo-op when he visits Des Moines today, according to Joe Biden’s campaign.

“Iowans are seeing up close the most consequential failure of government in modern American history,” said Kate Bedingfeld, spokeswoman for the former vice president and presumptive Democratic presidential nominee.

“With nearly 300,000 Iowans filing for unemployment, rural hospitals on life support, Latino communities disproportionately suffering and workers on the job without sufficient protection, Mike Pence owes Iowans more than a photo-op — he owes them answers,” she said.

Pence, head of the White House coronavirus task force, is scheduled to meet with Iowa Gov. Kim Reynolds and U.S. Sens. Chuck Grassley and Joni Ernst, all Republicans, as well as with faith, farm and food production leaders.

Pence will talk to faith leaders about how they are using federal and state guidelines to open their houses of worship in a safe and responsible manner.

Later, he will go to Hy-Vee’s headquarters in West Des Moines for a roundtable discussion with agriculture and food supply leaders to discuss steps being taken to ensure the food supply remains secure.

Pence has called Iowa a “success story” in its response to the COVID-19, but Bedingfeld said the Trump administration failed to protect Iowa families from the virus that has claimed the lives of 231 Iowans.

“From devastating losses across the state, at meatpacking plants to rural communities, one thing is clear — it’s Iowans and the American people who are paying the price for the Trump administration’s denials and delays in response to this pandemic,” she said.

“Instead of listening to our own intelligence agencies and public health experts, Donald Trump was fed dangerous propaganda from the Chinese Communist Party — and he bought it,” she said. “Iowans deserve better — they deserve Joe Biden.”

For his part, Grassley said he welcomes the discussion with Pence.

“There’s much work to be done, and the pandemic is disrupting all of our communities,” Grassley said. “It’s important to hear directly from those who help feed the nation and the world.”

Ernst also is looking forward to the discussion of how Iowa is working to protect the health and safety of Iowa’s families and communities while reopening the state’s economy.

“We continue to take an all-hands-on-deck approach to tackling this pandemic,” she said. “Together, we will get through this.”

Comments: (319) 398-8375; james.lynch@thegazette.com




amp

‘Death stalked swiftly’ in 1918. What will we remember now?

In August 1919, the Cedar Rapids Evening Gazette opined in favor of the passage of a $5 million congressional appropriation to “investigate influenza, its cause, prevention and cure.”

“We all remember without effort the darkness and terror which engulfed the land last fall and winter as death stalked swiftly from seaboard to seaboard, into crowded city and unto lonely plain, sparing not the cottage of the poor nor the mansion of the rich,” the editorial said. “In four short months, influenza claimed a half million lives and pressed millions of others onto beds of sickness, suffering and helplessness. The nation’s mortality rate leapt high and with astounding speed. The nation was unprepared to cope with a disease calamity such as it has never known.”

The Gazette lamented that billions of dollars in loss were wrought by the pandemic of so-called Spanish influenza, compared with only $5 million being spent to investigate the virus.

“More has been spent in studying diseases of hogs,” the editorial argued.

Just less than a year earlier, The Evening Gazette did not see “darkness and terror” coming. A front page, above-the-fold story Sept. 25, 1918, asked: “Spanish Influenza just the old-fashioned grippe?” “Grippe” is an old-time term for the flu, by the way.

“As a matter of fact, in the opinion of City Physician Beardsley, and a good many other Cedar Rapids men in the same profession, Spanish influenza is just another name for the regular old fashioned influenza and is no different from the influenza we have always had. A bad cold is a bad cold, and a worse cold is grippe, which covers a multitude of things ...,” The Gazette reported, optimistically.

An earlier strain of influenza in the spring of 1918 had been less virulent and deadly. But the second wave was no ordinary grippe.

By mid-October, according to reports in The Evening Gazette, influenza caseloads exploded. On Oct. 12, 1918, the local health board shut down pool rooms, billiard halls and bowling alleys. It pleaded with store owners to avoid allowing crowds to linger. On Oct. 16, stores were ordered to discontinue any special sales that might draw more shoppers.

Restrictions tightened as the pandemic worsened.

Death notices were stacking up on Gazette pages, in rows reminiscent of small tombstones. Many victims were cut down in the prime of life by a virus that struck young, healthy people hardest. Mothers and fathers died, leaving young children. Soldiers serving in World War I died far away from home. Visitors to town never returned home.

Young brothers died and were mourned at a double funeral. A sister who came to care for a sick brother died, and so did her brother.

Ray Franklin Minburn, 24, died of influenza, leaving behind six sisters and two brothers. “Mr. Minburn was a faithful son, a devoted companion, a good neighbor,” concluded his death announcement on Oct. 21, 1918.

On the same page that day came news, tucked among the tombstones, reporting that Iowa Gov. William Harding had recovered from influenza, in the midst of his reelection campaign, and was back in the office. You might remember Harding as the governor who banned German and other languages during World War I and who was nearly impeached for bribery in 1919.

Not far from Harding’s update came news from the prison in Anamosa that “whisky and quinine” were being deployed to attack the grippe.

The pages of The Evening Gazette also were dotted with advertisements for supposed cures and treatments.

“Danger of infection from influenza or any contagious disease can be eliminated by using preventive measures,” prescribed by Ruby S. Thompson, chiropractor and naturopathic physician. Those included “Sulphur-vapor baths, Carlsbad mineral bath.”

You could build up your blood using “Gude’s Pepto-Mangan,” the “Red Blood Builder.” Keep your strength up with Horlick’s Malted Milk.

One ad looked exactly like a news story, carrying the bold headline “Druggists still asked to conserve stocks of VapoRub needed in ‘flu’ districts.” In a tiny notation at the end of the “story” were the words “The Vicks Chemical Co.”

That August 1919 Gazette editorial I mentioned makes me wonder what we’ll be writing in a year or so after our current pandemic.

Death stalking us swiftly from seaboard to seaboard in an unprepared nation, preceded by the casual insistence it’s no worse than the seasonal flu, sounds eerily familiar in 2020. More attention is being paid to hogs than the health of humans working in meatpacking plants.

Will we be writing in 2021 how reopening states and counties too soon led to our own second wave? Here in Iowa, reopening began before we had a fully working predictive model to chart the pandemic’s course and before new testing efforts had a chance to ramp up. Will decisions made without crucial information look smart in 2021? Or will we wish we’d waited just a couple more weeks?

What of the protesters demanding liberation? What about the president, running for reelection in a nation harmed by his crisis mismanagement? What will a new normal look like?

Will there be newspapers around to editorialize in the aftermath? After all, most of the pitches for fake cures are online now, some even extolled at White House briefings.

And will we be better prepared next time? I bet editorial writers in 1919 figured we’d have this pandemic response thing down to a science by now.

Little did they know that in 2020 we’d have so little respect for science. And after a century-plus, the darkness and terror apparently slipped our minds.

(319) 398-8262; todd.dorman@thegazette.com




amp

For Mercy employee on COVID-19 floor, isolating from family is best Mother’s Day gift she can give

This Mother’s Day, April Kelley just wants to give her daughter Jessica Kelley a hug. But she can’t. Jessica, 21, works on the COVID-19 floor at Mercy Medical Center in Cedar Rapids.

To protect her family and still do her job, Jessica is living full time at the hospital, which has made housing available to staff who need to isolate from their families during the pandemic.

“Just based on the floor I’m on, I don’t want to put my family at risk. It’s not worth it,” she said.

Her mother has an autoimmune disorder, adding another layer to Jessica’s worries. Though she does not interact with patients with the coronavirus directly, she still knows exposure is a risk.

“It wasn’t too hard of a decision, but it’s hard on me sometimes,” she said. “I really miss her.”

Jessica is a telemetry monitor technician. For her eight- to 12-hour shifts, her job is to watch heart monitors of patients in the hospital’s intensive care unit. If any patient starts to have cardiac distress or irregular heart rhythms, she and her fellow technicians are the first ones to notice and can notify the doctors and nurses in the main ward.

“It was her choice to either work at the hospital or come home, which was really difficult for her,” April Kelley said. “She’s only 21, so I was pretty proud of her for choosing to help. I don’t think people realize the sacrifice people are making to be there, working in the hospitals right now.”

Jessica is finishing her junior year as a nursing student at Mount Mercy University in Cedar Rapids. When classes moved online and the dorms closed, she had to figure out what to do. While many of her classmates moved back home with their families, doing so would have meant quitting her job. Right now, she said, that job feels more important than ever. In addition to being a full-time student, she works 32 to 36 hours a week at the hospital.

She spent about a week at home with her mother and brother in Humboldt after the dorms closed, but even then, she stayed in her mother’s finished basement and didn’t interact directly with her.

Her older brother, 26, is staying at home with their mom, and she misses him, too. Jessica said to stay connected, she does FaceTime with her mom, a social worker, almost every day.

“She’s definitely one of my best friends, one of my biggest supporters. She is a single mom, and she’s worked two jobs for the last 12 years,” Jessica said. “She always provides for us, and she’s just wonderful in every single way. She’s very caring, she takes care of everybody, no matter where you are.”

This Mother’s Day, those roles have reversed. Now, Jessica is protecting her mother instead of the other way around.

“She said, ‘Mom, I just can’t come home again, I couldn’t put you in that kind of danger,’” April said. “I’m extremely proud of the young lady she is and how responsible she is, and what she is doing during this time, to make sure other people are safe.”

Jessica’s interest in nursing came from her family. Her grandmother, aunt and cousin are all nurses. She also had an experience as a child that stuck with her and inspired her current career goal of becoming a pediatric intensive care nurse after graduation.

In the second grade, she had encephalitis. At first, she said, doctors didn’t believe she was actually sick. Her mother had to take her to a different hospital to get help.

“They said I was making it up, that my screaming and vomiting was just trying to get attention. They said I was faking it,” she said. “At one point, I really did not know who my mom was, and that’s the scariest part, to have someone tell you that’s not real. That’s just not right, and I don’t want other people, especially children to have to deal with that.”

She became interested in the telemetry job after touring the hospital as a student. She said watching the monitors can be surreal, knowing each line she watches represents a patient she may never meet but whose life she is responsible for.

“You see their heart, but you don’t see them,” she said. “Sometimes you watch them die, but never see them. Other times, you see someone going into a fatal rhythm, and you call the nurses ... and when they finally get that person stabilized, you know they might not have made it if we weren’t there. It’s very rewarding.”

April stressed the need for people to follow public health guidelines on social distancing to stay healthy.

“I know they’re starting to open back up and people are eager to get on with their lives,” she said. “But there are a lot of people putting their lives on the line right now ... and I would hate for Jessica to have to go back and self-isolate again if there was a second wave.”

April’s sad she can’t spend this Mother’s Day with her daughter, but right now, that’s not what is important.

“Remember, there’s going to be another Mother’s Day, she said. “We all just have to take care of our people.”

Comments: (319) 398-8339; alison.gowans@thegazette.com




amp

Campgrounds reopen in Iowa Friday, see takers despite some health limitations

Some Eastern Iowans are ready to go camping.

With Gov. Kim Reynolds allowing campgrounds across the state to open Friday, some people wasted little time in heading outdoors.

“They’re already starting to fill up,” said Ryan Schlader of Linn County Conservation. “By about 7 this morning, we had a dozen at Squaw Creek Park. People were coming in bright and early to camp. We’re not surprised.”

Schlader said Linn County Conservation tried to have the campgrounds open at the county’s Squaw Creek, Morgan Creek and Pinicon Ridge parks at 5 a.m. Friday. He expected all of them would be busy.

“I think people were ready to go,” he said.

Lake Macbride State Park in Johnson County didn’t see quite as much of a rush for campsites, park manager Ron Puettmann reported Friday morning, saying he’d had six walk-ins for the park’s 42 campsites.

Camping this weekend will be done on a first-come, first-served basis. Sites won’t be available for reservations until next week, though online reservations can be made now, Puettmann said.

“I’m quite sure people were waiting anxiously to get on,” he said.

While Reynolds’ campground announcement came Wednesday, Schlader and Puettmann said they had no issues having the campgrounds ready for Friday.

Schlader said county staff have been in touch with the Iowa Department of Natural Resources and other county conservation boards to discuss protocols for reopening to ensure a safe experience for campers and employers.

“We anticipated at some point the order would be lifted,” Schlader said. “We were anticipating maybe May 15. The campgrounds were in good shape and ready to go.”

For now, camping comes with some limitations:

• Campers can camp only in a self-contained unit with a functioning restroom, such as a recreational vehicle.

• Shower houses with restrooms will remain closed for the time being.

• Campsites are limited to six people unless they are from the same household.

• No visitors are allowed at the campsites.

Puettmann said staffers and a DNR officer will be on hand to make sure guidelines are followed, but he didn’t anticipate enforcement would be an issue.

“For the most part, we’re going to allow people to police themselves,” he said.

It’s hard to gauge demand, Schlader said.

The weather isn’t yet deal for camping, and some people might not be ready to camp, given the continuing coronavirus.

“There is a lot of uncertainty,” he said. “Do people feel like they need to get out and enjoy a camping experience within their own campsite, or do people still feel under the weather and think it’s not a good idea for my family to go right now? ... We just want this to be an option for people.”

Comments: (319) 339-3155; lee.hermiston@thegazette.com




amp

Pence’s Iowa visit underscores coronavirus worry

DES MOINES — In traveling to Iowa to call attention to the burdens COVID-19 brought to religious services and the food supply, Vice President Mike Pence unwittingly called attention to another issue: whether the White House itself is safe from the disease.

So far this week, two White House aides — President Donald Trump’s valet on Thursday, and Pence’s press secretary on Friday — have tested positive for the virus.

On Friday morning, Pence’s departure to Des Moines was delayed an hour as Air Force Two idled on a tarmac near Washington. Though Pence’s press secretary was not on the plane, White House physicians through contact tracing identified six other aides who had been near her who were aboard, and pulled them from the flight. The White House later said the six had tested negative.

Trump, who identified the Pence aide as press secretary Katie Miller, said he was “not worried” about the virus in the White House.

Nonetheless, officials said they were stepping up safety protocols and were considering a mandatory mask policy for those in close contact with Trump and Pence.

The vice president and 10 members of his staff are given rapid coronavirus tests daily, and the president is also tested regularly.

Miller, who is married to Trump adviser Stephen Miller, had been in recent contact with Pence but not with the president. Pence is leader of the White House coronavirus task force and Katie Miller has handled the group’s communications.

After landing in Des Moines, Pence spoke to a group of faith leaders about the importance of resuming religious services, saying cancellations in the name of slowing the spread of the virus have “been a burden” for congregants.

His visit coincided with the state announcing 12 more deaths from the virus, a total of 243 in less than two months.

Pence spoke with the religious leaders and Republican officials during a brief visit. He also spoke later with agricultural and food company executives.

“It’s been a source of heartache for people across the country,” Pence told about a dozen people at the Church of the Way Presbyterian church in Urbandale.

Pence told the group that continued efforts to hold services online and in other ways “made incalculable difference in our nation seeing our way through these troubled times.”

Iowa is among many states where restrictions on in-person services are starting to ease. GOP Gov. Kim Reynolds, who joined both of the state’s Republican senators at the event, has instituted new rules that allow services to resume with restrictions.

At Friday’s event, some religious leaders expressed hesitation at resuming large gatherings, while others said they would begin holding services soon,

“We are pretty much in a position of uniformly believing that it’s too early to return to personal worship. It’s inadvisable at the moment particularly with rising case counts in communities where we are across the state,” said David Kaufman, rabbi of Temple B’nai Jeshurun in Des Moines.

The Rev. Terry Amann, of Church of the Way, said his church will resume services May 17 with chairs arranged so families can sit together but avoid the temptation to shake hands or offer hugs. He said hand sanitizer will be available.

A new poll by The University of Chicago Divinity School and the Associated Press-NORC Center for Public Affairs Research shows just 9 percent of Americans think in-person services should be allowed without restrictions, while 42 percent think they should be allowed with restrictions and 48 percent think they shouldn’t be allowed at all.

Pence later met with agriculture and food industry leaders. Iowa tops the nation in egg production and pork processing and is a top grower of corn and soybeans.

Meatpacking is among the state’s biggest employers, and companies have been working to restart operations after closing them because hundreds of their workers became infected.

As Pence touted the Trump administration’s announcement of the reopening of 14 meatpacking plants including two of the worst hit by coronavirus infections in Perry and Waterloo, the union representing workers called for safer work conditions.

“Iowa’s meatpacking workers are not sacrificial lambs. They have been working tirelessly during the coronavirus pandemic to ensure families here and across the country have access to the food they need,” said the United Food and Commercial Workers Union in a statement.

The Associated Press and the McClatchy Washington Bureau contributed to this report.




amp

Mother’s Day, Birthdays, Anniversaries: Celebrating during a pandemic

A 10th wedding anniversary traditionally is celebrated with a gift of aluminum or tin.

For Sondy Daggett, her 10th year of marriage to Liz Hoskins was marked with a gift of Champagne and chocolate-covered strawberries shared through a window.

Employees at Bickford of Marion, the assisted living and memory care center where Hoskins is a resident, surprised the couple with the anniversary gift on May 1. Despite the current coronavirus-related mitigation practices, the staff had created a special moment for the couple, who have been partners for 24 years.

Daggett burst into tears as employees played their wedding song — Billy Joel’s “The Longest Time.”

“It just touched my soul,” Daggett said.

Across the state, moments like this are relegated through windows or over a phone call. As the novel coronavirus pandemic sweeps through the country, long-term care facilities have locked down in an effort to keep residents healthy, which means their families are no longer able to hug their loved ones, or sit with them in their rooms.

For many families, the feelings at such times this time are conflicted. Typical Mother’s Day celebrations have been placed on hold, and recent milestones have been missed by those living in long-term care facilities. Simple visits through windows feel distant.

“Those are the moments you remember and you miss,” said Daggett, recalling memories of visits to Bickford of Marion from Hoskins’s grandchildren and family gatherings during the holidays.

Hoskins, who has dementia, has been a resident at Bickford since August 2019.

“The pandemic has taken this away,” Daggett said.

But beyond this new dynamic with which family members are left to grapple, they also have the constant worry that their loved one could fall ill.

So far, Bickford of Marion has not seen any cases.

“Every time you read about another outbreak — whether it’s close to home or anywhere in the country — it brings home how fortunate we are so far,” said Matt Hoskins, Liz Hoskin’s son. “I can’t imagine the anxiety the residents and staff are having once it breaks through the wall.”

As of Friday, 29 long-term care facilities across the state, which includes skilled nursing facilities and senior living centers, among others — have reported outbreaks of COVID-19 among hundreds of their staff and residents.

As a result, for some Iowans, that fear has become a reality.

‘I have to trust’

Ruth Brackett’s son Jamie Degner, a 38-year-old resident at Harmony House Health Care Center in Waterloo, tested positive for COVID-19 this past week.

Degner, who has severe autism and intellectual disabilities, has been a resident there since he was 15 years old.

More than 60 residents and staff have tested positive for COVID-19 at Harmony House, an intermediate care facility. It’s one of two long-term care facilities in Black Hawk County reporting an outbreak, defined as three or more positive tests among residents.

Degner received his test results on Tuesday. He’s had lower-than-normal oxygen levels, but otherwise has recorded his usual vital signs and has not experienced symptoms.

Brackett said it is “unbelievably difficult to not be able to go be with him through this.”

As with many facilities across the state, Harmony House closed its doors to visitors in early March, when the first cases of COVID-19 began being reported across Iowa and the nation. Brackett said her son’s cognitive abilities make it impossible for him to understand that she is unable to visit because she might make him sick, so the staff instead tell Degner his mom is “at work.”

While she’s optimistic he’ll improve, Brackett worries whether Degner’s virus would take a turn for the worse.

“It’s tough because I have to trust” the staff, Brackett said. “There’s nothing I can do, so I can’t spend a lot of time dwelling on what I might do differently.”

The families that spoke to The Gazette believe the leadership at long-term care facilities are doing what they can to keep its residents safe and healthy.

At Bickford of Marion, officials have taken the unique step of promising public transparency of possible COVID-19 cases in its facility. On the website of every Bickford location is a feature recording the number of residents who have tested positive for COVID-19.

“Whether it’s COVID-19 or not, we want to be transparent with families about their loved ones’ care,” Bickford of Marion Executive Director Jacobi Feckers said. “I don’t know why other nursing homes haven’t taken that step because I haven’t spoken to other facilities, but I’m thankful that’s the route we’ve taken.”

It’s not just families who are placing their trust in management. Ron Moore is an independent living resident at Cottage Grove Place, one of the largest senior living centers in Cedar Rapids that has reported an outbreak of COVID-19 this past week.

According to the latest data from public health officials, five residents and staff there have tested positive.

The outbreak originated in the skilled nursing unit, and officials said they are working to ensure the virus doesn’t spread to the assisted-living and independent-living portions of the facility. They restricted movement between the facilities and conduct frequent temperature checks of staff.

So far, the general feeling among residents at Cottage Grove Place’s independent-living housing is that management has “done a good job” of controlling exposure.

“The feelings of the residents here are positive,” Moore said. “They appreciate what management has done to protect us.”

‘Any opportunity to celebrate’

Still, life looks much differently at Cottage Grove Place. Moore said his schedule typically is packed with weekly book clubs and coffees with friends. Now he and his wife take walks, or try to connect with friends over email.

“I’ve found (residents) are not depressed at this time,” he said. “But in the future, if this goes on for many months? My prediction is yes, depression will be a serious thing.”

Local senior living centers have come up with unique ways to allow visitors to see their loved ones. Gina Hausknecht, a 55-year-old Iowa City resident, was able to see her mother in person for the first time in weeks after her assisted-living home, Oaknoll Retirement Community in Iowa City, created a “drive up” visit option this past weekend.

While Hausknecht sat in the car, she was able to speak with her mother, 93-year-old Ellen Hausknecht, for an hour outside the facility. Before this, it had been emotionally difficult for Hausknecht not to see her mom weekly as she usually does

“It sunk in that I don’t know when I’m going to see my mom again, and that felt really terrible,” Hausknecht previously told The Gazette.

Hausknecht said she hopes to take this year’s Mother’s Day as an opportunity to do something special, particularly given the difficult past few weeks.

“Our family isn’t super-big on these kinds of holidays but we do like to acknowledge them, and this year it feels important to take hold of any opportunity to celebrate,” she said.

Other facilities, including Bickford of Marion, also have eased restrictions on sending food and gifts to residents in time for Mother’s Day. Matt Hoskins, Liz’s Hoskins’ son, said the family’s usual Mother’s Day plans are impossible this year, so they hope to send Liz’s Hoskins artwork from her grandchildren along with other gifts.

Brackett, who will be apart from her son Degner this year, said she hadn’t planned anything for the holiday. She looks forward to her first in-person visit with him after the pandemic, when she will bring his favorite meal from McDonald’s and a new deck of Phase 10 cards.

Despite the feelings of being separated, their wedding anniversary on May 1 likely is something Daggett will cherish, she said. With Daggett acting as Hoskins caregiver since her dementia diagnosis in 2016, their wedding anniversary has been something the couple hasn’t celebrated in a significant way in some time, she said.

But that worry still creeps in the back of her mind. Daggett said she’s trying to remain “as confident as anyone can at this point.”

“I learned a long time ago you can’t worry about what you can’t control,” Daggett said. “But does that mean I still wake up at 2 in the morning worried about it? Of course I do.”

Comments: (319) 398-8469; michaela.ramm@thegazette.com




amp

Ampersand, the Aftermath

The first Ampersand web typography conference took place in Brighton last Friday. Ampersand was ace. I’m going to say that again with emphasis: Ampersand was ace! Like the Ready Brek kid from the 80s TV ads I’m glowing with good vibes.

Imagine you’d just met some of the musicians that created the soundtrack to your life. That’s pretty much how I feel.

Nerves and all…

Photo by Ben Mitchell.

For a long, long time I’ve gazed across at the typography community with something akin to awe at the work they do. I’ve lurked quietly on the ATypI mailing list, in the Typophile forum, and behind the glass dividing my eyes from the blogs, portfolios, and galleries.

I always had a sneaking suspicion the web and type design communities had much in common: Excellence born from actual client work; techniques and skills refined by practice, not in a lab or classroom; a willingness to share and disseminate, most clearly demonstrated at Typophile and through web designer’s own blogs. The people of both professions have a very diverse set of backgrounds from graphic design all the way through to engineering, to accidentally working in a print shop. We’ve been apprenticed to our work, and Ampersand was a celebration of what we’ve achieved so far and what’s yet to come.

Of course, web design is a new profession. Type design has a history that spans hundreds of years. Nevertheless, both professions are self-actualising. Few courses exist of any real merit. There is no qualifications authority. The work from both arenas succeeds or fails based on whether it works or not.

Ampersand was the first event of its kind. Folks from both communities came together around the mutal fascination, frustration, challenge and opportunity of web type.

Like Brooklyn Beta, the audience was as fantastic as the line up. I met folks like Yves Peters of the FontFeed, Mike Duggan of Microsoft Typography, Jason Smith, Phil Garnham, Fernando Mello, and Emanuela Conidi of Fontsmith, Veronica Burian of TypeTogether, Adam Twardoch of Fontlab and MyFonts, Nick Sherman of of Webtype, Mandy Brown of A Book Apart and Typekit, and many, many others. (Sorry for stopping there, but wow, it would be a huge list.)

Rich Rutter

Rich Rutter opened the day on behalf of Clearleft and Fontdeck at the Brighton Dome. Rich and I had talked about a web typography conference before. He just went out and did it. Hats off to him, and people like Sophie Barrett at Clearleft who helped make the day run so smoothly.

Others have written comprehensive, insightful summaries of the day and the talks. Much better than I could, sitting there on the day, rapt, taking no notes. What follows are a few snippets my memory threw out when prodded.

Vincent Connare

Who knew the original letterforms for Comic Sans were inspired by a copy of The Watchmen Vincent Connare had in his office? Or that Vincent, who also designed Trebuchet, considers himself an engineer rather than type designer, and is working at the moment on the Ubuntu fonts with colleagues at Dalton Maag.

Jason Santa Maria declared himself a type nerd, and gave a supremely detailed talk about selecting, setting, and understanding web type. Wonderful stuff.

Jason Santa Maria

Jonathan Hoefler talked in rapid, articulate, and precise terms about the work behind upcoming release of pretty-much all of H&FJ’s typefaces as web fonts. (Hooray!) He clearly and wonderfully explained how they took the idea behind their typefaces, and moved them through a design process to produce a final form for a specific purpose. In this case, the web, as a distinct and different environment from print.

Jonathan Hoefler

Photo by Sean Johnson.

I spoke between Jason and Jonathan. Gulp. After staying up until 4am the night before, anxiously working on slides, I was carried along by the privilege and joy of being there, hopefully without too much mumbling or squinting with bleary eyes.

After lunch, David Berlow continued the story of web fonts, taking us on a journey through his own trials and tribulations at Font Bureau when re-producing typefaces for the web crude media. His dry, droll, richly-flavoured delivery was a humorous counterpoint to some controversial asides.

David Berlow

Photo by Jeremy Keith.

John Daggett of Mozilla, editor of the CSS3 Fonts Module, talked with great empathy for web designers about the amazing typographic advances we’re about to see in browsers.

Tim Brown of Typekit followed. Tim calmly and thoroughly advocated the extension of modular scales to all aspects of a web interface, taking values from the body type and building all elements with those values as the common denominator.

Finally, Mark Boulton wrapped up the day brilliantly, describing the designer’s role as the mitigator of entropy, reversing the natural trend for things to move from order to chaos, and a theme he’s exploring at the moment: designing from the content out.

Mark Boulton

The tone of the day was fun, thoughtful, articulate, and exacting. All the talks were a mix of anecdotal and observational humour, type nerdery, and most of all an overwhelming commitment to excellence in web typography. It was a journey in itself. Decades of experience from plate and press, screen, and web was being distilled into 45-minute presentations. I loved it.

As always, one of the most enjoyable bits for me was the hallway track. I talked to heaps of people both in the pre- and after-party, and in between the talks on the day itself. I heard stories, ideas, and opinions from print designers, web designers, type designers, font developers, and writers. We talked late into the night. We talked more the next day.

Now the talking has paused for a while, my thoughts are manifold. I can honestly say, I’ve never been so filled with positivity about where we are, and where we’re going. Web typography is here, it works, it’s better all the time, and one day web and type designers everywhere will wonder, perplexed, as they try to imagine what the web was like before.

Here’s to another Ampersand next year! I’m now going to see if Rich needs any encouragement to do it again. I’m guessing not, but if he does, I aim to provide it, vigorously. I hope I see you there!

Furthermore

Last but not least, did I mention that Rich Rutter, Mark Boulton, and I are writing a book? We are! More on that another time, but until then, follow @webtypography for intermittent updates.




amp

Concurrency & Multithreading in iOS

Concurrency is the notion of multiple things happening at the same time. This is generally achieved either via time-slicing, or truly in parallel if multiple CPU cores are available to the host operating system. We've all experienced a lack of concurrency, most likely in the form of an app freezing up when running a heavy task. UI freezes don't necessarily occur due to the absence of concurrency — they could just be symptoms of buggy software — but software that doesn't take advantage of all the computational power at its disposal is going to create these freezes whenever it needs to do something resource-intensive. If you've profiled an app hanging in this way, you'll probably see a report that looks like this:

Anything related to file I/O, data processing, or networking usually warrants a background task (unless you have a very compelling excuse to halt the entire program). There aren't many reasons that these tasks should block your user from interacting with the rest of your application. Consider how much better the user experience of your app could be if instead, the profiler reported something like this:

Analyzing an image, processing a document or a piece of audio, or writing a sizeable chunk of data to disk are examples of tasks that could benefit greatly from being delegated to background threads. Let's dig into how we can enforce such behavior into our iOS applications.


A Brief History

In the olden days, the maximum amount of work per CPU cycle that a computer could perform was determined by the clock speed. As processor designs became more compact, heat and physical constraints started becoming limiting factors for higher clock speeds. Consequentially, chip manufacturers started adding additional processor cores on each chip in order to increase total performance. By increasing the number of cores, a single chip could execute more CPU instructions per cycle without increasing its speed, size, or thermal output. There's just one problem...

How can we take advantage of these extra cores? Multithreading.

Multithreading is an implementation handled by the host operating system to allow the creation and usage of n amount of threads. Its main purpose is to provide simultaneous execution of two or more parts of a program to utilize all available CPU time. Multithreading is a powerful technique to have in a programmer's toolbelt, but it comes with its own set of responsibilities. A common misconception is that multithreading requires a multi-core processor, but this isn't the case — single-core CPUs are perfectly capable of working on many threads, but we'll take a look in a bit as to why threading is a problem in the first place. Before we dive in, let's look at the nuances of what concurrency and parallelism mean using a simple diagram:

In the first situation presented above, we observe that tasks can run concurrently, but not in parallel. This is similar to having multiple conversations in a chatroom, and interleaving (context-switching) between them, but never truly conversing with two people at the same time. This is what we call concurrency. It is the illusion of multiple things happening at the same time when in reality, they're switching very quickly. Concurrency is about dealing with lots of things at the same time. Contrast this with the parallelism model, in which both tasks run simultaneously. Both execution models exhibit multithreading, which is the involvement of multiple threads working towards one common goal. Multithreading is a generalized technique for introducing a combination of concurrency and parallelism into your program.


The Burden of Threads

A modern multitasking operating system like iOS has hundreds of programs (or processes) running at any given moment. However, most of these programs are either system daemons or background processes that have very low memory footprint, so what is really needed is a way for individual applications to make use of the extra cores available. An application (process) can have many threads (sub-processes) operating on shared memory. Our goal is to be able to control these threads and use them to our advantage.

Historically, introducing concurrency to an app has required the creation of one or more threads. Threads are low-level constructs that need to be managed manually. A quick skim through Apple's Threaded Programming Guide is all it takes to see how much complexity threaded code adds to a codebase. In addition to building an app, the developer has to:

  • Responsibly create new threads, adjusting that number dynamically as system conditions change
  • Manage them carefully, deallocating them from memory once they have finished executing
  • Leverage synchronization mechanisms like mutexes, locks, and semaphores to orchestrate resource access between threads, adding even more overhead to application code
  • Mitigate risks associated with coding an application that assumes most of the costs associated with creating and maintaining any threads it uses, and not the host OS

This is unfortunate, as it adds enormous levels of complexity and risk without any guarantees of improved performance.


Grand Central Dispatch

iOS takes an asynchronous approach to solving the concurrency problem of managing threads. Asynchronous functions are common in most programming environments, and are often used to initiate tasks that might take a long time, like reading a file from the disk, or downloading a file from the web. When invoked, an asynchronous function executes some work behind the scenes to start a background task, but returns immediately, regardless of how long the original task might takes to actually complete.

A core technology that iOS provides for starting tasks asynchronously is Grand Central Dispatch (or GCD for short). GCD abstracts away thread management code and moves it down to the system level, exposing a light API to define tasks and execute them on an appropriate dispatch queue. GCD takes care of all thread management and scheduling, providing a holistic approach to task management and execution, while also providing better efficiency than traditional threads.

Let's take a look at the main components of GCD:

What've we got here? Let's start from the left:

  • DispatchQueue.main: The main thread, or the UI thread, is backed by a single serial queue. All tasks are executed in succession, so it is guaranteed that the order of execution is preserved. It is crucial that you ensure all UI updates are designated to this queue, and that you never run any blocking tasks on it. We want to ensure that the app's run loop (called CFRunLoop) is never blocked in order to maintain the highest framerate. Subsequently, the main queue has the highest priority, and any tasks pushed onto this queue will get executed immediately.
  • DispatchQueue.global: A set of global concurrent queues, each of which manage their own pool of threads. Depending on the priority of your task, you can specify which specific queue to execute your task on, although you should resort to using default most of the time. Because tasks on these queues are executed concurrently, it doesn't guarantee preservation of the order in which tasks were queued.

Notice how we're not dealing with individual threads anymore? We're dealing with queues which manage a pool of threads internally, and you will shortly see why queues are a much more sustainable approach to multhreading.

Serial Queues: The Main Thread

As an exercise, let's look at a snippet of code below, which gets fired when the user presses a button in the app. The expensive compute function can be anything. Let's pretend it is post-processing an image stored on the device.

import UIKit

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        compute()
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

At first glance, this may look harmless, but if you run this inside of a real app, the UI will freeze completely until the loop is terminated, which will take... a while. We can prove it by profiling this task in Instruments. You can fire up the Time Profiler module of Instruments by going to Xcode > Open Developer Tool > Instruments in Xcode's menu options. Let's look at the Threads module of the profiler and see where the CPU usage is highest.

We can see that the Main Thread is clearly at 100% capacity for almost 5 seconds. That's a non-trivial amount of time to block the UI. Looking at the call tree below the chart, we can see that the Main Thread is at 99.9% capacity for 4.43 seconds! Given that a serial queue works in a FIFO manner, tasks will always complete in the order in which they were inserted. Clearly the compute() method is the culprit here. Can you imagine clicking a button just to have the UI freeze up on you for that long?

Background Threads

How can we make this better? DispatchQueue.global() to the rescue! This is where background threads come in. Referring to the GCD architecture diagram above, we can see that anything that is not the Main Thread is a background thread in iOS. They can run alongside the Main Thread, leaving it fully unoccupied and ready to handle other UI events like scrolling, responding to user events, animating etc. Let's make a small change to our button click handler above:

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
            self.compute()
        }
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Unless specified, a snippet of code will usually default to execute on the Main Queue, so in order to force it to execute on a different thread, we'll wrap our compute call inside of an asynchronous closure that gets submitted to the DispatchQueue.global queue. Keep in mind that we aren't really managing threads here. We're submitting tasks (in the form of closures or blocks) to the desired queue with the assumption that it is guaranteed to execute at some point in time. The queue decides which thread to allocate the task to, and it does all the hard work of assessing system requirements and managing the actual threads. This is the magic of Grand Central Dispatch. As the old adage goes, you can't improve what you can't measure. So we measured our truly terrible button click handler, and now that we've improved it, we'll measure it once again to get some concrete data with regards to performance.

Looking at the profiler again, it's quite clear to us that this is a huge improvement. The task takes an identical amount of time, but this time, it's happening in the background without locking up the UI. Even though our app is doing the same amount of work, the perceived performance is much better because the user will be free to do other things while the app is processing.

You may have noticed that we accessed a global queue of .userInitiated priority. This is an attribute we can use to give our tasks a sense of urgency. If we run the same task on a global queue of and pass it a qos attribute of background , iOS will think it's a utility task, and thus allocate fewer resources to execute it. So, while we don't have control over when our tasks get executed, we do have control over their priority.

A Note on Main Thread vs. Main Queue

You might be wondering why the Profiler shows "Main Thread" and why we're referring to it as the "Main Queue". If you refer back to the GCD architecture we described above, the Main Queue is solely responsible for managing the Main Thread. The Dispatch Queues section in the Concurrency Programming Guide says that "the main dispatch queue is a globally available serial queue that executes tasks on the application’s main thread. Because it runs on your application’s main thread, the main queue is often used as a key synchronization point for an application."

The terms "execute on the Main Thread" and "execute on the Main Queue" can be used interchangeably.


Concurrent Queues

So far, our tasks have been executed exclusively in a serial manner. DispatchQueue.main is by default a serial queue, and DispatchQueue.global gives you four concurrent dispatch queues depending on the priority parameter you pass in.

Let's say we want to take five images, and have our app process them all in parallel on background threads. How would we go about doing that? We can spin up a custom concurrent queue with an identifier of our choosing, and allocate those tasks there. All that's required is the .concurrent attribute during the construction of the queue.

class ViewController: UIViewController {
    let queue = DispatchQueue(label: "com.app.concurrentQueue", attributes: .concurrent)
    let images: [UIImage] = [UIImage].init(repeating: UIImage(), count: 5)

    @IBAction func handleTap(_ sender: Any) {
        for img in images {
            queue.async { [unowned self] in
                self.compute(img)
            }
        }
    }

    private func compute(_ img: UIImage) -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Running that through the profiler, we can see that the app is now spinning up 5 discrete threads to parallelize a for-loop.

Parallelization of N Tasks

So far, we've looked at pushing computationally expensive task(s) onto background threads without clogging up the UI thread. But what about executing parallel tasks with some restrictions? How can Spotify download multiple songs in parallel, while limiting the maximum number up to 3? We can go about this in a few ways, but this is a good time to explore another important construct in multithreaded programming: semaphores.

Semaphores are signaling mechanisms. They are commonly used to control access to a shared resource. Imagine a scenario where a thread can lock access to a certain section of the code while it executes it, and unlocks after it's done to let other threads execute the said section of the code. You would see this type of behavior in database writes and reads, for example. What if you want only one thread writing to a database and preventing any reads during that time? This is a common concern in thread-safety called Readers-writer lock. Semaphores can be used to control concurrency in our app by allowing us to lock n number of threads.

let kMaxConcurrent = 3 // Or 1 if you want strictly ordered downloads!
let semaphore = DispatchSemaphore(value: kMaxConcurrent)
let downloadQueue = DispatchQueue(label: "com.app.downloadQueue", attributes: .concurrent)

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        for i in 0..<15 {
            downloadQueue.async { [unowned self] in
                // Lock shared resource access
                semaphore.wait()

                // Expensive task
                self.download(i + 1)

                // Update the UI on the main thread, always!
                DispatchQueue.main.async {
                    tableView.reloadData()

                    // Release the lock
                    semaphore.signal()
                }
            }
        }
    }

    func download(_ songId: Int) -> Void {
        var counter = 0

        // Simulate semi-random download times.
        for _ in 0..<Int.random(in: 999999...10000000) {
            counter += songId
        }
    }
}

Notice how we've effectively restricted our download system to limit itself to k number of downloads. The moment one download finishes (or thread is done executing), it decrements the semaphore, allowing the managing queue to spawn another thread and start downloading another song. You can apply a similar pattern to database transactions when dealing with concurrent reads and writes.

Semaphores usually aren't necessary for code like the one in our example, but they become more powerful when you need to enforce synchronous behavior whille consuming an asynchronous API. The above could would work just as well with a custom NSOperationQueue with a maxConcurrentOperationCount, but it's a worthwhile tangent regardless.


Finer Control with OperationQueue

GCD is great when you want to dispatch one-off tasks or closures into a queue in a 'set-it-and-forget-it' fashion, and it provides a very lightweight way of doing so. But what if we want to create a repeatable, structured, long-running task that produces associated state or data? And what if we want to model this chain of operations such that they can be cancelled, suspended and tracked, while still working with a closure-friendly API? Imagine an operation like this:

This would be quite cumbersome to achieve with GCD. We want a more modular way of defining a group of tasks while maintaining readability and also exposing a greater amount of control. In this case, we can use Operation objects and queue them onto an OperationQueue, which is a high-level wrapper around DispatchQueue. Let's look at some of the benefits of using these abstractions and what they offer in comparison to the lower-level GCI API:

  • You may want to create dependencies between tasks, and while you could do this via GCD, you're better off defining them concretely as Operation objects, or units of work, and pushing them onto your own queue. This would allow for maximum reusability since you may use the same pattern elsewhere in an application.
  • The Operation and OperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing). This is another important benefit if you want to monitor the state of an operation or operation queue.
  • Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. The Operation API is more flexible in that respect, giving the developer control over the operation's life cycle.
  • OperationQueue allows you to specify the maximum number of queued operations that can run simultaneously, giving you a finer degree of control over the concurrency aspects.

The usage of Operation and OperationQueue could fill an entire blog post, but let's look at a quick example of what modeling dependencies looks like. (GCD can also create dependencies, but you're better off dividing up large tasks into a series of composable sub-tasks.) In order to create a chain of operations that depend on one another, we could do something like this:

class ViewController: UIViewController {
    var queue = OperationQueue()
    var rawImage = UIImage? = nil
    let imageUrl = URL(string: "https://example.com/portrait.jpg")!
    @IBOutlet weak var imageView: UIImageView!

    let downloadOperation = BlockOperation {
        let image = Downloader.downloadImageWithURL(url: imageUrl)
        OperationQueue.main.async {
            self.rawImage = image
        }
    }

    let filterOperation = BlockOperation {
        let filteredImage = ImgProcessor.addGaussianBlur(self.rawImage)
        OperationQueue.main.async {
            self.imageView = filteredImage
        }
    }

    filterOperation.addDependency(downloadOperation)

    [downloadOperation, filterOperation].forEach {
        queue.addOperation($0)
     }
}

So why not opt for a higher level abstraction and avoid using GCD entirely? While GCD is ideal for inline asynchronous processing, Operation provides a more comprehensive, object-oriented model of computation for encapsulating all of the data around structured, repeatable tasks in an application. Developers should use the highest level of abstraction possible for any given problem, and for scheduling consistent, repeated work, that abstraction is Operation. Other times, it makes more sense to sprinkle in some GCD for one-off tasks or closures that we want to fire. We can mix both OperationQueue and GCD to get the best of both worlds.


The Cost of Concurrency

DispatchQueue and friends are meant to make it easier for the application developer to execute code concurrently. However, these technologies do not guarantee improvements to the efficiency or responsiveness in an application. It is up to you to use queues in a manner that is both effective and does not impose an undue burden on other resources. For example, it's totally viable to create 10,000 tasks and submit them to a queue, but doing so would allocate a nontrivial amount of memory and introduce a lot of overhead for the allocation and deallocation of operation blocks. This is the opposite of what you want! It's best to profile your app thoroughly to ensure that concurrency is enhancing your app's performance and not degrading it.

We've talked about how concurrency comes at a cost in terms of complexity and allocation of system resources, but introducing concurrency also brings a host of other risks like:

  • Deadlock: A situation where a thread locks a critical portion of the code and can halt the application's run loop entirely. In the context of GCD, you should be very careful when using the dispatchQueue.sync { } calls as you could easily get yourself in situations where two synchronous operations can get stuck waiting for each other.
  • Priority Inversion: A condition where a lower priority task blocks a high priority task from executing, which effectively inverts their priorities. GCD allows for different levels of priority on its background queues, so this is quite easily a possibility.
  • Producer-Consumer Problem: A race condition where one thread is creating a data resource while another thread is accessing it. This is a synchronization problem, and can be solved using locks, semaphores, serial queues, or a barrier dispatch if you're using concurrent queues in GCD.
  • ...and many other sorts of locking and data-race conditions that are hard to debug! Thread safety is of the utmost concern when dealing with concurrency.

Parting Thoughts + Further Reading

If you've made it this far, I applaud you. Hopefully this article gives you a lay of the land when it comes to multithreading techniques on iOS, and how you can use some of them in your app. We didn't get to cover many of the lower-level constructs like locks, mutexes and how they help us achieve synchronization, nor did we get to dive into concrete examples of how concurrency can hurt your app. We'll save those for another day, but you can dig into some additional reading and videos if you're eager to dive deeper.




amp

CLI Equivalents for Common MAMP PRO and Sequel Pro Tasks

Working on website front ends I sometimes use MAMP PRO to manage local hosts and Sequel Pro to manage databases. Living primarily in my text editor, a terminal, and a browser window, moving to these click-heavy dedicated apps can feel clunky. Happily, the tasks I have most frequently turned to those apps for —starting and stopping servers, creating new hosts, and importing, exporting, deleting, and creating databases— can be done from the command line.

I still pull up MAMP PRO if I need to change a host's PHP version or work with its other more specialized settings, or Sequel Pro to quickly inspect a database, but for the most part I can stay on the keyboard and in my terminal. Here's how:

Command Line MAMP PRO

You can start and stop MAMP PRO's servers from the command line. You can even do this when the MAMP PRO desktop app isn't open.

Note: MAMP PRO's menu icon will not change color to reflect the running/stopped status when the status is changed via the command line.

  • Start the MAMP PRO servers:
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd startServers
  • Stop the MAMP PRO servers:
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd stopServers
  • Create a host (replace host_name and root_path):
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd createHost host_name root_path

MAMP PRO-friendly Command Line Sequel Pro

Note: if you don't use MAMP PRO, just replace the /Applications/MAMP/Library/bin/mysql with mysql.

In all of the following commands, replace username with your user name (locally this is likely root) and database_name with your database name. The -p (password) flag with no argument will trigger an interactive password prompt. This is more secure than including your password in the command itself (like -pYourPasswordHere). Of course, if you're using the default password root is not particular secure to begin with so you might just do -pYourPasswordHere.

Setting the -h (host) flag to localhost or 127.0.0.1 tells mysql to look at what's on localhost. With the MAMP PRO servers running, that will be the MAMP PRO databases.

# with the MAMP PRO servers running, these are equivalent:
# /Applications/MAMP/Library/bin/mysql -h 127.0.0.1 other_options
# and
# /Applications/MAMP/Library/bin/mysql -h localhost other_options

/Applications/MAMP/Library/bin/mysql mysql_options # enter. opens an interactive mysql session
mysql> some command; # don't forget the semicolon
mysql> exit;
  • Create a local database
# with the MAMP PRO servers running
# replace `username` with your username, which is `root` by default
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p -e "create database database_name"

or

# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p # and then enter
mysql> create database database_name; # don't forget the semicolon
mysql> exit

    MAMP PRO's databases are stored in /Library/Application Support/appsolute/MAMP PRO/db so to confirm that it worked you can

ls /Library/Application Support/appsolute/MAMP PRO/db
# will output the available mysql versions. For example I have
mysql56_2018-11-05_16-25-13     mysql57

# If it isn't clear which one you're after, open the main MAMP PRO and click
# on the MySQL "servers and services" item. In my case it shows "Version: 5.7.26"

# Now look in the relevant MySQL directory
ls /Library/Application Support/appsolute/MAMP PRO/db/mysql57
# the newly created database should be in the list
  • Delete a local database
# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p -e "drop database database_name"
  • Export a dump of a local database. Note that this uses mysqldump not mysql.
# to export an uncompressed file
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysqldump -h localhost -u username -p database_name > the/output/path.sql

# to export a compressed file
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysqldump -h localhost -u username -p database_name | gzip -c > the/output/path.gz

  • Export a local dump from an external database over SSH. Note that this uses mysqldump not mysql.

# replace `ssh-user`, `ssh_host`, `mysql_user`, `database_name`, and the output path

# to end up with an uncompressed file
ssh ssh_user@ssh_host "mysqldump -u mysql_user -p database_name | gzip -c" | gunzip > the/output/path.sql

# to end up with a compressed file
ssh ssh_user@ssh_host "mysqldump -u mysql_user -p database_name | gzip -c" > the/output/path.gz
  • Import a local database dump into a local database
# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p database_name < the/dump/path.sql
  • Import a local database dump into a remote database over SSH. Use care with this one. But if you are doing it with Sequel Pro —maybe you are copying a Craft site's database from a production server to a QA server— you might as well be able to do it on the command line.
ssh ssh_user@ssh_host "mysql -u username -p remote_database_name" < the/local/dump/path.sql


For me, using the command line instead of the MAMP PRO and Sequel Pro GUI means less switching between keyboard and mouse, less opening up GUI features that aren't typically visible on my screen, and generally better DX. Give it a try! And while MAMP Pro's CLI is limited to the essentials, command line mysql of course knows no limits. If there's something else you use Sequel Pro for, you may be able to come up with a mysql CLI equivalent you like even better.



  • Code
  • Front-end Engineering
  • Back-end Engineering

amp

What’s New in Recipe Card Blocks Free & PRO

It’s been a few months since the release of the Recipe Card Blocks PRO plugin, and our team continued to release new updates constantly for both versions of the plugin: Free & PRO. As we’ve released many major updates for both versions in the past months, let’s make a quick overview of the most important changes and new features we’ve […]




amp

Reel 3.0: New Color Schemes, Portfolio Styles & More!

We’re very excited to announce a new major update for our Reel theme. The new 3.0 version brings new color schemes and many improvements to the Portfolio Showcase widget. What’s new in 3.0? 5 New Color Schemes + 2 New Theme Styles Full-width header option New styles & options for Portfolio Showcase widget 5 New Color Schemes After long research […]




amp

Presence 2.0: Beaver Builder Integration, Dark Skin & More!

Great news for the users of Presence — our multipurpose theme. We have finally released the long-awaited 2.0 version, which features major changes and improvements. What’s new in Presence 2.0? Beaver Builder Integration Dark Skin New Demo: Organic Shop New Typography and Colors options in the Customizer New Templates in Page Builder Beaver Builder Integration If you have followed recent […]




amp

Concurrency & Multithreading in iOS

Concurrency is the notion of multiple things happening at the same time. This is generally achieved either via time-slicing, or truly in parallel if multiple CPU cores are available to the host operating system. We've all experienced a lack of concurrency, most likely in the form of an app freezing up when running a heavy task. UI freezes don't necessarily occur due to the absence of concurrency — they could just be symptoms of buggy software — but software that doesn't take advantage of all the computational power at its disposal is going to create these freezes whenever it needs to do something resource-intensive. If you've profiled an app hanging in this way, you'll probably see a report that looks like this:

Anything related to file I/O, data processing, or networking usually warrants a background task (unless you have a very compelling excuse to halt the entire program). There aren't many reasons that these tasks should block your user from interacting with the rest of your application. Consider how much better the user experience of your app could be if instead, the profiler reported something like this:

Analyzing an image, processing a document or a piece of audio, or writing a sizeable chunk of data to disk are examples of tasks that could benefit greatly from being delegated to background threads. Let's dig into how we can enforce such behavior into our iOS applications.


A Brief History

In the olden days, the maximum amount of work per CPU cycle that a computer could perform was determined by the clock speed. As processor designs became more compact, heat and physical constraints started becoming limiting factors for higher clock speeds. Consequentially, chip manufacturers started adding additional processor cores on each chip in order to increase total performance. By increasing the number of cores, a single chip could execute more CPU instructions per cycle without increasing its speed, size, or thermal output. There's just one problem...

How can we take advantage of these extra cores? Multithreading.

Multithreading is an implementation handled by the host operating system to allow the creation and usage of n amount of threads. Its main purpose is to provide simultaneous execution of two or more parts of a program to utilize all available CPU time. Multithreading is a powerful technique to have in a programmer's toolbelt, but it comes with its own set of responsibilities. A common misconception is that multithreading requires a multi-core processor, but this isn't the case — single-core CPUs are perfectly capable of working on many threads, but we'll take a look in a bit as to why threading is a problem in the first place. Before we dive in, let's look at the nuances of what concurrency and parallelism mean using a simple diagram:

In the first situation presented above, we observe that tasks can run concurrently, but not in parallel. This is similar to having multiple conversations in a chatroom, and interleaving (context-switching) between them, but never truly conversing with two people at the same time. This is what we call concurrency. It is the illusion of multiple things happening at the same time when in reality, they're switching very quickly. Concurrency is about dealing with lots of things at the same time. Contrast this with the parallelism model, in which both tasks run simultaneously. Both execution models exhibit multithreading, which is the involvement of multiple threads working towards one common goal. Multithreading is a generalized technique for introducing a combination of concurrency and parallelism into your program.


The Burden of Threads

A modern multitasking operating system like iOS has hundreds of programs (or processes) running at any given moment. However, most of these programs are either system daemons or background processes that have very low memory footprint, so what is really needed is a way for individual applications to make use of the extra cores available. An application (process) can have many threads (sub-processes) operating on shared memory. Our goal is to be able to control these threads and use them to our advantage.

Historically, introducing concurrency to an app has required the creation of one or more threads. Threads are low-level constructs that need to be managed manually. A quick skim through Apple's Threaded Programming Guide is all it takes to see how much complexity threaded code adds to a codebase. In addition to building an app, the developer has to:

  • Responsibly create new threads, adjusting that number dynamically as system conditions change
  • Manage them carefully, deallocating them from memory once they have finished executing
  • Leverage synchronization mechanisms like mutexes, locks, and semaphores to orchestrate resource access between threads, adding even more overhead to application code
  • Mitigate risks associated with coding an application that assumes most of the costs associated with creating and maintaining any threads it uses, and not the host OS

This is unfortunate, as it adds enormous levels of complexity and risk without any guarantees of improved performance.


Grand Central Dispatch

iOS takes an asynchronous approach to solving the concurrency problem of managing threads. Asynchronous functions are common in most programming environments, and are often used to initiate tasks that might take a long time, like reading a file from the disk, or downloading a file from the web. When invoked, an asynchronous function executes some work behind the scenes to start a background task, but returns immediately, regardless of how long the original task might takes to actually complete.

A core technology that iOS provides for starting tasks asynchronously is Grand Central Dispatch (or GCD for short). GCD abstracts away thread management code and moves it down to the system level, exposing a light API to define tasks and execute them on an appropriate dispatch queue. GCD takes care of all thread management and scheduling, providing a holistic approach to task management and execution, while also providing better efficiency than traditional threads.

Let's take a look at the main components of GCD:

What've we got here? Let's start from the left:

  • DispatchQueue.main: The main thread, or the UI thread, is backed by a single serial queue. All tasks are executed in succession, so it is guaranteed that the order of execution is preserved. It is crucial that you ensure all UI updates are designated to this queue, and that you never run any blocking tasks on it. We want to ensure that the app's run loop (called CFRunLoop) is never blocked in order to maintain the highest framerate. Subsequently, the main queue has the highest priority, and any tasks pushed onto this queue will get executed immediately.
  • DispatchQueue.global: A set of global concurrent queues, each of which manage their own pool of threads. Depending on the priority of your task, you can specify which specific queue to execute your task on, although you should resort to using default most of the time. Because tasks on these queues are executed concurrently, it doesn't guarantee preservation of the order in which tasks were queued.

Notice how we're not dealing with individual threads anymore? We're dealing with queues which manage a pool of threads internally, and you will shortly see why queues are a much more sustainable approach to multhreading.

Serial Queues: The Main Thread

As an exercise, let's look at a snippet of code below, which gets fired when the user presses a button in the app. The expensive compute function can be anything. Let's pretend it is post-processing an image stored on the device.

import UIKit

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        compute()
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

At first glance, this may look harmless, but if you run this inside of a real app, the UI will freeze completely until the loop is terminated, which will take... a while. We can prove it by profiling this task in Instruments. You can fire up the Time Profiler module of Instruments by going to Xcode > Open Developer Tool > Instruments in Xcode's menu options. Let's look at the Threads module of the profiler and see where the CPU usage is highest.

We can see that the Main Thread is clearly at 100% capacity for almost 5 seconds. That's a non-trivial amount of time to block the UI. Looking at the call tree below the chart, we can see that the Main Thread is at 99.9% capacity for 4.43 seconds! Given that a serial queue works in a FIFO manner, tasks will always complete in the order in which they were inserted. Clearly the compute() method is the culprit here. Can you imagine clicking a button just to have the UI freeze up on you for that long?

Background Threads

How can we make this better? DispatchQueue.global() to the rescue! This is where background threads come in. Referring to the GCD architecture diagram above, we can see that anything that is not the Main Thread is a background thread in iOS. They can run alongside the Main Thread, leaving it fully unoccupied and ready to handle other UI events like scrolling, responding to user events, animating etc. Let's make a small change to our button click handler above:

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
            self.compute()
        }
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Unless specified, a snippet of code will usually default to execute on the Main Queue, so in order to force it to execute on a different thread, we'll wrap our compute call inside of an asynchronous closure that gets submitted to the DispatchQueue.global queue. Keep in mind that we aren't really managing threads here. We're submitting tasks (in the form of closures or blocks) to the desired queue with the assumption that it is guaranteed to execute at some point in time. The queue decides which thread to allocate the task to, and it does all the hard work of assessing system requirements and managing the actual threads. This is the magic of Grand Central Dispatch. As the old adage goes, you can't improve what you can't measure. So we measured our truly terrible button click handler, and now that we've improved it, we'll measure it once again to get some concrete data with regards to performance.

Looking at the profiler again, it's quite clear to us that this is a huge improvement. The task takes an identical amount of time, but this time, it's happening in the background without locking up the UI. Even though our app is doing the same amount of work, the perceived performance is much better because the user will be free to do other things while the app is processing.

You may have noticed that we accessed a global queue of .userInitiated priority. This is an attribute we can use to give our tasks a sense of urgency. If we run the same task on a global queue of and pass it a qos attribute of background , iOS will think it's a utility task, and thus allocate fewer resources to execute it. So, while we don't have control over when our tasks get executed, we do have control over their priority.

A Note on Main Thread vs. Main Queue

You might be wondering why the Profiler shows "Main Thread" and why we're referring to it as the "Main Queue". If you refer back to the GCD architecture we described above, the Main Queue is solely responsible for managing the Main Thread. The Dispatch Queues section in the Concurrency Programming Guide says that "the main dispatch queue is a globally available serial queue that executes tasks on the application’s main thread. Because it runs on your application’s main thread, the main queue is often used as a key synchronization point for an application."

The terms "execute on the Main Thread" and "execute on the Main Queue" can be used interchangeably.


Concurrent Queues

So far, our tasks have been executed exclusively in a serial manner. DispatchQueue.main is by default a serial queue, and DispatchQueue.global gives you four concurrent dispatch queues depending on the priority parameter you pass in.

Let's say we want to take five images, and have our app process them all in parallel on background threads. How would we go about doing that? We can spin up a custom concurrent queue with an identifier of our choosing, and allocate those tasks there. All that's required is the .concurrent attribute during the construction of the queue.

class ViewController: UIViewController {
    let queue = DispatchQueue(label: "com.app.concurrentQueue", attributes: .concurrent)
    let images: [UIImage] = [UIImage].init(repeating: UIImage(), count: 5)

    @IBAction func handleTap(_ sender: Any) {
        for img in images {
            queue.async { [unowned self] in
                self.compute(img)
            }
        }
    }

    private func compute(_ img: UIImage) -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Running that through the profiler, we can see that the app is now spinning up 5 discrete threads to parallelize a for-loop.

Parallelization of N Tasks

So far, we've looked at pushing computationally expensive task(s) onto background threads without clogging up the UI thread. But what about executing parallel tasks with some restrictions? How can Spotify download multiple songs in parallel, while limiting the maximum number up to 3? We can go about this in a few ways, but this is a good time to explore another important construct in multithreaded programming: semaphores.

Semaphores are signaling mechanisms. They are commonly used to control access to a shared resource. Imagine a scenario where a thread can lock access to a certain section of the code while it executes it, and unlocks after it's done to let other threads execute the said section of the code. You would see this type of behavior in database writes and reads, for example. What if you want only one thread writing to a database and preventing any reads during that time? This is a common concern in thread-safety called Readers-writer lock. Semaphores can be used to control concurrency in our app by allowing us to lock n number of threads.

let kMaxConcurrent = 3 // Or 1 if you want strictly ordered downloads!
let semaphore = DispatchSemaphore(value: kMaxConcurrent)
let downloadQueue = DispatchQueue(label: "com.app.downloadQueue", attributes: .concurrent)

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        for i in 0..<15 {
            downloadQueue.async { [unowned self] in
                // Lock shared resource access
                semaphore.wait()

                // Expensive task
                self.download(i + 1)

                // Update the UI on the main thread, always!
                DispatchQueue.main.async {
                    tableView.reloadData()

                    // Release the lock
                    semaphore.signal()
                }
            }
        }
    }

    func download(_ songId: Int) -> Void {
        var counter = 0

        // Simulate semi-random download times.
        for _ in 0..<Int.random(in: 999999...10000000) {
            counter += songId
        }
    }
}

Notice how we've effectively restricted our download system to limit itself to k number of downloads. The moment one download finishes (or thread is done executing), it decrements the semaphore, allowing the managing queue to spawn another thread and start downloading another song. You can apply a similar pattern to database transactions when dealing with concurrent reads and writes.

Semaphores usually aren't necessary for code like the one in our example, but they become more powerful when you need to enforce synchronous behavior whille consuming an asynchronous API. The above could would work just as well with a custom NSOperationQueue with a maxConcurrentOperationCount, but it's a worthwhile tangent regardless.


Finer Control with OperationQueue

GCD is great when you want to dispatch one-off tasks or closures into a queue in a 'set-it-and-forget-it' fashion, and it provides a very lightweight way of doing so. But what if we want to create a repeatable, structured, long-running task that produces associated state or data? And what if we want to model this chain of operations such that they can be cancelled, suspended and tracked, while still working with a closure-friendly API? Imagine an operation like this:

This would be quite cumbersome to achieve with GCD. We want a more modular way of defining a group of tasks while maintaining readability and also exposing a greater amount of control. In this case, we can use Operation objects and queue them onto an OperationQueue, which is a high-level wrapper around DispatchQueue. Let's look at some of the benefits of using these abstractions and what they offer in comparison to the lower-level GCI API:

  • You may want to create dependencies between tasks, and while you could do this via GCD, you're better off defining them concretely as Operation objects, or units of work, and pushing them onto your own queue. This would allow for maximum reusability since you may use the same pattern elsewhere in an application.
  • The Operation and OperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing). This is another important benefit if you want to monitor the state of an operation or operation queue.
  • Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. The Operation API is more flexible in that respect, giving the developer control over the operation's life cycle.
  • OperationQueue allows you to specify the maximum number of queued operations that can run simultaneously, giving you a finer degree of control over the concurrency aspects.

The usage of Operation and OperationQueue could fill an entire blog post, but let's look at a quick example of what modeling dependencies looks like. (GCD can also create dependencies, but you're better off dividing up large tasks into a series of composable sub-tasks.) In order to create a chain of operations that depend on one another, we could do something like this:

class ViewController: UIViewController {
    var queue = OperationQueue()
    var rawImage = UIImage? = nil
    let imageUrl = URL(string: "https://example.com/portrait.jpg")!
    @IBOutlet weak var imageView: UIImageView!

    let downloadOperation = BlockOperation {
        let image = Downloader.downloadImageWithURL(url: imageUrl)
        OperationQueue.main.async {
            self.rawImage = image
        }
    }

    let filterOperation = BlockOperation {
        let filteredImage = ImgProcessor.addGaussianBlur(self.rawImage)
        OperationQueue.main.async {
            self.imageView = filteredImage
        }
    }

    filterOperation.addDependency(downloadOperation)

    [downloadOperation, filterOperation].forEach {
        queue.addOperation($0)
     }
}

So why not opt for a higher level abstraction and avoid using GCD entirely? While GCD is ideal for inline asynchronous processing, Operation provides a more comprehensive, object-oriented model of computation for encapsulating all of the data around structured, repeatable tasks in an application. Developers should use the highest level of abstraction possible for any given problem, and for scheduling consistent, repeated work, that abstraction is Operation. Other times, it makes more sense to sprinkle in some GCD for one-off tasks or closures that we want to fire. We can mix both OperationQueue and GCD to get the best of both worlds.


The Cost of Concurrency

DispatchQueue and friends are meant to make it easier for the application developer to execute code concurrently. However, these technologies do not guarantee improvements to the efficiency or responsiveness in an application. It is up to you to use queues in a manner that is both effective and does not impose an undue burden on other resources. For example, it's totally viable to create 10,000 tasks and submit them to a queue, but doing so would allocate a nontrivial amount of memory and introduce a lot of overhead for the allocation and deallocation of operation blocks. This is the opposite of what you want! It's best to profile your app thoroughly to ensure that concurrency is enhancing your app's performance and not degrading it.

We've talked about how concurrency comes at a cost in terms of complexity and allocation of system resources, but introducing concurrency also brings a host of other risks like:

  • Deadlock: A situation where a thread locks a critical portion of the code and can halt the application's run loop entirely. In the context of GCD, you should be very careful when using the dispatchQueue.sync { } calls as you could easily get yourself in situations where two synchronous operations can get stuck waiting for each other.
  • Priority Inversion: A condition where a lower priority task blocks a high priority task from executing, which effectively inverts their priorities. GCD allows for different levels of priority on its background queues, so this is quite easily a possibility.
  • Producer-Consumer Problem: A race condition where one thread is creating a data resource while another thread is accessing it. This is a synchronization problem, and can be solved using locks, semaphores, serial queues, or a barrier dispatch if you're using concurrent queues in GCD.
  • ...and many other sorts of locking and data-race conditions that are hard to debug! Thread safety is of the utmost concern when dealing with concurrency.

Parting Thoughts + Further Reading

If you've made it this far, I applaud you. Hopefully this article gives you a lay of the land when it comes to multithreading techniques on iOS, and how you can use some of them in your app. We didn't get to cover many of the lower-level constructs like locks, mutexes and how they help us achieve synchronization, nor did we get to dive into concrete examples of how concurrency can hurt your app. We'll save those for another day, but you can dig into some additional reading and videos if you're eager to dive deeper.




amp

CLI Equivalents for Common MAMP PRO and Sequel Pro Tasks

Working on website front ends I sometimes use MAMP PRO to manage local hosts and Sequel Pro to manage databases. Living primarily in my text editor, a terminal, and a browser window, moving to these click-heavy dedicated apps can feel clunky. Happily, the tasks I have most frequently turned to those apps for —starting and stopping servers, creating new hosts, and importing, exporting, deleting, and creating databases— can be done from the command line.

I still pull up MAMP PRO if I need to change a host's PHP version or work with its other more specialized settings, or Sequel Pro to quickly inspect a database, but for the most part I can stay on the keyboard and in my terminal. Here's how:

Command Line MAMP PRO

You can start and stop MAMP PRO's servers from the command line. You can even do this when the MAMP PRO desktop app isn't open.

Note: MAMP PRO's menu icon will not change color to reflect the running/stopped status when the status is changed via the command line.

  • Start the MAMP PRO servers:
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd startServers
  • Stop the MAMP PRO servers:
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd stopServers
  • Create a host (replace host_name and root_path):
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd createHost host_name root_path

MAMP PRO-friendly Command Line Sequel Pro

Note: if you don't use MAMP PRO, just replace the /Applications/MAMP/Library/bin/mysql with mysql.

In all of the following commands, replace username with your user name (locally this is likely root) and database_name with your database name. The -p (password) flag with no argument will trigger an interactive password prompt. This is more secure than including your password in the command itself (like -pYourPasswordHere). Of course, if you're using the default password root is not particular secure to begin with so you might just do -pYourPasswordHere.

Setting the -h (host) flag to localhost or 127.0.0.1 tells mysql to look at what's on localhost. With the MAMP PRO servers running, that will be the MAMP PRO databases.

# with the MAMP PRO servers running, these are equivalent:
# /Applications/MAMP/Library/bin/mysql -h 127.0.0.1 other_options
# and
# /Applications/MAMP/Library/bin/mysql -h localhost other_options

/Applications/MAMP/Library/bin/mysql mysql_options # enter. opens an interactive mysql session
mysql> some command; # don't forget the semicolon
mysql> exit;
  • Create a local database
# with the MAMP PRO servers running
# replace `username` with your username, which is `root` by default
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p -e "create database database_name"

or

# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p # and then enter
mysql> create database database_name; # don't forget the semicolon
mysql> exit

    MAMP PRO's databases are stored in /Library/Application Support/appsolute/MAMP PRO/db so to confirm that it worked you can

ls /Library/Application Support/appsolute/MAMP PRO/db
# will output the available mysql versions. For example I have
mysql56_2018-11-05_16-25-13     mysql57

# If it isn't clear which one you're after, open the main MAMP PRO and click
# on the MySQL "servers and services" item. In my case it shows "Version: 5.7.26"

# Now look in the relevant MySQL directory
ls /Library/Application Support/appsolute/MAMP PRO/db/mysql57
# the newly created database should be in the list
  • Delete a local database
# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p -e "drop database database_name"
  • Export a dump of a local database. Note that this uses mysqldump not mysql.
# to export an uncompressed file
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysqldump -h localhost -u username -p database_name > the/output/path.sql

# to export a compressed file
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysqldump -h localhost -u username -p database_name | gzip -c > the/output/path.gz

  • Export a local dump from an external database over SSH. Note that this uses mysqldump not mysql.

# replace `ssh-user`, `ssh_host`, `mysql_user`, `database_name`, and the output path

# to end up with an uncompressed file
ssh ssh_user@ssh_host "mysqldump -u mysql_user -p database_name | gzip -c" | gunzip > the/output/path.sql

# to end up with a compressed file
ssh ssh_user@ssh_host "mysqldump -u mysql_user -p database_name | gzip -c" > the/output/path.gz
  • Import a local database dump into a local database
# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p database_name < the/dump/path.sql
  • Import a local database dump into a remote database over SSH. Use care with this one. But if you are doing it with Sequel Pro —maybe you are copying a Craft site's database from a production server to a QA server— you might as well be able to do it on the command line.
ssh ssh_user@ssh_host "mysql -u username -p remote_database_name" < the/local/dump/path.sql


For me, using the command line instead of the MAMP PRO and Sequel Pro GUI means less switching between keyboard and mouse, less opening up GUI features that aren't typically visible on my screen, and generally better DX. Give it a try! And while MAMP Pro's CLI is limited to the essentials, command line mysql of course knows no limits. If there's something else you use Sequel Pro for, you may be able to come up with a mysql CLI equivalent you like even better.



  • Code
  • Front-end Engineering
  • Back-end Engineering

amp

Book review: Orientation & Identity

Interviews and background stories covered in this book: Orientation & Identity by Erwin K. Bauer.




amp

New Branding & Website Design Launched for Enterprise High School in Clearwater, Florida

We recently completed a full rebrand and website design project for Enterprise High School, a charter school located in Clearwater,...continue reading




amp

Logo Design & Branding for Food Launcher

A startup specializing in food product development and commercialization services, “Food Launcher” is a team of food scientists with over...continue reading




amp

Good Cop & Bad Cop: Laying Down the Law and Keeping People Happy As an Independent Business Owner

Earlier this week I met up for coffee with a client of mine. The two of us originally met when his employeer was my client and after leaving that job he hired me to customize his personal blog and we formed our own client/designer relationship. I was excited when he emailed me last week with the […]




amp

She’s Geeky: My First Unconference & Having Feels about Solidarity Between Women in Tech

This Friday I attended the first day of She’s Geeky here in Seattle. It was my first experience of the Unconference Format and I had no idea what to expect, but ended up having a GREAT TIME. Discussions that I joined in on throughout the day included subjects such as Impostor Syndrome, Diversity Groups, Side- […]




amp

Want to help the USPS and vets? Buy a &#039;Healing PTSD&#039; stamp

Support two entities with the price of one.




amp

Want to help the USPS and vets? Buy a &#039;Healing PTSD&#039; stamp

Support two entities with the price of one.




amp

75+ High Quality Free Fonts: Handwriting, Script & Brush Fonts

Fonts took on a revival in handmade styles this year, from calligraphic, script and handwritten to brush painted and block-printed. Combined with the great visual appeal of hero images and typographic layouts in web design, handwriting fonts are a trend that you can expect to see more of. In this article you’ll find a fresh […]


The post 75+ High Quality Free Fonts: Handwriting, Script & Brush Fonts appeared first on Web Designer Wall.




amp

Design Trends in 2016 & What to Expect in 2017

The year ahead should be a really exciting one for design, with the introduction of wider support for SVG and a host of new things we can do with CSS as CSS4 gains broader acceptance. In taking a look back at what made a big splash this year, I hope you will be inspired to […]


The post Design Trends in 2016 & What to Expect in 2017 appeared first on Web Designer Wall.




amp

30 Truly Interactive Websites Built With CSS & JavaScript

All websites are somewhat interactive…we click on links or scroll a page, but truly interactive websites take us on a user-driven adventure or draws us in through motion and sound while giving us the power of choice. Interaction can be as simple as a series of clicks that navigate us through a story or landscape, […]


The post 30 Truly Interactive Websites Built With CSS & JavaScript appeared first on Web Designer Wall.




amp

Tutorial: Duo Layout With CSS3 Animations & Transitions (Pt. 2)

Last week I demonstrated how to build a split-screen website layout using CSS flexbox and viewport units that offers an alternative way to present a brand’s featured content. Clicking on one side or the other navigates further into the site without a page load, using CSS transitions and 3d transforms. This week, I’ll show you […]


The post Tutorial: Duo Layout With CSS3 Animations & Transitions (Pt. 2) appeared first on Web Designer Wall.




amp

Easy CSS Animation With Transition & Transforms

Recently, I walked you through how to create a simple landing page that used a couple different CSS animation techniques. “Animation” is a loose term, in web design usually referring to anything that involves movement. CSS transitions are one tool we are given to manipulate elements on state changes or mouse events, and when combines […]


The post Easy CSS Animation With Transition & Transforms appeared first on Web Designer Wall.




amp

Best Email Marketing Tips to Increase Engagement & Subscribers

Email is your post powerful marketing channel when used well. Your visitor’s inbox is a perfect opportunity for you to capture attention, communicate important updates and invite readers back to your site for increased visibility. The stats on email marketing effectiveness say it all – top marketing specialists and service providers tell us that email […]


The post Best Email Marketing Tips to Increase Engagement & Subscribers appeared first on Web Designer Wall.




amp

Common WordPress Errors & How to Fix Them

WordPress is an amazingly stable platform thanks to the dedication and talent of the hundreds of professionals contributing to it, and the strict code standards they follow. Even so, the huge variety of themes, plugins and server environments out there make it difficult to guarantee nothing will ever go wrong. This guide will help you […]


The post Common WordPress Errors & How to Fix Them appeared first on Web Designer Wall.




amp

Upper Yosemite Falls & Half Dome Moonbow

This past week was the optimal time to photograph moonbows in Yosemite Valley. I revisited photographing the moonbow at Upper Yosemite Falls as I had last year, but this time there was considerable more water and as a result the moonbow (rainbow by moonlight) was more easily seen. It was considerably larger, more vivid in color and wider arching. Conditions were great and at times a little too good as the 3 cameras I set up were completely drenched. If you’d like to read about what it took to get this photo be sure to check out my last blog post, Upper Yosemite Falls Moonbow – Getting The Shot, as it goes into a lot of detail about the hike and the challenges I faced.  If you’re curious about gear and settings this was taken with a Canon 5D Mark IV and Canon 11-24mm f/4 lens. Settings were ISO 640, 15 seconds at f/4.





amp

Top 15 Digital Scrapbooking Downloads (Free & Paid)

Scrapbooking can be a fun way to capture important moments in life and with our list of the Top 15 Scrapbooking Resources, you can start right away!




amp

How to Master the Elevator Pitch & Leave a Great First Impression

Want to master the elevator pitch and leave a great first impression? Use this easy formula to help communicate what you do in a concise pitch!




amp

Top 20 Photoshop Actions (Free & Premium)

Photoshop is an amazing program and with our list of the 20 best free & premium Photoshop Actions, you can start creating incredible work immediately.




amp

The Strategic Pyramid – Brand Purpose, Mission, Vision & Values

Do you know the difference between a mission and a vision? Or the difference between a purpose and a goal? Don’t worry, you’re not the only one. Let's clarify!




amp

Web Design & CRO – A Checklist for Designers

Designing is often as much as a science as it is an art. Using specific knowledge of human psychology & online behaviour, the science of creating effective websites that are optimized for business...




amp

Loosening the Caregiver&#039;s Grip

It happens slowly, like that metaphorical frog you’ve heard about. Possessiveness and controlling behavior in TBI caregivers is something that creeps up on you, and I suspect it is common — not because people are trying to be annoying, but because they care so much and want to see that their loved one is treated well in every respect.




amp

Never Stop Asking &#039;What If?&#039;

We imagine the what-ifs as a worst case scenario, our worst nightmare happening to us, our life falling apart. But here’s another way of looking at it.




amp

Concurrency & Multithreading in iOS

Concurrency is the notion of multiple things happening at the same time. This is generally achieved either via time-slicing, or truly in parallel if multiple CPU cores are available to the host operating system. We've all experienced a lack of concurrency, most likely in the form of an app freezing up when running a heavy task. UI freezes don't necessarily occur due to the absence of concurrency — they could just be symptoms of buggy software — but software that doesn't take advantage of all the computational power at its disposal is going to create these freezes whenever it needs to do something resource-intensive. If you've profiled an app hanging in this way, you'll probably see a report that looks like this:

Anything related to file I/O, data processing, or networking usually warrants a background task (unless you have a very compelling excuse to halt the entire program). There aren't many reasons that these tasks should block your user from interacting with the rest of your application. Consider how much better the user experience of your app could be if instead, the profiler reported something like this:

Analyzing an image, processing a document or a piece of audio, or writing a sizeable chunk of data to disk are examples of tasks that could benefit greatly from being delegated to background threads. Let's dig into how we can enforce such behavior into our iOS applications.


A Brief History

In the olden days, the maximum amount of work per CPU cycle that a computer could perform was determined by the clock speed. As processor designs became more compact, heat and physical constraints started becoming limiting factors for higher clock speeds. Consequentially, chip manufacturers started adding additional processor cores on each chip in order to increase total performance. By increasing the number of cores, a single chip could execute more CPU instructions per cycle without increasing its speed, size, or thermal output. There's just one problem...

How can we take advantage of these extra cores? Multithreading.

Multithreading is an implementation handled by the host operating system to allow the creation and usage of n amount of threads. Its main purpose is to provide simultaneous execution of two or more parts of a program to utilize all available CPU time. Multithreading is a powerful technique to have in a programmer's toolbelt, but it comes with its own set of responsibilities. A common misconception is that multithreading requires a multi-core processor, but this isn't the case — single-core CPUs are perfectly capable of working on many threads, but we'll take a look in a bit as to why threading is a problem in the first place. Before we dive in, let's look at the nuances of what concurrency and parallelism mean using a simple diagram:

In the first situation presented above, we observe that tasks can run concurrently, but not in parallel. This is similar to having multiple conversations in a chatroom, and interleaving (context-switching) between them, but never truly conversing with two people at the same time. This is what we call concurrency. It is the illusion of multiple things happening at the same time when in reality, they're switching very quickly. Concurrency is about dealing with lots of things at the same time. Contrast this with the parallelism model, in which both tasks run simultaneously. Both execution models exhibit multithreading, which is the involvement of multiple threads working towards one common goal. Multithreading is a generalized technique for introducing a combination of concurrency and parallelism into your program.


The Burden of Threads

A modern multitasking operating system like iOS has hundreds of programs (or processes) running at any given moment. However, most of these programs are either system daemons or background processes that have very low memory footprint, so what is really needed is a way for individual applications to make use of the extra cores available. An application (process) can have many threads (sub-processes) operating on shared memory. Our goal is to be able to control these threads and use them to our advantage.

Historically, introducing concurrency to an app has required the creation of one or more threads. Threads are low-level constructs that need to be managed manually. A quick skim through Apple's Threaded Programming Guide is all it takes to see how much complexity threaded code adds to a codebase. In addition to building an app, the developer has to:

  • Responsibly create new threads, adjusting that number dynamically as system conditions change
  • Manage them carefully, deallocating them from memory once they have finished executing
  • Leverage synchronization mechanisms like mutexes, locks, and semaphores to orchestrate resource access between threads, adding even more overhead to application code
  • Mitigate risks associated with coding an application that assumes most of the costs associated with creating and maintaining any threads it uses, and not the host OS

This is unfortunate, as it adds enormous levels of complexity and risk without any guarantees of improved performance.


Grand Central Dispatch

iOS takes an asynchronous approach to solving the concurrency problem of managing threads. Asynchronous functions are common in most programming environments, and are often used to initiate tasks that might take a long time, like reading a file from the disk, or downloading a file from the web. When invoked, an asynchronous function executes some work behind the scenes to start a background task, but returns immediately, regardless of how long the original task might takes to actually complete.

A core technology that iOS provides for starting tasks asynchronously is Grand Central Dispatch (or GCD for short). GCD abstracts away thread management code and moves it down to the system level, exposing a light API to define tasks and execute them on an appropriate dispatch queue. GCD takes care of all thread management and scheduling, providing a holistic approach to task management and execution, while also providing better efficiency than traditional threads.

Let's take a look at the main components of GCD:

What've we got here? Let's start from the left:

  • DispatchQueue.main: The main thread, or the UI thread, is backed by a single serial queue. All tasks are executed in succession, so it is guaranteed that the order of execution is preserved. It is crucial that you ensure all UI updates are designated to this queue, and that you never run any blocking tasks on it. We want to ensure that the app's run loop (called CFRunLoop) is never blocked in order to maintain the highest framerate. Subsequently, the main queue has the highest priority, and any tasks pushed onto this queue will get executed immediately.
  • DispatchQueue.global: A set of global concurrent queues, each of which manage their own pool of threads. Depending on the priority of your task, you can specify which specific queue to execute your task on, although you should resort to using default most of the time. Because tasks on these queues are executed concurrently, it doesn't guarantee preservation of the order in which tasks were queued.

Notice how we're not dealing with individual threads anymore? We're dealing with queues which manage a pool of threads internally, and you will shortly see why queues are a much more sustainable approach to multhreading.

Serial Queues: The Main Thread

As an exercise, let's look at a snippet of code below, which gets fired when the user presses a button in the app. The expensive compute function can be anything. Let's pretend it is post-processing an image stored on the device.

import UIKit

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        compute()
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

At first glance, this may look harmless, but if you run this inside of a real app, the UI will freeze completely until the loop is terminated, which will take... a while. We can prove it by profiling this task in Instruments. You can fire up the Time Profiler module of Instruments by going to Xcode > Open Developer Tool > Instruments in Xcode's menu options. Let's look at the Threads module of the profiler and see where the CPU usage is highest.

We can see that the Main Thread is clearly at 100% capacity for almost 5 seconds. That's a non-trivial amount of time to block the UI. Looking at the call tree below the chart, we can see that the Main Thread is at 99.9% capacity for 4.43 seconds! Given that a serial queue works in a FIFO manner, tasks will always complete in the order in which they were inserted. Clearly the compute() method is the culprit here. Can you imagine clicking a button just to have the UI freeze up on you for that long?

Background Threads

How can we make this better? DispatchQueue.global() to the rescue! This is where background threads come in. Referring to the GCD architecture diagram above, we can see that anything that is not the Main Thread is a background thread in iOS. They can run alongside the Main Thread, leaving it fully unoccupied and ready to handle other UI events like scrolling, responding to user events, animating etc. Let's make a small change to our button click handler above:

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
            self.compute()
        }
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Unless specified, a snippet of code will usually default to execute on the Main Queue, so in order to force it to execute on a different thread, we'll wrap our compute call inside of an asynchronous closure that gets submitted to the DispatchQueue.global queue. Keep in mind that we aren't really managing threads here. We're submitting tasks (in the form of closures or blocks) to the desired queue with the assumption that it is guaranteed to execute at some point in time. The queue decides which thread to allocate the task to, and it does all the hard work of assessing system requirements and managing the actual threads. This is the magic of Grand Central Dispatch. As the old adage goes, you can't improve what you can't measure. So we measured our truly terrible button click handler, and now that we've improved it, we'll measure it once again to get some concrete data with regards to performance.

Looking at the profiler again, it's quite clear to us that this is a huge improvement. The task takes an identical amount of time, but this time, it's happening in the background without locking up the UI. Even though our app is doing the same amount of work, the perceived performance is much better because the user will be free to do other things while the app is processing.

You may have noticed that we accessed a global queue of .userInitiated priority. This is an attribute we can use to give our tasks a sense of urgency. If we run the same task on a global queue of and pass it a qos attribute of background , iOS will think it's a utility task, and thus allocate fewer resources to execute it. So, while we don't have control over when our tasks get executed, we do have control over their priority.

A Note on Main Thread vs. Main Queue

You might be wondering why the Profiler shows "Main Thread" and why we're referring to it as the "Main Queue". If you refer back to the GCD architecture we described above, the Main Queue is solely responsible for managing the Main Thread. The Dispatch Queues section in the Concurrency Programming Guide says that "the main dispatch queue is a globally available serial queue that executes tasks on the application’s main thread. Because it runs on your application’s main thread, the main queue is often used as a key synchronization point for an application."

The terms "execute on the Main Thread" and "execute on the Main Queue" can be used interchangeably.


Concurrent Queues

So far, our tasks have been executed exclusively in a serial manner. DispatchQueue.main is by default a serial queue, and DispatchQueue.global gives you four concurrent dispatch queues depending on the priority parameter you pass in.

Let's say we want to take five images, and have our app process them all in parallel on background threads. How would we go about doing that? We can spin up a custom concurrent queue with an identifier of our choosing, and allocate those tasks there. All that's required is the .concurrent attribute during the construction of the queue.

class ViewController: UIViewController {
    let queue = DispatchQueue(label: "com.app.concurrentQueue", attributes: .concurrent)
    let images: [UIImage] = [UIImage].init(repeating: UIImage(), count: 5)

    @IBAction func handleTap(_ sender: Any) {
        for img in images {
            queue.async { [unowned self] in
                self.compute(img)
            }
        }
    }

    private func compute(_ img: UIImage) -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Running that through the profiler, we can see that the app is now spinning up 5 discrete threads to parallelize a for-loop.

Parallelization of N Tasks

So far, we've looked at pushing computationally expensive task(s) onto background threads without clogging up the UI thread. But what about executing parallel tasks with some restrictions? How can Spotify download multiple songs in parallel, while limiting the maximum number up to 3? We can go about this in a few ways, but this is a good time to explore another important construct in multithreaded programming: semaphores.

Semaphores are signaling mechanisms. They are commonly used to control access to a shared resource. Imagine a scenario where a thread can lock access to a certain section of the code while it executes it, and unlocks after it's done to let other threads execute the said section of the code. You would see this type of behavior in database writes and reads, for example. What if you want only one thread writing to a database and preventing any reads during that time? This is a common concern in thread-safety called Readers-writer lock. Semaphores can be used to control concurrency in our app by allowing us to lock n number of threads.

let kMaxConcurrent = 3 // Or 1 if you want strictly ordered downloads!
let semaphore = DispatchSemaphore(value: kMaxConcurrent)
let downloadQueue = DispatchQueue(label: "com.app.downloadQueue", attributes: .concurrent)

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        for i in 0..<15 {
            downloadQueue.async { [unowned self] in
                // Lock shared resource access
                semaphore.wait()

                // Expensive task
                self.download(i + 1)

                // Update the UI on the main thread, always!
                DispatchQueue.main.async {
                    tableView.reloadData()

                    // Release the lock
                    semaphore.signal()
                }
            }
        }
    }

    func download(_ songId: Int) -> Void {
        var counter = 0

        // Simulate semi-random download times.
        for _ in 0..<Int.random(in: 999999...10000000) {
            counter += songId
        }
    }
}

Notice how we've effectively restricted our download system to limit itself to k number of downloads. The moment one download finishes (or thread is done executing), it decrements the semaphore, allowing the managing queue to spawn another thread and start downloading another song. You can apply a similar pattern to database transactions when dealing with concurrent reads and writes.

Semaphores usually aren't necessary for code like the one in our example, but they become more powerful when you need to enforce synchronous behavior whille consuming an asynchronous API. The above could would work just as well with a custom NSOperationQueue with a maxConcurrentOperationCount, but it's a worthwhile tangent regardless.


Finer Control with OperationQueue

GCD is great when you want to dispatch one-off tasks or closures into a queue in a 'set-it-and-forget-it' fashion, and it provides a very lightweight way of doing so. But what if we want to create a repeatable, structured, long-running task that produces associated state or data? And what if we want to model this chain of operations such that they can be cancelled, suspended and tracked, while still working with a closure-friendly API? Imagine an operation like this:

This would be quite cumbersome to achieve with GCD. We want a more modular way of defining a group of tasks while maintaining readability and also exposing a greater amount of control. In this case, we can use Operation objects and queue them onto an OperationQueue, which is a high-level wrapper around DispatchQueue. Let's look at some of the benefits of using these abstractions and what they offer in comparison to the lower-level GCI API:

  • You may want to create dependencies between tasks, and while you could do this via GCD, you're better off defining them concretely as Operation objects, or units of work, and pushing them onto your own queue. This would allow for maximum reusability since you may use the same pattern elsewhere in an application.
  • The Operation and OperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing). This is another important benefit if you want to monitor the state of an operation or operation queue.
  • Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. The Operation API is more flexible in that respect, giving the developer control over the operation's life cycle.
  • OperationQueue allows you to specify the maximum number of queued operations that can run simultaneously, giving you a finer degree of control over the concurrency aspects.

The usage of Operation and OperationQueue could fill an entire blog post, but let's look at a quick example of what modeling dependencies looks like. (GCD can also create dependencies, but you're better off dividing up large tasks into a series of composable sub-tasks.) In order to create a chain of operations that depend on one another, we could do something like this:

class ViewController: UIViewController {
    var queue = OperationQueue()
    var rawImage = UIImage? = nil
    let imageUrl = URL(string: "https://example.com/portrait.jpg")!
    @IBOutlet weak var imageView: UIImageView!

    let downloadOperation = BlockOperation {
        let image = Downloader.downloadImageWithURL(url: imageUrl)
        OperationQueue.main.async {
            self.rawImage = image
        }
    }

    let filterOperation = BlockOperation {
        let filteredImage = ImgProcessor.addGaussianBlur(self.rawImage)
        OperationQueue.main.async {
            self.imageView = filteredImage
        }
    }

    filterOperation.addDependency(downloadOperation)

    [downloadOperation, filterOperation].forEach {
        queue.addOperation($0)
     }
}

So why not opt for a higher level abstraction and avoid using GCD entirely? While GCD is ideal for inline asynchronous processing, Operation provides a more comprehensive, object-oriented model of computation for encapsulating all of the data around structured, repeatable tasks in an application. Developers should use the highest level of abstraction possible for any given problem, and for scheduling consistent, repeated work, that abstraction is Operation. Other times, it makes more sense to sprinkle in some GCD for one-off tasks or closures that we want to fire. We can mix both OperationQueue and GCD to get the best of both worlds.


The Cost of Concurrency

DispatchQueue and friends are meant to make it easier for the application developer to execute code concurrently. However, these technologies do not guarantee improvements to the efficiency or responsiveness in an application. It is up to you to use queues in a manner that is both effective and does not impose an undue burden on other resources. For example, it's totally viable to create 10,000 tasks and submit them to a queue, but doing so would allocate a nontrivial amount of memory and introduce a lot of overhead for the allocation and deallocation of operation blocks. This is the opposite of what you want! It's best to profile your app thoroughly to ensure that concurrency is enhancing your app's performance and not degrading it.

We've talked about how concurrency comes at a cost in terms of complexity and allocation of system resources, but introducing concurrency also brings a host of other risks like:

  • Deadlock: A situation where a thread locks a critical portion of the code and can halt the application's run loop entirely. In the context of GCD, you should be very careful when using the dispatchQueue.sync { } calls as you could easily get yourself in situations where two synchronous operations can get stuck waiting for each other.
  • Priority Inversion: A condition where a lower priority task blocks a high priority task from executing, which effectively inverts their priorities. GCD allows for different levels of priority on its background queues, so this is quite easily a possibility.
  • Producer-Consumer Problem: A race condition where one thread is creating a data resource while another thread is accessing it. This is a synchronization problem, and can be solved using locks, semaphores, serial queues, or a barrier dispatch if you're using concurrent queues in GCD.
  • ...and many other sorts of locking and data-race conditions that are hard to debug! Thread safety is of the utmost concern when dealing with concurrency.

Parting Thoughts + Further Reading

If you've made it this far, I applaud you. Hopefully this article gives you a lay of the land when it comes to multithreading techniques on iOS, and how you can use some of them in your app. We didn't get to cover many of the lower-level constructs like locks, mutexes and how they help us achieve synchronization, nor did we get to dive into concrete examples of how concurrency can hurt your app. We'll save those for another day, but you can dig into some additional reading and videos if you're eager to dive deeper.




amp

CLI Equivalents for Common MAMP PRO and Sequel Pro Tasks

Working on website front ends I sometimes use MAMP PRO to manage local hosts and Sequel Pro to manage databases. Living primarily in my text editor, a terminal, and a browser window, moving to these click-heavy dedicated apps can feel clunky. Happily, the tasks I have most frequently turned to those apps for —starting and stopping servers, creating new hosts, and importing, exporting, deleting, and creating databases— can be done from the command line.

I still pull up MAMP PRO if I need to change a host's PHP version or work with its other more specialized settings, or Sequel Pro to quickly inspect a database, but for the most part I can stay on the keyboard and in my terminal. Here's how:

Command Line MAMP PRO

You can start and stop MAMP PRO's servers from the command line. You can even do this when the MAMP PRO desktop app isn't open.

Note: MAMP PRO's menu icon will not change color to reflect the running/stopped status when the status is changed via the command line.

  • Start the MAMP PRO servers:
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd startServers
  • Stop the MAMP PRO servers:
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd stopServers
  • Create a host (replace host_name and root_path):
/Applications/MAMP PRO.app/Contents/MacOS/MAMP PRO cmd createHost host_name root_path

MAMP PRO-friendly Command Line Sequel Pro

Note: if you don't use MAMP PRO, just replace the /Applications/MAMP/Library/bin/mysql with mysql.

In all of the following commands, replace username with your user name (locally this is likely root) and database_name with your database name. The -p (password) flag with no argument will trigger an interactive password prompt. This is more secure than including your password in the command itself (like -pYourPasswordHere). Of course, if you're using the default password root is not particular secure to begin with so you might just do -pYourPasswordHere.

Setting the -h (host) flag to localhost or 127.0.0.1 tells mysql to look at what's on localhost. With the MAMP PRO servers running, that will be the MAMP PRO databases.

# with the MAMP PRO servers running, these are equivalent:
# /Applications/MAMP/Library/bin/mysql -h 127.0.0.1 other_options
# and
# /Applications/MAMP/Library/bin/mysql -h localhost other_options

/Applications/MAMP/Library/bin/mysql mysql_options # enter. opens an interactive mysql session
mysql> some command; # don't forget the semicolon
mysql> exit;
  • Create a local database
# with the MAMP PRO servers running
# replace `username` with your username, which is `root` by default
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p -e "create database database_name"

or

# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p # and then enter
mysql> create database database_name; # don't forget the semicolon
mysql> exit

    MAMP PRO's databases are stored in /Library/Application Support/appsolute/MAMP PRO/db so to confirm that it worked you can

ls /Library/Application Support/appsolute/MAMP PRO/db
# will output the available mysql versions. For example I have
mysql56_2018-11-05_16-25-13     mysql57

# If it isn't clear which one you're after, open the main MAMP PRO and click
# on the MySQL "servers and services" item. In my case it shows "Version: 5.7.26"

# Now look in the relevant MySQL directory
ls /Library/Application Support/appsolute/MAMP PRO/db/mysql57
# the newly created database should be in the list
  • Delete a local database
# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p -e "drop database database_name"
  • Export a dump of a local database. Note that this uses mysqldump not mysql.
# to export an uncompressed file
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysqldump -h localhost -u username -p database_name > the/output/path.sql

# to export a compressed file
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysqldump -h localhost -u username -p database_name | gzip -c > the/output/path.gz

  • Export a local dump from an external database over SSH. Note that this uses mysqldump not mysql.

# replace `ssh-user`, `ssh_host`, `mysql_user`, `database_name`, and the output path

# to end up with an uncompressed file
ssh ssh_user@ssh_host "mysqldump -u mysql_user -p database_name | gzip -c" | gunzip > the/output/path.sql

# to end up with a compressed file
ssh ssh_user@ssh_host "mysqldump -u mysql_user -p database_name | gzip -c" > the/output/path.gz
  • Import a local database dump into a local database
# with the MAMP PRO servers running
# replace `username` (`root` by default) and `database_name`
/Applications/MAMP/Library/bin/mysql -h localhost -u username -p database_name < the/dump/path.sql
  • Import a local database dump into a remote database over SSH. Use care with this one. But if you are doing it with Sequel Pro —maybe you are copying a Craft site's database from a production server to a QA server— you might as well be able to do it on the command line.
ssh ssh_user@ssh_host "mysql -u username -p remote_database_name" < the/local/dump/path.sql


For me, using the command line instead of the MAMP PRO and Sequel Pro GUI means less switching between keyboard and mouse, less opening up GUI features that aren't typically visible on my screen, and generally better DX. Give it a try! And while MAMP Pro's CLI is limited to the essentials, command line mysql of course knows no limits. If there's something else you use Sequel Pro for, you may be able to come up with a mysql CLI equivalent you like even better.



  • Code
  • Front-end Engineering
  • Back-end Engineering