इस एपिसोड के बारे में
Jeroen shares his real-world iOS development journey working on a legacy app at Dawn Technologies. He details his systematic approach to modernizing an 8-year-old codebase that serves as a critical tool for companies.
• Breaking down a monolithic App Delegate into dedicated managers with single responsibilities
• Leveraging the existing feature flag system to safely deploy new implementations
• Refactoring the walkie-talkie functionality with real-time audio streaming over WebSockets
• Completely rewriting the chat system to use a modern service-based architecture
• Overhauling the location tracking system to use iOS 17's new async location tracking APIs
• Implementing WiFi settings fixes for iOS 16 compatibility using modern APIs
• Maintaining a cleanup branch to remove deprecated APIs and fix compiler warnings
Check out Do iOS, the iOS development conference I'm organizing later this year. Visit do-ios.com for more information and tickets - link in the show notes.
Join me in Amsterdam for Do iOS 2025, tickets and details available now.
Lead Software Developer
Learn best practices for being a great lead software developer.
Learn best practices for being a great lead software developer.
Disclaimer: This post contains affiliate links. If you make a purchase, I may receive a commission at no extra cost to you.
Do iOS: https://do-ios.com
Rate me on Apple Podcasts.
Send feedback on SpeakPipe
Or contact me:
- Mastodon: https://hachyderm.io/@appforce1
- X: https://x.com/appforce1
- BlueSky: https://bsky.app/profile/appforce1.net
- LinkedIN: https://www.linkedin.com/in/leenarts/
Support my podcast with a monthly subscription, it really helps.
My book: Being a Lead Software Developer
नोद्स दिखाएं 🔗
अनुलिपि 🔗
00:01:13.010 --> 00:01:21.250
Welcome to the second episode of the App Force One Worklock, where I share my real world iOS development journey as I work on my day-to-day iOS projects.
00:01:21.570 --> 00:01:25.890
Hey there, iOS developers, welcome to the second worklock episode of App Force One.
00:01:25.969 --> 00:01:30.370
I'm Juden Leinhardt and I'm excited to share with you what I've been working on over the past few weeks.
00:01:30.530 --> 00:01:35.810
As I mentioned in the intro episode, I'm now back to building iOS apps full time at Dawn Technologies.
00:01:36.130 --> 00:01:41.010
Working on my day-to-day projects, which include critical image response apps for companies.
00:01:41.250 --> 00:01:45.730
Think of it like a digital first aid kit that companies use when something goes wrong.
00:01:45.890 --> 00:01:51.570
This isn't just any app, it's one of that could literally save lives, which makes the work feel incredibly meaningful.
00:01:51.730 --> 00:01:56.450
But here's the thing this code base is like a classic car that's been sitting in a garage for years.
00:01:56.530 --> 00:02:00.290
It's over eight years old, which in iOS development terms is ancient.
00:02:00.530 --> 00:02:05.250
It was built before Swiss UI existed, so it's full on all UI kit.
00:02:05.570 --> 00:02:12.050
It's using patterns and practices that were cutting edge in 2016 but are now considered outdated.
00:02:12.129 --> 00:02:20.370
We're talking about manual view controller management, old networking patterns and architectural decisions that made sense at the time but are now technical debt.
00:02:20.449 --> 00:02:21.090
And I love it.
00:02:21.250 --> 00:02:26.530
I absolutely love it because this is exactly the kind of challenge that gets me excited about iOS development.
00:02:26.770 --> 00:02:30.129
It's like being handed a classic car that needs a complete restoration.
00:02:30.210 --> 00:02:34.689
Sure, it's going to be a lot of work, but the end result is going to be amazing.
00:02:35.009 --> 00:02:36.290
So my weekend review.
00:02:36.370 --> 00:02:41.970
So what I actually have been working on since September 25th, let me break it down into major themes.
00:02:42.129 --> 00:02:55.330
So those are the app delicate cleanup and modern architecture, working with the existing feature flag system, walkie-talkie and PTT integration, chat system refactoring, location tracking modernization.
00:02:55.569 --> 00:02:57.170
Okay, let's get started.
00:02:57.410 --> 00:02:58.290
First one.
00:02:58.610 --> 00:03:01.170
App Delicate Cleanup and Modern Architecture.
00:03:01.330 --> 00:03:06.370
One of the biggest refactoring efforts I've been leading is breaking down the monolithic app delicate.
00:03:06.530 --> 00:03:07.170
You know how it is.
00:03:07.330 --> 00:03:13.810
Over the years, the app delicate becomes this massive file that handles everything from authentication to notifications to background tasks.
00:03:14.050 --> 00:03:18.050
It's like that one friend who always volunteers to organize everything at a party.
00:03:18.129 --> 00:03:21.090
They end up doing everything and eventually they burn out.
00:03:21.329 --> 00:03:28.530
I've been extracting concerns into dedicated managers like hiring a team of specialists instead of relying on one overworked generalist.
00:03:28.769 --> 00:03:33.250
An app lifecycle manager handles foreground background transitions like a bouncer at a club.
00:03:33.410 --> 00:03:38.530
Background task manager manages background task registration and scheduling, it's more like a project manager.
00:03:38.769 --> 00:03:44.209
Authentication coordinator handles all biometric and authentication logic, it's the security card.
00:03:44.449 --> 00:03:49.970
Crash Reporting Manager manages Sentry app and uses tracking like detective collecting evidence.
00:03:50.209 --> 00:03:56.610
The key insight here is that we've been moving from a single massive class to a collection of focused testable components.
00:03:56.769 --> 00:04:01.410
Each manager has a single responsibility, making the code much cleaner to understand and maintain.
00:04:01.569 --> 00:04:04.689
It's like going from a Swiss Army knife to a proper toolkit.
00:04:04.930 --> 00:04:09.569
So the second thing I've been dealing with is working with the existing feature flag system.
00:04:09.730 --> 00:04:16.370
The app already had a massive feature flag system in place, and I've been leveraging it extensively for my refactoring work.
00:04:16.530 --> 00:04:19.090
Think of it like having a dimmer switch for your code.
00:04:19.170 --> 00:04:22.370
You can turn features up or down without rewiring the entire house.
00:04:22.610 --> 00:04:27.250
This is crucial when you're dealing with a critical app that you can't afford to have any downtime on.
00:04:27.410 --> 00:04:29.490
It's like having an emergency break on the train.
00:04:29.569 --> 00:04:32.850
You hope you never need it, but when you do, you'll be really glad it's there.
00:04:33.090 --> 00:04:46.850
The feature flags I've been working on were the following one: Refactor Alert Detail Screen for the new alert detail implementation, a refactor alert statistic screen for the statistics screen rewrite, and a refactor flick buttons for the flick management refactor.
00:04:47.009 --> 00:04:51.889
And then there's the async location tracking for the new iOS 17 and 18 location tracking.
00:04:52.050 --> 00:04:57.970
This allows me to test new implementations alongside the old ones, ensuring I can roll back quickly if something goes wrong.
00:04:58.129 --> 00:05:01.810
It's like having a safety net when you're walking a tightrope, really.
00:05:02.209 --> 00:05:06.370
And the third thing I've been working on is the walkie-talkie and push-to-talk integration.
00:05:06.689 --> 00:05:11.889
One of the most complex features I've been working on is the push-to-talk integration for the walkie-talkie functionality.
00:05:12.050 --> 00:05:16.610
This involves real-time audio streaming over WebSockets, which is incredibly challenging to get right.
00:05:16.689 --> 00:05:25.090
It's like trying to have a conversation through a walkie-talkie while riding a roller coaster, everything is moving, everything is changing, and you need to keep the connection stable.
00:05:25.329 --> 00:05:28.129
Let me tell you about the debugging nightmare I had last week.
00:05:28.370 --> 00:05:33.650
I was getting reports that the walkie-talkie was cutting out mid-conversation, but only on certain devices.
00:05:33.890 --> 00:05:40.930
After hours of debugging, I discovered that the audio engine was setting up multiple times, causing conflicts.
00:05:41.010 --> 00:05:45.010
And it also caused the MP volume fuel to literally move around on the screen because of this.
00:05:45.090 --> 00:05:47.090
That was the issue I talked about earlier.
00:05:47.330 --> 00:05:49.970
It was like having a volume slider that had a mind of its own.
00:05:50.129 --> 00:06:12.770
And the key challenges I've been solving is the audio streaming, encoding and decoding audio in real time, like trying to translate a conversation while it's happening, web socket management, handling connection states, reconnection logic, and retry mechanisms, like having a backup plan for every possible scenario, state management, tracking recording state, connection state, and audio playback, like keeping track of who's talking, who's listening, and what's happening.
00:06:13.010 --> 00:06:21.090
And then of course there's thread safety, ensuring that audio processes happen on the right threads, like making sure that the right people are in the right rooms at the right time.
00:06:21.650 --> 00:06:32.210
I've consolidated the audio engine setup to solve this MP volume view movement issues I had and implemented the retry mechanism that attempts reconnecting up to five times instead of just two.
00:06:32.530 --> 00:06:37.490
The audio buffering system now runs in separate threads to prevent clipping and ensure smooth playback.
00:06:37.810 --> 00:06:41.330
It's like having a backup sound system that kicks in when the main one fails.
00:06:41.650 --> 00:06:44.930
Another thing I've been working on was a chat system refactoring.
00:06:45.090 --> 00:06:49.650
I've been completely rewriting the chat system to use a modern service-based architecture.
00:06:49.810 --> 00:06:54.050
The old system uses a singleton MB chat manager that was tightly coupled to the UI.
00:06:54.129 --> 00:06:57.090
It's like having a chat system that was permanently glued to the screen.
00:06:57.250 --> 00:07:03.410
The new chat service is much more modular and testable, like having a chat system that can be plugged into any device.
00:07:03.569 --> 00:07:26.770
And the key improvements that I've been working on are an async await support, modernizing the matrix SDK integration and better error handling so that proper error types and recovery mechanisms are in place, and thread safety, again thread safety, so to make sure that the matrix SDK that we rely on is used safely across threads and making sure that everyone follows the same traffic rules there.
00:07:27.010 --> 00:07:29.970
And I also wanted to introduce some more separation of concerns.
00:07:30.129 --> 00:07:37.090
The service handles all the matrix logics while the UI focuses on presentations, like having a chef who cooks and a waiter who serves.
00:07:37.170 --> 00:07:41.569
Everybody has their own specialized task and we don't walk in front of each other.
00:07:46.689 --> 00:07:53.170
The location tracking system has been completely overhauled to use iOS 17 and 18's new async location tracking APIs.
00:07:53.250 --> 00:07:57.569
This is a perfect example of how iOS evolves and how you need to adapt your code.
00:07:57.810 --> 00:08:00.290
It's like upgrading from a paper map to GPS.
00:08:00.370 --> 00:08:02.850
The old system worked, but the new one is much better.
00:08:03.090 --> 00:08:20.450
The new system includes geofencing, processing, using the new CL monitor API for better performance, like having a security card who never sleeps, and background task manager management, so background task management, proper background task handling for location updates like having a reliable assistant who always remembers to check in.
00:08:20.770 --> 00:08:32.210
Debouncing, preventing to prevail prevent excessive server calls when driving, because otherwise we get like an update every five meters, and especially if you're at speed, that's a bit much.
00:08:32.450 --> 00:08:37.730
And distance filtering so that we only send location updates when the user has moved significantly.
00:08:38.769 --> 00:08:43.090
So that's just to make sure that we don't uh saturate the server.
00:08:43.490 --> 00:08:48.529
Alright, let's dive into the details a little bit more because this is like a high-level overview.
00:08:49.090 --> 00:08:51.409
Code Deep Dive, the App Delicate Refactor.
00:08:51.569 --> 00:08:55.490
Uh let me show you a specific example of the refactoring work that I've been doing.
00:08:55.569 --> 00:09:00.450
This is the kind of real-world problem that every iOS developer faces when working with legacy codes.
00:09:00.610 --> 00:09:01.649
So the problem here.
00:09:01.889 --> 00:09:05.490
The original app delicate was over 500 lines long and handled everything.
00:09:05.649 --> 00:09:08.929
It was like a Swiss armor knife that had grown into a full toolbox.
00:09:09.090 --> 00:09:17.569
Imagine if your kitchen had one giant appliance that was supposed to be your refrigerator, your stuff, your dishwasher, your microwave, and your coffee make all rolled into one.
00:09:17.889 --> 00:09:19.889
That's what our app delicate had become.
00:09:20.129 --> 00:09:24.289
I remember the first time I opened the file, I was like, nope, what the hell is this?
00:09:24.610 --> 00:09:34.049
It was handling authentication and biometric login, push notification registration, background task management, deep linking, security checks, feature flag refreshing, and then some other things.
00:09:34.289 --> 00:09:37.490
This made it incredibly difficult to test, understand, and maintain.
00:09:37.569 --> 00:09:40.450
It was like trying to fix a car when all the parts were welded together.
00:09:40.529 --> 00:09:42.929
You couldn't work on one thing without affecting everything else.
00:09:43.169 --> 00:09:49.250
Every time I made a change, I was holding my breath, wondering if I might have broken something on the other side of the whole machine.
00:09:49.490 --> 00:09:54.610
So the solution that I came up with was that I broke everything down into focus managers.
00:09:54.769 --> 00:09:59.089
The new app lifecycle manager is much simpler, it just coordinates between the other services.
00:09:59.250 --> 00:10:05.089
When the app comes to the foreground, it refreshes feature flags, syncs device info, and updates the session manager if needed.
00:10:05.250 --> 00:10:08.769
When it becomes active, it posts notifications and runs security checks.
00:10:08.929 --> 00:10:12.529
The key insight is that each manager has a single clear responsibility.
00:10:12.689 --> 00:10:18.689
The app lifecycle manager doesn't know how to handle background tasks, it just knows when to tell the other services to do their job.
00:10:18.929 --> 00:10:25.089
It's like having a conductor who doesn't play any instruments but knows when each section should come in.
00:10:25.490 --> 00:10:28.370
The benefits of this is that first of all we have testability.
00:10:30.529 --> 00:10:36.129
Each manager can be tested in isolation, like having separate test tracks for each car component.
00:10:36.449 --> 00:10:41.809
Maintainability, changes to one concern don't affect others, like having separate rooms in a house.
00:10:42.049 --> 00:10:48.129
Readability, the code is self-documenting, like having clear labels on everything, and there's some more reusability.
00:10:48.289 --> 00:10:52.689
Managers can be used in different contexts, like having modular furniture that works in any room.
00:10:52.849 --> 00:10:59.889
So the challenges that ever was facing was that the biggest challenges was ensuring that the refractor didn't break existing functionality.
00:11:00.049 --> 00:11:02.289
This is where the feature flag system became crucial.
00:11:02.529 --> 00:11:06.289
I could test the new implementation alongside the old one, ensuring a smooth transition.
00:11:06.529 --> 00:11:10.529
It's like having uh renovation in your house while you're still living in it.
00:11:10.689 --> 00:11:14.929
You need to make sure that the electricity and the water still work while you're replacing the plumbing.
00:11:15.490 --> 00:11:21.169
Alright, so let's dive into feature flags a little bit because I've mentioned them a full few times over.
00:11:21.329 --> 00:11:30.049
Um the feature flag system that's already in place in this code base, it's like a tool that becomes essential for modern iOS development, especially when dealing with legacy code.
00:11:30.209 --> 00:11:32.209
Think of it like having a remote control for your code.
00:11:32.289 --> 00:11:35.730
You can turn features on and off without touching the code itself.
00:11:36.049 --> 00:11:39.409
The code base already had a well-designed feature flag system in place.
00:11:39.490 --> 00:11:47.490
It's built around an enum that defines all the different features with names like refactor alert detail screen and async location tracking.
00:11:47.730 --> 00:11:51.250
Each feature has a unique identifier and the default value.
00:11:52.610 --> 00:11:53.809
So, how did I use it?
00:11:53.969 --> 00:11:57.169
In the UI code, I can conditionally use new implementations.
00:11:57.329 --> 00:12:02.049
For example, when someone taps on alert, I check if the new alert detail screen feature is enabled.
00:12:02.129 --> 00:12:05.809
If it is, I create a new view controller with the modern MVM architecture.
00:12:05.969 --> 00:12:08.769
If not, I fall back to the old storyboard-based implementation.
00:12:08.929 --> 00:12:10.689
This pattern is repeated throughout the app.
00:12:10.769 --> 00:12:13.969
Every time I want to use a refacted component, I first check the feature flag.
00:12:14.049 --> 00:12:17.730
It's like having a switch that determines which version of the code gets executed.
00:12:17.969 --> 00:12:19.329
So why does this matter?
00:12:19.730 --> 00:12:29.329
Feature flags allows you to deploy safely, test new code in production without affecting all users, like having a test kitchen in a restaurant, and you can roll back quickly.
00:12:29.409 --> 00:12:33.809
If something goes wrong, I can disable the feature instantly, like having an emergency stop button.
00:12:34.049 --> 00:12:50.529
Also, it allows for A-B testing, so you can compare the old versus the new implementations, like having two different recipes and seeing which of the which of these the customers prefer, and it allows for gradual rollouts, so enabling features for a subset of users first, like having a soft opening before the grant opening.
00:12:50.769 --> 00:12:56.289
This is especially important for critical apps like the ones I'm working on, where downtime could literally cost lives.
00:12:56.449 --> 00:12:58.769
It's like having a backup generator for a hospital.
00:12:58.849 --> 00:13:03.009
You hope you never need it, but when you do, it's the difference between life and death.
00:13:03.250 --> 00:13:06.370
The existing system has been a lifesaver for my refactoring work.
00:13:06.449 --> 00:13:14.849
Instead of having to deploy everything at once and hope for the best, I can gradually migrate users to the new implementation while keeping the old code as a safety net.
00:13:15.169 --> 00:13:18.370
So the lessons that I learned, um, legacy code is a gift.
00:13:18.529 --> 00:13:19.569
That's the first lesson.
00:13:19.730 --> 00:13:23.329
Working with legacy code isn't a burden, it's an opportunity to learn.
00:13:23.490 --> 00:13:28.129
Every piece of technical debt tells a story about how IRS development has evolved.
00:13:28.370 --> 00:13:34.769
The old patterns made sense at the time, and understanding why they were chosen helps me make better decisions today.
00:13:35.009 --> 00:13:42.209
It's like reading a history book, you can see how we got to where we are now, and it helps you understand where you're going to need to be going.
00:13:42.449 --> 00:13:47.169
I've actually started to appreciate the craftsmanship that went into this code, even if it's outdated.
00:13:47.329 --> 00:13:51.089
The developers who built this eight years ago were working with the tools and patterns they had available.
00:13:51.329 --> 00:13:54.610
They made the best decisions they could with the information they had back at the time.
00:13:54.769 --> 00:13:57.969
That's something I try to remember when I refactored their work.
00:13:58.289 --> 00:14:01.569
Refactoring also requires patience, that's the second lesson.
00:14:01.730 --> 00:14:03.250
You can't refactor everything at once.
00:14:03.329 --> 00:14:06.929
The key is to identify the most critical areas and tackle them systematically.
00:14:07.089 --> 00:14:12.370
The app delicate refactor took well over a week, but each step made the code base a little better.
00:14:12.529 --> 00:14:17.969
It's like renovating an old house, you can't tear it all down at once, you have to do it room by room.
00:14:18.129 --> 00:14:20.849
I had to resist the urge to just rewrite everything from scratch.
00:14:21.009 --> 00:14:28.370
That could have been faster in the short term, but it would have been significantly more risky for a critical app like this one.
00:14:28.529 --> 00:14:35.250
Instead, I took the slow and steady approach, making small incremental improvements that I could test and validate at each step.
00:14:35.490 --> 00:14:38.049
So the third lesson: testing is everything.
00:14:38.209 --> 00:14:41.809
When refactoring critical functionality, testing becomes your safety net.
00:14:41.969 --> 00:14:46.529
The feature flex system allows me to test new implementations in production without risking the entire app.
00:14:46.689 --> 00:14:49.409
It's like having a safety harness when you're rock climbing.
00:14:49.490 --> 00:14:53.730
You hope you never need it, but when you do, it's the difference between a minor slip and a major fall.
00:14:54.129 --> 00:14:55.730
I learned this the hard way early on.
00:14:55.809 --> 00:15:01.649
I made a change to the authentication flow without properly testing it, and it broke login for a subset of users.
00:15:01.730 --> 00:15:02.769
That was a wake-up call.
00:15:02.849 --> 00:15:04.449
Now I test everything extensively.
00:15:04.529 --> 00:15:09.969
And I use the feature flag system to gradually roll out changes to a small percentage of users first.
00:15:10.849 --> 00:15:14.610
Then the fourth lesson is modern iOS apps are worth the effort.
00:15:15.009 --> 00:15:19.089
Sorry, I need to say modern iOS APIs are worth the effort.
00:15:19.329 --> 00:15:24.689
The new location tracking API in iOS 17 or 18 is significantly better than the old ones.
00:15:24.849 --> 00:15:31.969
Yes, it requires rewriting existing code, but the performance and reliability improvements are worth it.
00:15:32.209 --> 00:15:34.689
It's like upgrading from a flip phone to a smartphone.
00:15:34.849 --> 00:15:40.209
Sure, you have to learn new ways of doing things, but the capabilities are so much better that it's worth the effort.
00:15:40.370 --> 00:15:43.649
The old location tracking code was a mass of callbacks and delicate methods.
00:15:43.730 --> 00:15:47.649
The new async await APIs are so much cleaner and easier to reason about.
00:15:47.889 --> 00:15:54.049
It took me a while to get used to the new patterns though, but now I can't imagine going back to the old way of doing things.
00:15:54.209 --> 00:15:56.129
Okay, so let's look ahead a little bit.
00:15:56.370 --> 00:15:58.849
So what's coming up in the next two weeks?
00:15:59.250 --> 00:16:05.329
I'm not exactly sure, but I expect it will be something to do with the chat system.
00:16:07.649 --> 00:16:10.370
I'm refactoring it and I'm now 80% done.
00:16:10.449 --> 00:16:18.529
The remaining work involves migrating the remaining UI components to the new chat service and in comprehensive error handling, implementing proper offline support.
00:16:18.610 --> 00:16:21.169
It's like finishing the last few rooms in the house renovation.
00:16:21.329 --> 00:16:24.449
The foundation is solid, but there's some finishing work to do.
00:16:24.610 --> 00:16:29.169
The chat system is one of the most complex parts of the app, so I'm taking my time to get it right.
00:16:29.409 --> 00:16:32.049
I also want to finish the alert detail screen refactor.
00:16:32.129 --> 00:16:34.529
The new alert detail screen is much more complete.
00:16:34.689 --> 00:16:38.849
It also uses a modern MVVM architecture with proper separation of concerns.
00:16:39.009 --> 00:16:41.730
The remaining work is mostly UI polish and testing.
00:16:41.889 --> 00:16:44.209
It's like putting the final coat of paint on a car.
00:16:44.289 --> 00:16:49.569
The engine is running great, but you want to make sure that it definitely looks good.
00:16:49.809 --> 00:16:54.449
This screen is critical because it's where users get detailed information about emergency alerts.
00:16:54.610 --> 00:16:58.449
The old version was clunky and hard to navigate, especially in high stress situations.
00:16:58.689 --> 00:17:01.649
The new version is much more intuitive and responsive.
00:17:02.289 --> 00:17:05.170
I'm also going to continue the location tracking modernization.
00:17:05.490 --> 00:17:11.970
The new location tracking system is working well, but I want to add more sophisticated UFencing logic and improve the background task management.
00:17:12.130 --> 00:17:17.329
It's like having a GPS that works, but now I want to make sure that it's smart enough to avoid traffic jams.
00:17:17.490 --> 00:17:22.769
So location tracking is crucial for this app because it's used to determine who's in the area when an emergency happens.
00:17:23.009 --> 00:17:27.490
The more accurate and reliable it is, the better the emergency response can be.
00:17:27.650 --> 00:17:31.250
And then of course there's my cleanup branch, because I've been doing this on the side.
00:17:31.490 --> 00:17:35.089
I've also been working on a massive cleanup branch that's been running in parallel.
00:17:35.170 --> 00:17:40.210
That's the kind of work that doesn't get much attention but is absolutely crucial for maintaining a healthy code base.
00:17:40.450 --> 00:17:43.650
It's like doing uh spring cleaning, not glamorous but necessary.
00:17:43.809 --> 00:17:45.089
I actually enjoy this kind of work.
00:17:45.170 --> 00:17:48.370
There's something satisfying about removing that code and fixing warnings.
00:17:48.529 --> 00:17:50.049
It's like cleaning up your workspace.
00:17:50.130 --> 00:17:53.410
You feel more productive when everything is organized and tidy.
00:17:53.569 --> 00:18:01.410
This cleanup work includes removing deprecated APIs, getting rid of the old API that we don't longer want to support.
00:18:01.650 --> 00:18:04.450
I've been just fixing warnings because there were like hundreds of warnings.
00:18:04.529 --> 00:18:11.170
So cleaning up compiler warnings and deprecation notices, removing that code, eliminating code that's no longer used anywhere anywhere.
00:18:11.250 --> 00:18:14.849
So there were large chunks of code that were not being called into.
00:18:15.329 --> 00:18:18.049
And I wanted to modernize a few of the patterns that were used.
00:18:18.210 --> 00:18:22.369
So updating old patterns to use modern Swift UI features and Swift features.
00:18:42.849 --> 00:18:46.930
You don't notice it when it's working, but when you but you'll definitely notice when it's not.
00:18:47.250 --> 00:18:52.129
So there was also a bug fix I needed to do, uh Wi-Fi settings related.
00:18:52.369 --> 00:18:55.970
I've been working on this bug fix for the Wi-Fi settings not being configurable.
00:18:56.129 --> 00:19:00.369
Uh so it used to be that this worked, but now with iOS 26 it doesn't.
00:19:00.529 --> 00:19:06.369
So this is a perfect example of how legacy code can have subtle issues that only serves when you're doing other refacting work.
00:19:06.529 --> 00:19:15.009
The Wi-Fi management system was using deprecated APIs and had some threading issues that were preventing users from properly configuring their Wi-Fi networks for presence tracking.
00:19:15.170 --> 00:19:16.049
So here's the story.
00:19:16.129 --> 00:19:19.170
I got a support ticket from a user who couldn't configure their Wi-Fi network.
00:19:19.250 --> 00:19:23.170
They were on iOS 26, and the Wi-Fi setting screen was completely broken.
00:19:23.250 --> 00:19:30.210
At first I thought it was a UI issue, but after digging deeper, I discovered something much more interesting.
00:19:30.289 --> 00:19:35.730
The issue was that the app was still using the old Wi-Fi API that was deprecated since iOS 14.
00:19:35.889 --> 00:19:43.730
Specifically, it was using CN copy current network info from the system configuration framework, which was deprecated in iOS 14.
00:19:43.809 --> 00:19:44.930
And here's the kicker.
00:19:45.089 --> 00:19:57.649
It seems like this API stopped working completely in iOS 26, so users on the latest iOS versions couldn't configure their Wi-Fi networks at all, which is pretty critical for an emerging response app that relies on presence tracking, right?
00:19:57.809 --> 00:20:11.649
So the fix involved completely modernizing the Wi-Fi validation system, moving away from the deprecated C and copy current network info API to the modern NEHotspot Network.fetchCurrent API that's been available since iOS 14.
00:20:12.049 --> 00:20:19.329
This new API uses uh well uses uh completion handling, but I wrapped it in an async await pattern, which is much more reliable.
00:20:19.490 --> 00:20:25.170
I also had to ensure that the UI updates happen on the main thread and fix some race conditions in the validation logic.
00:20:25.409 --> 00:20:33.649
The key change was replacing the old synchronous API call with a new async version and wrapping it in a proper continuation to handle the completion-based API.
00:20:33.889 --> 00:20:40.450
It's a perfect example of how Apple's API evolution requires us to constantly update our codes to code to stay compatible.
00:20:40.849 --> 00:20:42.450
It's like fixing a squeaky door.
00:20:42.529 --> 00:20:53.170
It's not the most exciting work, but it makes a huge difference in the user experience, and it's a great reminder of why keeping up with API deprecations is so important, especially when you're dealing with critical functionality.
00:20:53.409 --> 00:20:57.170
So, and that's a wrap on the second App Force One worklock episode.
00:20:57.329 --> 00:21:02.849
I hope this gives you a real sense of what it's like to work on a complex legacy iOS app in 2025.
00:21:03.089 --> 00:21:13.250
The key takeaways is that uh refactoring legacy code isn't just about making it modern, it's about understanding the business context, the technical the technical constraints and the user impact.
00:21:13.490 --> 00:21:18.849
Every decision I make was has real consequences for people who depend on this app in emergency situations.
00:21:19.009 --> 00:21:25.329
It's like being a surgeon, you can't just focus on the technical aspects, you have to remember that there's a real person on the operating table.
00:21:25.569 --> 00:21:35.170
In the next episode, I'll dive deeper into the walkie-talkie audio streaming most likely, and share some of the debugging challenges I am definitely going to be facing in the next week.
00:21:35.490 --> 00:21:41.649
I'll also talk perhaps about the Matrix SDK integration and how I'm handling real-time management messaging.
00:21:42.049 --> 00:21:45.970
Think of it like a behind-the-scenes look on how the magic happens.
00:21:46.129 --> 00:21:52.049
Before I wrap up, I want to mention that I'm organizing a conference called Do iOS, which is happening later this year.
00:21:52.210 --> 00:21:59.250
It's going to be an amazing event focused on iOS development, which talks uh with talks from some of the best developers in the community.
00:21:59.409 --> 00:22:09.569
If you're interested in learning more about iOS development, networking with other developers, and getting inspired by the latest trends and techniques, definitely check out do iOS.com for more information on the tickets.
00:22:09.649 --> 00:22:11.809
Make sure to check the link in the show notes.
00:22:12.049 --> 00:22:16.930
So, until next time, keep building amazing apps and remember every expert was once a beginner.
00:22:17.089 --> 00:22:21.490
The key is to keep learning, keep building, and keep sharing what you learn with the community.
00:22:21.649 --> 00:22:25.329
Thank you for listening, and I'll see you next week for the next worklock episode.
00:22:25.490 --> 00:22:28.609
I'm really excited to share more of this journey with you.