My name is Megabits and I’m a regular iOS developer. Until one day I bought an Apple Watch.

PomoNow is my tomato-clock application integrated with Todolist, featuring the interaction design of “balancing ritual and functionality”. It not only enables beginners to immediately start using pomodoro Technique, but also has high flexibility, suitable for all levels of Pomodoro technique users. Currently my Mac version and synchronization function are under development. For specific introduction, see: PomoNow 2, which gives you a tomato clock with a sense of ceremony! Matrix selection, Watch version use effect see: Weibo video

This is the first Generation of Apple Watch. As a first-generation product, it perfectly performs the historical mission of getting more and more stuck with time. It took me a while to even open an App, but I managed to finish PomoNow Watch on such an unusable gadget.

PomoNow is a tomato clock. What’s the most important thing for a tomato clock? Can use! Yes, it works, but getting there is hard enough. The typical pomodoro technique goes like this: 25 minutes of work, 5 minutes of rest, four repetitions followed by a 25-minute long rest. The first two were easy, and the pit was there four times. Supporting long breaks on the Watch means automatically starting the next tomato after one tomato has finished, and that’s where the rub comes in. I’m going to go into a little bit more detail about what’s so difficult about this feature and how I think about it. You are also welcome to think along with this article. Then I’ll talk about other issues and solutions THAT I encountered during development, many of them watchOS or Xcode itself. I’ve found some less-than-perfect solutions in practice, but I hope they help you.

How to keep time

When I first started to make the Watch version of PomoNow, I hoped to make the Watch app run independently.

For a small device like Apple Watch, running the App in the background for a long time consumes a lot of power, so once the Watch App enters the background, it will stop running. It can be said that it is very troublesome to directly time on the Watch app. Generally speaking, the idea of making a stopwatch on the Watch is as follows: calculate the end time when the Watch starts, and use a timer to calculate the remaining time once per second and then display it.

That way, you won’t be affected by background freezes. Because the time is calculated in real time according to the target time minus the current time. We can also calculate whether we are in “work time” or “rest time” by dividing the time into chunks.



You’re smart enough to have figured out how to implement continuous automatic timing in a similar way.



Following the pattern shown above, we scan front to back, cell to cell. After the “current time” pointer enters the cell we have scanned, we know whether we are working or resting, and how much time is left.

Push notification Problem

So is the problem solved? Naive! The biggest problem is not with timing, but with push notifications. As mentioned above, the Watch app cannot run all the time in the background, so it must be realized by a notification sent at a regular time if it wants to tell the user that the timing is over. For a single tomato, it is easier to handle, and two notifications are OK. But in the case of automatically starting a new tomato, assuming that the user does not lift his wrist to open the App, countless periodic notifications will be set in the background. You may want to say: a hundred (limited) should be enough, who counts a hundred tomatoes? That may be true, but the solution is simply not elegant.

Is there a way to do this gracefully? I came up with a solution like this, although it seems to be as convoluted as the one above. We know that push notifications can be repeated. Given the initial condition of one long break for every four tomatoes, we might be able to specify the following 8 locations for regularly repeated push notifications at the same time interval (working time x 4 + rest time x 3 + long rest time).



Unfortunately, it’s not going to work. Because the time interval for periodic push notifications must be based on this moment, it is impossible to make each notification pop up at the corresponding time the first time.

Therefore, I decided to give up the function of automatic timing in the first version of PomoNow Watch, and users can only manually start the timing on the Watch. In addition, due to the system limitation of not being able to directly push notifications on the Watch, I also need to wake up the iOS App to remind users of the time. You can’t run this Watch app on its own.

According to the above analysis, the first version of my Watch app uses such a method: it can be timed independently on the Watch, only supporting the completion of a single tomato, and users need to manually start a new tomato after completion.

How hard is it to debug once

One of the first things you encounter after starting production is debugging. The simulator was fine, but real machine debugging was horrible. Since the Watch APP cannot be installed directly from the computer, Xcode needs to first transfer the swift runtime and a series of installation scripts to the mobile phone, and then the mobile phone completes the installation process. After that, Xcode needs to connect with Watch through mobile phone to debug. The former has long waiting times, while the latter has a high probability of failure. Let me talk about the various problems you might encounter during debugging.



The first is connectivity. For example, the Watch is locked before you plug the iPhone into the computer, and then unlock it. Xcode shows that the phone and the Watch have been detected. At this time, if you click “Run”, there will be a certain probability of failure to connect. Although the situation is different, it does happen from time to time. When this happens, I usually unplug the data cable and plug it in again. After Xcode detects the Watch again, there is usually no problem.

In addition, both the mobile phone and the watch must be kept unlocked during debugging. In earlier versions, if the table is not unlocked, debugging will fail directly. In later versions, a message will be displayed to wait for unlocking. It took me quite a bit of time.

Finally, it is not easy to directly remind the connection is not connected, and then there are more pit problems may appear. After a few seconds of clicking run, the Watch shows “running” without going through the installation process. There is no reaction at all. There are two possible ways to do this. One is to display an error. Xcode says it is running, but it is actually preparing the installation script. Another possibility is that Xcode blows up. Sometimes it works if you plug in the data cable, and sometimes you need to return Xcode and restart it.

What if the problem occurs after the installation process? It’s possible that your mind wandered. When the screen goes off for a few minutes, the Apple Watch automatically returns to the face, which is a user-friendly design. So check to see if your app is in the background before blaming Apple.

However, these problems occur only occasionally, or once during the first run, while the following problems occur frequently.

After finally installing the Watch app, it’s time to wait for the connection. You watch the screen go round and round and round and round and round until the end of time, and then your app crashes. This is the connection problem. This kind of problem is generally a metaphysical problem, especially for me this kind of initial users, is not to understand because of their watch comparison card, or where the explosion. At this point, you stop debugging and want to try opening your app manually to see if it works. It didn’t work. It just went round and round and round and round and round and Boom. There are two ways to do this. The first is to force the app to exit when it loads by holding down the switch button until the shutdown screen appears, and then holding down the crown until it returns to the home screen. It can then be tried again, with a low probability of success. The second method is relatively simple and crude, restart the watch. If you have time to wait for it to finish rebooting, it will basically solve the problem. (Deleting the Watch App and re-installing it sometimes works.)



More than 10 minutes have passed since I finally installed the Watch APP after ninety-eight difficulties. I think of my best years and never coming back. So as not to delay the best years of my life, I would play Isaac every time I clicked the debug button, and when I was dead, I would come back and it was almost up and running.

So is there a solution? There are. There is not much difference between the Watch app on the simulator and the real machine. Most of the time, we just want to see the running effect without debugging information. At this point, we just change the running target to iOS app and run it. Because the iOS app will compile and install the Watch App when it is installed, and then you just need to run it manually. This avoids the problem of a bunch of slow debugger connections.

Abandonment of independent operation

When making the first version, I actually put forward many “great ideas” for PomoNow’s experience on The Watch, such as timing synchronization with iPhone and adding tasks on the Watch. But the Apple Watch debugging experience was so bad that I had to give up before I drove myself crazy. What’s more, Apple Watch is not worth my efforts to develop either in terms of quantity or frequency of use. Therefore, after completing the function of tomato, I did not add any new function, and defined it as “experimental” for some users who love to use Watch to try.

On June 1 of this year, a user named Madsights sent me a message on Github asking about not auto-timing and taking long breaks. I didn’t expect anyone to respond to this question, and it got me back on track for a Watch version.

As I mentioned earlier, the first version had independent timing, but push notifications still had to be sent from the phone, making independent timing almost meaningless. Since I need a complete timing logic, why not put all the timing on the phone? So the second version of PomoNow Watch became a display-only extension. When you start the timing on the Watch, the iOS device will wake up to start the timing in the background, which not only solves the problem of incomplete functions, but also directly realizes the timing synchronization between the Watch and iPhone. And it’s very simple.

I finished the new version on June 19. I thought I would just fix a few minor bugs, but then I ran into a new problem.

Localization metaphysics problem

PomoNow currently provides versions in four languages: Simplified Chinese, traditional Chinese, English and Japanese. I encountered considerable metaphysical problems when doing localization, which bothered me for a long time. As we know, localization in Xcode is done mainly by adding translation files for the corresponding language, either manually entering or importing or exporting a standard interchange format.



The problem was discovered after I had finished: The Watch app showed Japanese on all devices in all languages (my main language is English). Some people online said: “The problem is your local cache, you upload to Apple will not have any problems with the version.” This is not always the case. When I was working on the first version, the problem was exactly what he described, and while debugging only showed Chinese on the local emulator and device, it returned to normal once it hit the shelves. By the time I got to version 2, things were different. I finished all the localization as before. Although I saw that English was not displayed in the simulator, I didn’t take it seriously until a user told me via email.

On July 19, a user named Clifford D’Souza emailed me back, pointing out that PomoNow was displaying a bunch of unreadable Japanese on his Watch. ????? Didn’t I take care of everything? To be honest, I can understand if a Chinese user displays English, but the localization doesn’t work, but what’s going on in Japanese? I’m totally clued in. I’ve been through the whole project and I haven’t found a single thing I did wrong.

Finally I was really tired, almost as the last straw deleted all the language files from scratch. And then… Will solve the problem? WTF? Well, it worked anyway, so I packed up the new version and uploaded it as soon as I could. It worked out pretty well.

A few quiet days passed, and after I had released a few more releases, the problem resurfaced. This time it was called back during the review phase. Apple’s censors asked me, “Please explain why your device is showing Japanese on all languages.” Explain? This is your Bug. Okay, why do I have to explain this? How can I explain that? I had to turn the project over again. It didn’t help. Delete the language file redo, there is no use. At this moment, I want to give up. If I have to, I will not make the Watch app.

After a demoralizing afternoon, a possible solution hit me the next morning.

In general, with the exception of storyboards, we do not need to provide an untranslated language file because the untranslated string is already contained in the statement that calls the string. A typical statement is as follows :(this “Time to work! The original.)

content.title = NSLocalizedString("Time to work!", comment: "Time to work!")
Copy the code

After analyzing the previous problem, I found that this error does not affect the translation result of the Storyboard. What does this mean? We said that the Storyboard contains an untranslated language file. Is the absence of this file causing these strings to display abnormally? I’ve tried adding untranslated language files in previous versions, but it didn’t work then. But we’re at this point, so let’s try.

So I added an empty Strings file in English, and you can already guess what happened.



I still can’t figure out what’s wrong with it. Before pushing updates to this fixed version, I asked Junyi Lou to test out the previous version. Surprisingly, localisation on his Beta version of the Apple Watch worked fine, and I’m afraid I wasn’t fooled by Apple.

Why do you have to make a Watch App

After a lot of potholes and a lot of wasted time, I finally got this thing out. The reason why I want to stick to the Watch app is that I think running on the Watch is what a timing tool like tomato clock should look like, and the interaction of “winding” I dreamed up before can also be well reflected on the Watch.

I don’t know why I haven’t heard about these annoying issues, whether it’s because the version of Xcode I created the project with is buggy, or whether it’s just because my Watch is jammed. Anyway, I hope the solution mentioned in this article can be helpful to students who are willing to jump into the pit in the future. Thanks again for the second-hand Apple Watch that Griffin gave me to make this Watch APP available. If you are willing to support me, please buy PomoNow on the App Store. Well, that’s it. I’m gonna take a break.



PomoNow: AppStore

Note:

1. The content of this article is the author’s personal development experience on the original Apple Watch, which does not guarantee to cover all other situations.

2. Due to trademark rights, PomoNow has not been put on the shelves in the United States and Europe (the whole App cannot contain the word Pomodoro or part of the word), and it may be put on the shelves again after changing its name.

3. I actually took the picture for fun. I chopped two apples (which I will eat later) to take this picture. I hope I didn’t scare anyone (laughs).