<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.jacklandrin.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.jacklandrin.com/" rel="alternate" type="text/html" /><updated>2026-02-14T16:05:23+00:00</updated><id>https://www.jacklandrin.com/feed.xml</id><title type="html">Blogs</title><subtitle>Jacklandrin&apos;s Blogs</subtitle><entry><title type="html">We should worry about AI!</title><link href="https://www.jacklandrin.com/ai/2024/01/07/We-should-worry-about-AI.html" rel="alternate" type="text/html" title="We should worry about AI!" /><published>2024-01-07T00:00:00+00:00</published><updated>2024-01-07T00:00:00+00:00</updated><id>https://www.jacklandrin.com/ai/2024/01/07/We-should-worry-about-AI</id><content type="html" xml:base="https://www.jacklandrin.com/ai/2024/01/07/We-should-worry-about-AI.html"><![CDATA[<p>Last year, I wrote an article, <a href="https://jacklandrin.github.io/ai/2023/04/01/Should-we-worry-about-AI.html">Should we worry about AI</a>. I interpret that we don’t need to be worried AI will destroy our world at the end of the day, and we should regard it as just an advanced tool to use well. I’m generally less inclined to see new technologies in a negative light. However, we have to be concerned about some side effects of the AI age as well. 
<img src="/assets/img/images/AIControl.png" alt="" /></p>
<h2 id="content-based-recommendations--information-cocoon">Content-Based Recommendations &amp; Information cocoon</h2>
<p>I believe that most people noticed that websites and apps can display content based on the history that they browsed. It happens on a batch of platforms such as TikTok, Twitter, YouTube and so on… When you order two or three times burgers on a food delivery app, it will often recommend burgers for you. It sounds pretty good to let you see more content which you’re interested in according to your preferences, but it also brings a critical problem – <strong>Information cocoon</strong>.</p>

<h3 id="whats-the-information-cocoon">What’s the Information cocoon?</h3>
<p>Information cocoon is as known as <strong>Echo Chamber</strong>, which refers to a situation where individuals are surrounded by, and primarily exposed to, information and ideas that align with their existing beliefs and perspectives. It can lead to limited exposure to diverse viewpoints and may reinforce pre-existing biases or opinions. Actually, this situation always happens in our human society, but AI systems possibly inadvertently contribute to or solidify these information bubbles by selectively presenting or amplifying content that aligns with a user’s existing views, rather than providing a balanced and diverse range of information.</p>

<p><img src="/assets/img/images/imformationbubble.png" alt="" /></p>

<p>For example, I often search for political topics on a Q&amp;A website, while my friend usually looks up travel topics on it. Many days later, I only can view political content on its home page, while my friend’s only includes items about trips. It seems fine, we both follow our favourite topics, but after a long time, I will find there is only politics in my world, and I have less and less chance to learn about other people’s topics such as travel. The content of my account locks me in an information bubble by my initial selection of topics. I’m cut off from other topics on this site. Nevertheless, it’s not the worst situation. Let’s see a real example.</p>

<h3 id="display-of-different-comments-based-on-gender">Display of Different Comments based on gender</h3>

<p>In a Chinese social media platform, someone posted a video about the gender topic. Gender opposition is a big topic in China so this video was very hot. However, users found that the comments on the video were ordered as different weights in terms of gender when people talked about it. If the user is a male, the first few comments content is inclined to man, and vice versa. Thus, different gender users weren’t able to see other’s opinions.</p>

<p><img src="/assets/img/images/gendersopposition.png" alt="" /></p>

<p>Recommendation systems aim to please users’ preferences without truly facilitating exchanges of opposing viewpoints between different sides. This behaviour objectively exacerbates the opposition between genders, as everyone is simply fervently expressing their own viewpoints. Even many people, when they see content aligned with their preferences, further reinforce their preexisting beliefs.</p>

<p>Similar things happen not only among genders but also countries, races, ideologies, religions…Many years ago, I thought that the Internet brought diversity to all humankind and let people from different backgrounds learn about each other well, but I’ve also been seeing it potentially enhances hatred, bias and antagonism, especially after the smarter recommendation system was born. Everyone is restricted by a bubble which provides the information that they only want to see.</p>

<h3 id="passively-obtain-information">Passively Obtain Information</h3>

<p>When I search for some keywords on Google, Wikipedia etc, I would say I am actively obtaining information. In the age of AI, we have started to use ChatGPT to actively obtain information. Well, how has AI changed the way of passively obtaining information?</p>

<p>In my childhood, I often listened to music on the radio. I never knew the DJ would play which songs every day. I was just aware of some songs I like and some I dislike. There were different genres, the songs composed in different decades. Though some of them were what I didn’t enjoy, I found a lot of fresh styles I never touched before.</p>

<p>However, on some current music platforms, AI can deeply learn my behaviour so that it judges what I would like. I increasingly feel that the songs recommended by the system are severely homogeneous. It lets me feel there’s only one genre in the world, very bored, but when I look at other people’s playlists, a whole new world opens up.</p>

<p>I believe that most information is passively acquired rather than actively sought. Recommendation algorithms make passive information acquisition easy but dull.</p>

<h3 id="is-ai-the-sin-for-it">Is AI the Sin for It?</h3>

<p>Firstly, I don’t believe AI is the root cause of all this. Hatred, bias, and opposition have existed in humanity since early times, and each specific culture has been an echo chamber in the past. It’s just that AI has learned all of this and, with its immense computational power, has presented it to humanity. However, AI does indeed objectively reinforce many of our inherent biases and perceptions, making it difficult to objectively understand the world when passively acquiring knowledge. It’s not an exaggeration to say that we are being brainwashed by AI every day.</p>

<p>When I realize that our thoughts are being subtly changed, even possibly controlled, by AI, I can’t help but have concerns about AI. This also involves ethical and moral issues. When I asked ChatGPT whether AI solidifies information bubbles, it replied with:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AI itself does not solidify information bubbles, but it can be influenced by data and algorithms, leading to the formation of information bubbles. If AI only encounters specific types of data or undergoes biased algorithm training, it may generate biases or limit the scope of information. Therefore, ensuring that AI systems have access to diverse and fair data, as well as well-designed algorithms, is crucial to avoid the issue of information bubbles.
</code></pre></div></div>
<p>Therefore, I believe that software service providers are the ones truly obligated to improve this situation. They have the capability to set limits and rules for AI, adjust algorithms, provide diversity in content, and mitigate some of the societal conflicts.</p>

<p>I’m glad to see that the EU has already established laws addressing the ethical and moral issues brought by AI. There are still many ethical concerns posed by AI, such as the ability to mimic human faces and voices, potentially spreading false information. Besides, there are numerous challenges that I think we should be concerned about, prompting the need for more reasonable regulations to mitigate these issues. More importantly, it’s crucial to raise awareness among more people about these potential risks.</p>]]></content><author><name></name></author><category term="AI" /><category term="AI" /><summary type="html"><![CDATA[Last year, I wrote an article, Should we worry about AI. I interpret that we don't need to be worried AI will destroy our world at the end of the day, and we should regard it as just an advanced tool to use well. I'm generally less inclined to see new technologies in a negative light. However, we have to be concerned about some side effects of the AI age as well.]]></summary></entry><entry><title type="html">Should we worry about AI?</title><link href="https://www.jacklandrin.com/ai/2023/04/01/Should-we-worry-about-AI.html" rel="alternate" type="text/html" title="Should we worry about AI?" /><published>2023-04-01T00:00:00+00:00</published><updated>2023-04-01T00:00:00+00:00</updated><id>https://www.jacklandrin.com/ai/2023/04/01/Should-we-worry-about-AI</id><content type="html" xml:base="https://www.jacklandrin.com/ai/2023/04/01/Should-we-worry-about-AI.html"><![CDATA[<p><img src="/assets/img/images/image-chatgpt-openai.jpg" alt="" />
Nowadays GPT 4.0 has brought the topic of AI unprecedented attention. While many people enjoy this new technology, some express their worries.
Perhaps you heard these from the Internet and your friends:</p>
<ul>
  <li>ChatGPT is an amazing thing, but it will replace many jobs. Even in a certain future, AI will be able to have self-awareness and then dominate human beings.</li>
  <li>ChatGPT will collect everyone’s data and become some Big Bads’ tool to govern the blue planet.</li>
  <li>Once AI is enough smart and strong, it will destroy this disgusting world.</li>
</ul>

<p><img src="/assets/img/images/IMG_5215.JPG" alt="" /></p>

<p>Actually, these opinions are not strange. When electricity, cars, and nuclear weapons were created, people also expressed similar points of view. Basically, every revolutionary innovation always comes with controversy. I admit certain apprehension is necessary, but I believe that most of them are inevitable in the development of technology, which makes us have to face them with a positive mindset.</p>

<h3 id="who-will-be-replaced-by-chatgpt">Who will be replaced by ChatGPT?</h3>
<p>While modern medicine replaced witchcraft, shamans were replaced by doctors. 
While cars replaced carriages, there are more and more drivers instead of horsemen.
While chainsaws replaced traditional saws, lumberjacks weren’t replaced, they just changed the way to cut more trees.
While computers replaced abaci, accountants are busier and busier.</p>

<p>YES, technology will weed out some things that couldn’t keep up while they created more new demands as well. I believe ChatGPT won’t let painters and writers lose their jobs. Instead, more people will learn how to use AI as a tool to show their creativity. Actually, AI reduces the learning curve for programming, painting, writing and many many staffs.</p>

<p>Someone said tools are extensions of the human. Only if they are better than our hands, legs and brain, we will be willing to use them. Machines can be beyond our hands; vehicles are faster than our legs; calculators make us not need to do mental arithmetic. Thus, it is unnecessary to be worried that ChatGPT is smarter than us. We just want to invent something better than ourselves as a tool, and that’s what tools are all about.</p>

<h3 id="could-chatgpt-make-our-work-easier">Could ChatGPT make our work easier?</h3>

<p>Yes and No.</p>

<p>ChatGPT indeed brought a lot of benefits to us. In the past, we perhaps need a whole day to finish a UI design of one page. At present we just tell ChatGPT what we need, and then it could provide its artwork in only seconds. We do not need to spend a lot of time finding a solution on Stackoverflow to fix a bug anymore.</p>

<p>Though it seems to improve our unit work efficiency, we won’t still keep past workload. Due to human desires, trust me, new technologies will not only bring exponential improvements in efficiency but also exponential demand. Marketing doesn’t allow you to finish your work that took 8 hours per day in 1 hour now, meanwhile spending the rest 7 hours resting. We have to do more things to meet inflated demand. Workflows and organizational structures also become more complex as demands increase. When the time comes, you will see new careers and methods of working.</p>

<h2 id="more">More</h2>

<p><img src="/assets/img/images/asteroids.jpg" alt="" /></p>

<p>Human beings may just be accidents in the universe. We do never know about the plague, climate change, or asteroids which one will first destroy us. Probably we are overly concerned about the dangers of nuclear weapons and AI, but they might be able to help us resolve those. The AI could speed up research of vaccines; unclear weapons could destroy asteroids. I cannot predict what will happen in the future, I just know advanced technologies could bring hope for unknown everything.</p>]]></content><author><name></name></author><category term="AI" /><category term="AI" /><summary type="html"><![CDATA[Nowadays GPT 4.0 has brought the topic of AI unprecedented attention. While many people enjoy this new technology, some express their worries.]]></summary></entry><entry><title type="html">The Principle of ProMotion</title><link href="https://www.jacklandrin.com/programming/2022/01/14/the-principle-of-promotion.html" rel="alternate" type="text/html" title="The Principle of ProMotion" /><published>2022-01-14T00:00:00+00:00</published><updated>2022-01-14T00:00:00+00:00</updated><id>https://www.jacklandrin.com/programming/2022/01/14/the-principle-of-promotion</id><content type="html" xml:base="https://www.jacklandrin.com/programming/2022/01/14/the-principle-of-promotion.html"><![CDATA[<p>ProMotion is a significant innovation for screen display. It can dynamically adjust refresh rate based on user’s interaction and content, which makes smoother scrolling. This technology is used in iPad Pro, iPhone 13 Pro and M1 Pro/Max Macbook. It not only enhances user experience, but also saves energy in most of time.
In my former article <em>iOS Graphics: Workflow of Graphics System</em>, I introduced how the screen refreshes to display graphic. As dynamic refresh rate, however, ProMotion use a new refreshing logic to display graphic. Therefore, developers have to adapt it by externel code.</p>

<h2 id="why-these-refresh-rates">Why these refresh rates?</h2>

<p>The Aritcle <a href="https://developer.apple.com/documentation/quartzcore/optimizing_promotion_refresh_rates_for_iphone_13_pro_and_ipad_pro">Optimizing ProMotion Refresh Rates for iPhone 13 Pro and iPad Pro</a> mentions all refresh rate supported by Apple devices. For iPhone 13 Pro, they are 120Hz, 80Hz, 60Hz, 48Hz, 40Hz, 30Hz, 24Hz, 20Hz, 16Hz, 15Hz, 12Hz, 10Hz. Some people are worndering why they are these numbers, why there aren’t 90Hz or 100Hz.
The answer is OLED display. The OLED screen use PWM(Pulse-width modulation) Dimming. PWM is different with DC Dimming on LCD display. DC dimming adjusts brightness by changing voltage. However, if the OLED display uses this way, the components’ lifespan will be affected and the colour effect will be not good in some cases. PWM, therefore, is adapted on the OLED devices. Its basics is that it turns the display on and off in a very hight frequency to control brightness. You can easily understant it by the following image.
<img src="http://www.jacklandrin.com/wp-content/uploads/2022/01/Display-PWM-duty-cycles-img_assist-400x206-1.jpg" alt="" />
If the brightness is set as 50% in a certain span of time, just keep 50% time is on and 50% time is off in same frequency. This is an easy(or cost-effective) way to achieve aim. Nevertheless, it has serious drawbacks, such as the flicker that may cause eye strain and headaches. Just this isn’t today’s topic.</p>

<p>Apple uses PWM on iPhone 13 Pro and M1 Pro/Max Macbook as well, and its rate of controlling brightness is 480Hz, that means the OLED display turns on and off 480 times in one second. For this reason, the refresh rates can only be 480’s divisor, unless the graphics can’t be normally displayed. So, let’s focus these numbers, they are all divible by 480, while 90Hz and 100Hz can’t.</p>

<h2 id="new-refreshing-flow">New refreshing flow</h2>

<p>Due to Adaptive-Sync display, devices can’t update graphics based on screen’s VSync. Apple creates a new stradegy for ProMotion. Look at the image blow:
<img src="http://www.jacklandrin.com/wp-content/uploads/2022/01/promotionflow.png" alt="" /></p>

<p>The default refresh rate is 120Hz, so the graphics rendered by CPU and GPU will be displayed per 8.33ms. If the time cost exceeds 8.33ms, for example CPU and GPU finish their job in 10ms, the screen won’t refresh the graphics. Since I described in above text, iPhone 13 Pro can’t support 100Hz(refresh per 10ms), the screen will refresh in 12.5ms(80Hz). The NOP is the waiting time. If the CPU and GPU spends less than 8.33ms in next refreshing, the rate will restore back to 120Hz.</p>

<p>So, the time CPU and GPU spending decides the real refresh rate. This is also the main target of performance optimizing for ProMotion screen.</p>

<h2 id="how-to-implement-promotion">How to implement ProMotion?</h2>
<p>Apple introduced how to <a href="https://developer.apple.com/videos/play/wwdc2021/10147/">opitmize for variable refresh rate displays</a> in WWDC21.</p>
<h3 id="masos">masOS</h3>
<p>We can learn about that developer can set the frame-pacing in macOS like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[commandBuffer presentDrawable:drawable afterMinimumDuration:interval];
[commandBuffer presentDrawable:drawable atTime:t];
</code></pre></div></div>
<p>or set own <code class="language-plaintext highlighter-rouge">drawable</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[commandBuffer presentDrawable:drawable];
</code></pre></div></div>
<p>Then how much duration is reasionable? If you select set the drawable by yourself, you can calculate the average GPU time as next minimum refreshing duration. Look following code:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>id&lt;CAMetalDrawable&gt; currentDrawable = [metalLayer nextDrawable];

// Your encoders and command buffers are still available!

NSTimeInterval averageGPUTime = screen.minimumRefreshInterval;

[commandBuffer presentDrawable:currentDrawable afterMinimumDuration:averageGPUTime];

[commandBuffer addCompletedHandler:^(id&lt;MTLCommandBuffer&gt; buffer) {
  const NSTimeInterval GPUTime = buffer.GPUEndTime - buffer.GPUStartTime;

  // Use an exponential moving average
  const double alpha = .25;

  averageGPUTime = (GPUTime * alpha) + (averageGPUTime * (1.0 - alpha));
}];
</code></pre></div></div>
<h3 id="ipados-and-ios">iPadOS and iOS</h3>
<p><code class="language-plaintext highlighter-rouge">CVDisplayLink</code> and <code class="language-plaintext highlighter-rouge">CADisplayLink</code> are used for smooth opitimizing on fixed refresh rate displays. They are still used on variable refresh rate displays.
Timing is the most important thing for refresh graphics. Good timing can reduce NOP time to make display smoother. A regular timer, such as an NSTimer, is very unlikely to be in perfect sync with the display. But CADisplayLink can provide consistent timings. Develepers can use following way to set a reasonable refresh progress by CADisplayLink:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- (void)displayLinkCallback:(CADisplayLink *)link {
    progress += link.targetTimestamp - previousTargetTimestamp;
    previousTargetTimestamp = link.targetTimestamp;

    [self renderAnimationWithProgress:progress withDeadline:link.targetTimestamp];
}
</code></pre></div></div>]]></content><author><name></name></author><category term="programming" /><category term="programming" /><summary type="html"><![CDATA[ProMotion is a significant innovation for screen display. It can dynamically adjust refresh rate based on user's interaction and content, which makes smoother scrolling. This technology is used in iPad Pro, iPhone 13 Pro and M1 Pro/Max Macbook. It not only enhances user experience, but also saves energy in most of time.]]></summary></entry><entry><title type="html">OnlySwitch</title><link href="https://www.jacklandrin.com/macos%20app/2021/12/01/onlyswitch.html" rel="alternate" type="text/html" title="OnlySwitch" /><published>2021-12-01T00:00:00+00:00</published><updated>2021-12-01T00:00:00+00:00</updated><id>https://www.jacklandrin.com/macos%20app/2021/12/01/onlyswitch</id><content type="html" xml:base="https://www.jacklandrin.com/macos%20app/2021/12/01/onlyswitch.html"><![CDATA[<p align="left">
<img alt="AppIcon" src="https://github.com/jacklandrin/OnlySwitch/blob/main/OnlySwitch/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png?raw=true" width="128px" align="center" />
</p>

<h1 id="onlyswitch">OnlySwitch</h1>

<p><strong><em>Menubar is smaller, you only need an All-in-One switch.</em></strong></p>

<h2 id="install-by-homebrew">Install by Homebrew</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew install only-switch
</code></pre></div></div>
<h2 id="manually-download">Manually Download</h2>
<p><a href="https://github.com/jacklandrin/OnlySwitch/releases/latest/download/OnlySwitch.dmg"><strong>Download the app</strong></a></p>

<h2 id="communities">Communities</h2>
<p>Telegram group: https://t.me/OnlySwitchforMac</p>

<p>Discord: https://discord.gg/UzSNpYdPZj</p>

<h2 id="whats-the-onlyswitch">What’s the OnlySwitch?</h2>
<p>OnlySwitch provides a series of toggle switches to simplify your routine work, such as Hidden desktop icons, dark mode, and hide notch of the new Macbook Pro. The switches show on your status bar, you can control them effortlessly. Switch and Shortcuts items can be customized (remove/add or sort) to show on the list. These functionalities even can be put on your desktop as Widgets.</p>

<p>Since Version 1.7, <strong>Shortcuts</strong> can be imported into OnlySwitch.</p>

<p>Since Version 2.0, supports <strong>keyboard shortcuts</strong>. You can control your all switches and Shortcuts with the keyboard.</p>

<p align="center">
<img alt="Only Switch" src="https://github.com/user-attachments/assets/40d94175-6487-4c59-b09e-2261ac5b8453" width="80%" align="center" />
</p>

<p>Since Version 2.3.6, the Switches Availability (including Player and Hide Menu Bar Icons) is moved to System’s menu bar.</p>

<p><img src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/11c89e33-2007-4913-b320-47c188538b68" alt="" /></p>

<p>Since Version 2.5.0, OnlySwitch has started to support <strong>Apple Widgets</strong> (Sonoma and above).</p>

<p>Since Version 2.5.4, OnlySwitch has Only Control appearance.</p>

<h2 id="shortcuts-gallery">Shortcuts Gallery</h2>

<p>Everyone can contribute macOS Shortcuts for OnlySwitch now. Please read <a href="ShortcutsGalleryContributing.md">How to contribute to Shortcuts Gallery</a>. The shared Shortcuts will be displayed here:</p>

<p align="center">
<img alt="Sits in the status bar" src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/a9d90eed-c540-4183-9332-396dce0f72d4" width="70%" align="center" />
</p>

<h2 id="switch-list">Switch list</h2>

<h4 id="native-switches">Native Switches:</h4>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Switch</th>
      <th>status</th>
      <th style="text-align: left">Switch</th>
      <th style="text-align: left">status</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">Hide desktop</td>
      <td>finished</td>
      <td style="text-align: left">Hide notch</td>
      <td style="text-align: left">exist some issues</td>
    </tr>
    <tr>
      <td style="text-align: left">Dark mode</td>
      <td>finished</td>
      <td style="text-align: left">Low power mode</td>
      <td style="text-align: left">require password</td>
    </tr>
    <tr>
      <td style="text-align: left">Screen Saver</td>
      <td>finished</td>
      <td style="text-align: left">Show Finder Path Bar</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Night Shift</td>
      <td>finished</td>
      <td style="text-align: left">Mute mic</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Autohide Dock</td>
      <td>finished</td>
      <td style="text-align: left">Small launchpad icon</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Airpods</td>
      <td>finished</td>
      <td style="text-align: left">Pomodoro timer</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Bluetooth</td>
      <td>finished</td>
      <td style="text-align: left">Show extension name</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Xcode cache</td>
      <td>finished</td>
      <td style="text-align: left">Show user library folder</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Autohide Menu Bar</td>
      <td>finished</td>
      <td style="text-align: left">Mute</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Show hidden files</td>
      <td>finished</td>
      <td style="text-align: left">Empty pasteboard</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Radio Station</td>
      <td>finished</td>
      <td style="text-align: left">Empty trash</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Keep awake</td>
      <td>finished</td>
      <td style="text-align: left">Show Recent Apps on Dock</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Spotify</td>
      <td>finished</td>
      <td style="text-align: left">Apple Music</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Screen Test &amp; Clean</td>
      <td>finished</td>
      <td style="text-align: left">Hide Menu Bar Icons</td>
      <td style="text-align: left">partly finished</td>
    </tr>
    <tr>
      <td style="text-align: left">FKey</td>
      <td>finished</td>
      <td style="text-align: left">Back Noises</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Dim Screen</td>
      <td>finished</td>
      <td style="text-align: left">Eject Discs</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Hide Windows</td>
      <td>partly finished</td>
      <td style="text-align: left">True Tone</td>
      <td style="text-align: left">finished</td>
    </tr>
    <tr>
      <td style="text-align: left">Top Sticker</td>
      <td>partly finished</td>
      <td style="text-align: left">Key Light</td>
      <td style="text-align: left">finished</td>
    </tr>
  </tbody>
</table>

<p>Since Version 1.3, switches can be added to or removed from the list.</p>

<h4 id="shortcuts-gallery-1">Shortcuts Gallery:</h4>

<table>
  <thead>
    <tr>
      <th>Shortcuts</th>
      <th>Remark</th>
      <th>Shortcuts</th>
      <th style="text-align: left">Remark</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Toggle Scroll Direction</td>
      <td>Monteray</td>
      <td>Invert Scroll Direction(Ventura)</td>
      <td style="text-align: left">Ventura</td>
    </tr>
    <tr>
      <td>DarkMode Switch</td>
      <td> </td>
      <td>Network Details</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td>Split-Screen Apps</td>
      <td> </td>
      <td>Passwords</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td>Google Translate</td>
      <td> </td>
      <td>IP Address Information</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td>Autohide menu bar in full screen</td>
      <td>Monteray</td>
      <td>Flush DNS Cache</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td>Do Not Disturb</td>
      <td>Monteray or higher</td>
      <td>Upcoming Events</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td>S-GPT</td>
      <td>works with S-GPT Encoder, needs OpenAI API key</td>
      <td>S-GPT Encoder</td>
      <td style="text-align: left"> </td>
    </tr>
  </tbody>
</table>

<h4 id="evolution-gallery">Evolution Gallery:</h4>

<table>
  <thead>
    <tr>
      <th>Evolution</th>
      <th>Remark</th>
      <th>Evolution</th>
      <th style="text-align: left">Remark</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Stage Manager</td>
      <td> </td>
      <td>Update Software</td>
      <td style="text-align: left">installed via App Store</td>
    </tr>
    <tr>
      <td>Hide desktop Widget</td>
      <td>Sonoma</td>
      <td>Hide Desktop Icons</td>
      <td style="text-align: left">Sonoma</td>
    </tr>
    <tr>
      <td>Clamshell</td>
      <td> </td>
      <td>Wifi Switch</td>
      <td style="text-align: left"> </td>
    </tr>
  </tbody>
</table>

<h2 id="shortcuts-actions">Shortcuts Actions</h2>

<table>
  <thead>
    <tr>
      <th>Actions</th>
      <th>status</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Get wallpaper image</td>
      <td>exist some issues</td>
    </tr>
    <tr>
      <td>Get wallpaper url</td>
      <td>finished</td>
    </tr>
    <tr>
      <td>Is dark mode</td>
      <td>finished</td>
    </tr>
    <tr>
      <td>Set dark mode</td>
      <td>finished</td>
    </tr>
  </tbody>
</table>

<h2 id="supported-languages-">Supported Languages 🇺🇳</h2>
<p>English, Simplified Chinese, German, Croatian, Turkish, Polish, Filipino, Dutch, Italian, Russian, Spanish, Japanese, Somali, Korean, French, Ukrainian, Slovak, Portuguese (BR)</p>

<h2 id="welcome-to-pull-requests-for-these">Welcome to pull requests for these</h2>

<ul>
  <li>support other languages</li>
  <li>fix bugs</li>
</ul>

<p>If you have other good ideas 💡, feel free to send an E-mail to me.</p>

<h2 id="donate">Donate</h2>
<p>If you like it, help support this app by giving me a cup of tea for me to keep coding.</p>
<p align="center">
<img alt="Sits in the status bar" src="https://github.com/user-attachments/assets/76347782-e84f-469d-b9bf-2dae89d61979" width="20%" align="medium" title="Made by QRCobot" />
</p>

<h2 id="hiding-new-macbook-notch">Hiding new Macbook Notch</h2>

<p>The Hide notch switch only shows on the built-in display of M1 Pro/Max Macbook Pro. The switch just controls the current desktop, not all work desktops.
Now, the Hide notch switch supports dynamic wallpaper, just the processing takes a much longer time.</p>
<p align="center">
<img alt="Sits in the status bar" src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/efddd8d3-edfe-4497-bea0-5051d27625ca" width="60%" align="center" />
</p>

<h2 id="only-widget">Only Widget</h2>

<p>Only Switch supports Apple Widgets since version 2.5.0. The Widgets can be edited to any built-in switches and buttons. Clicking them will trigger the reflection of relevant switches and buttons. You can put Only Widgets anywhere, desktop or notification center.</p>

<p>Since version 2.5.2, Only Widget supports Evolution.</p>

<p><strong>NOTE:</strong> After updating version 2.5.0, you might need to reset your language. If your widgets didn’t follow your language settings, please kill Only Widget process, it will update.</p>

<p><img width="370" alt="Only Widget" src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/0c1be202-9e5f-41dd-b62d-52d5a7147139" /></p>

<h2 id="evolution">Evolution🔥</h2>
<p>Evolution has come following version 2.4, you can freely DIY the switches and buttons that you want. Currently, evolution supports <strong>Shell</strong> and <strong>Apple Script</strong>. They also can be invoked by hotkeys. Next, evolution will be able to be distributed by users as a shortcut utility platform.</p>

<p>Evolution settings page is implemented with TCA.
PS: Evolution feature needs macOS 13.0 and above.</p>

<p><img src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/69131917-bfe0-4c54-8b38-d4aeb26f749a" alt="" /></p>

<p>Everyone can contribute Evolution for OnlySwitch since version 2.4.3. Please read <a href="EvolutionGalleryContributing.md">How to contribute to Evolution Gallery</a>. The shared Evolutions will be displayed here:</p>

<p align="center">
<img alt="Sits in the status bar" src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/f3299ae0-0222-49a3-864a-80c6601bac6a" width="70%" align="center" />
</p>

<h3 id="how-to-create-an-evolution">How to create an Evolution?</h3>
<p>So far, Evolution offers two types, with Switch and Button.</p>
<ol>
  <li>Button is very simple, when Run button is pressed, the script you added will be executed.</li>
  <li>Regarding Switch, there are four fields you can edit.
    <ul>
      <li>Check status: When OnlySwitch list appeared or some settings are changed, the switch status will be checked whether on or off. At this moment, the script of check status will be executed. You can press the debug button to output the result of this script.</li>
      <li>True condition: You can input a true condition to define what is on or off for the switch status. If the true condition matches the output result, the status will be on, and vice versa.</li>
      <li>Turn on: the script can change the status to on.</li>
      <li>Turn off: the script can change the status to off.</li>
    </ul>
  </li>
</ol>

<p>The debug button can verify if your scripts are valid. Before you save evolution, all scripts must pass the test.</p>

<h2 id="airpods-switch">AirPods Switch</h2>
<p>I use <code class="language-plaintext highlighter-rouge">classOfDevice</code>(2360344) to check if a Bluetooth device is Airpods Pro, but I’m not sure whether other AirPods modules are also 2360344, since I only have two AirPods Pros. If you are using AirPods 1~3, please tell me what the <code class="language-plaintext highlighter-rouge">classOfDevice</code> is. Or I can detect the count of battery value to check if AirPods (when the count is 3, it’s AirPods), like <strong>AirPods Battery Monitor For MAC OS</strong>.</p>

<h2 id="radio-player">Radio Player</h2>
<p>Radio Player supports m3u, and aac stream, but without sound wave effect. Please send me the crash log and stream URL if your Radio Player crashes. You can close the sound wave effect on the Radio setting, and that player is AVPlayer, more stable. In version 2.3.5, the radio play can be set to enable/disabled. If the function is disabled, the switch will be invisible in the list, and the radio player will be unregistered from Now Playing(But I don’t know why there will be a little delay. It should be a problem by macOS).</p>

<p>Since Version 2.3.11, the radio list can be exported and imported.</p>

<h2 id="low-power-mode">Low Power Mode</h2>
<p>Low Power Mode uses Terminal commands that require root access, so the app will ask you to enter the password on every toggle.</p>

<h2 id="screen-test--clean">Screen Test &amp; Clean</h2>
<p>In Version 2.3, Only Switch brings a new feature, Screen Test. It provides a pure color view in full-screen mode, you can check dead pixels via it. Press the left and right arrow keys, the color will change from black, white, red, green, and blue. This functionality also can be used for screen cleaning, as you can see the stains on the screen.</p>

<h2 id="hide-menu-bar-icons">Hide Menu Bar Icons</h2>
<p>This feature is new in version 2.3.2. To be honest, Hidden and Dozer are both good apps for this function. Many users install OnlySwitch and them simultaneously, but this also squeezes the menu bar, which is already lacking in space. Therefore, the feature integrates into OnlySwitch.
<img src="https://github.com/jacklandrin/OnlySwitch/assets/3782279/fdda284e-929f-400e-aba5-9c628f065de6" alt="" />
When the switch is on, items on the left of the split(arrow-pointing) icon are hidden. Hold ⌘ (command) and drag the icon to configure the hidden section. If you want to use it no longer, you can disable it in preferences, the split icon will disappear. You also can set the interval of autohide for it here. If your date on the menu bar is truncated when it’s on, you can set this: System Preferences -&gt; Dock &amp; Menu Bar -&gt; Clock -&gt; Show date -&gt; always.</p>

<p>Since version 2.3.10, this switch can be controlled via right-click icons.</p>

<h2 id="they-talk-about-it">They talk about it</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
      <th> </th>
      <th style="text-align: left"> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><a href="https://www.itopnews.de/?s=OnlySwitch">itopnews.de</a></td>
      <td><a href="https://www.ifun.de/suche/OnlySwitch">Ifun.de</a></td>
      <td><a href="https://www.appgefahren.de/onlyswitch-kleines-tool-mit-wichtigen-aktionen-fuer-die-mac-menueleiste-312135.html">appgefahren.de</a></td>
      <td style="text-align: left"><a href="https://stadt-bremerhaven.de/only-switch-fuer-macos-schnellzugriff-auf-einige-systemoptionen/">CASCHYS BLOG</a></td>
    </tr>
    <tr>
      <td><a href="https://mac.softpedia.com/get/System-Utilities/OnlySwitch.shtml">softpedia</a></td>
      <td><a href="https://www.macupdate.com/app/mac/63719/onlyswitch">macupdate</a></td>
      <td><a href="https://www.v1tx.com/post/onlyswitch/">v1tx</a></td>
      <td style="text-align: left"><a href="https://www.oschina.net/p/onlyswitch">OSCHINA</a></td>
    </tr>
    <tr>
      <td><a href="https://www.macken.xyz/2021/12/gratis-ar-gott-alla-installningar-pa-ett-stalle-onlyswitch/">Macken</a></td>
      <td><a href="https://applech2.com/archives/20220111-onlyswitch-all-in-one-status-bar-button-for-mac.html">AAPL Ch</a></td>
      <td><a href="https://appsofter.com/download/1265.html">appsofter</a></td>
      <td style="text-align: left"><a href="https://lifehacker.ru/onlyswitch">lifehacker.ru</a></td>
    </tr>
    <tr>
      <td><a href="https://appletechnikblog.com/de/2022/02/25/app-tipp-der-woche-only-switch-fuer-die-menueleiste-auf-dem-mac/">appletechnikblog</a></td>
      <td><a href="https://en.blog.themarfa.name/how-to-quickly-manage-macos-system-settings/">All-in-One person</a></td>
      <td><a href="https://www.macgadget.de/News/2022/03/24/OnlySwitch-Schnellzugriff-auf-viele-Systemfunktionen-per-Mac-Menueleiste">Mac Gadget</a></td>
      <td style="text-align: left"><a href="https://www.maxiapple.com/2022/05/onlyswitch-macos-mac-gratuit.html">MaxiApple</a></td>
    </tr>
    <tr>
      <td><a href="https://insmac.org/macosx/5018-onlyswitch.html">insmac</a></td>
      <td><a href="https://tchgdns.de/onlyswitch-macos-open-source/">tchgdns</a></td>
      <td><a href="https://insmac.org/macosx/5018-onlyswitch.html">insmac</a></td>
      <td style="text-align: left"><a href="https://macbff.com/onlyswitch-2-3-1/">macbff</a></td>
    </tr>
    <tr>
      <td><a href="https://korben.info/controler-macos-onlyswitch.html">korben</a></td>
      <td><a href="https://www.macg.co/logiciels/2023/03/onlyswitch-ajoute-une-pelletee-de-raccourcis-pratiques-votre-barre-des-menus-135357">macg</a></td>
      <td><a href="https://korben.info/controler-macos-onlyswitch.html">korben.info</a></td>
      <td style="text-align: left"><a href="https://alternativeto.net/software/only-switch">AlternativeTo</a></td>
    </tr>
    <tr>
      <td><a href="https://macsoft.jp/onlyswitch/">macsoft.jp</a></td>
      <td><a href="https://www.macg.co/logiciels/2023/03/onlyswitch-ajoute-une-pelletee-de-raccourcis-pratiques-votre-barre-des-menus-135357">macgeneration</a></td>
      <td><a href="https://hdwh.de/onlyswitch-vereinfacht-eure-routinearbeit-mit-praktischen-schaltern/">hdwh.de</a></td>
      <td style="text-align: left"><a href="https://macked.app/onlyswitch.html">MacKed</a></td>
    </tr>
    <tr>
      <td><a href="https://www.tntmactorrent.net/onlyswitch-for-mac-free-download/">Mac Torrents</a></td>
      <td><a href="https://www.pctipp.ch/praxis/mac/mac-tipp-onlyswitch-2-2892320.html">PCtipp</a></td>
      <td><a href="https://lifehacker.com/tech/change-hidden-mac-settings-with-onlyswitch">lifehacker</a></td>
      <td style="text-align: left"><a href="https://kynguyenso.plo.vn/su-dung-onlyswitch-de-tuy-chinh-tat-ca-cai-dat-may-mac-nhanh-hon-post776151.html">PHAPLUAT</a></td>
    </tr>
    <tr>
      <td><a href="https://tchgdns.de/onlyswitch-menueleisten-multitool-bekommt-widgets-fuer-den-mac-desktop/">Techgedöns</a></td>
      <td><a href="https://www.youtube.com/watch?v=ARfBLKzRQY4&amp;t=41s">MacVince</a></td>
      <td> </td>
      <td style="text-align: left"> </td>
    </tr>
  </tbody>
</table>

<h2 id="reference">Reference</h2>

<ul>
  <li>NightShift switch refers to <a href="https://github.com/joshjon/nocturnal">Nocturnal</a></li>
  <li><a href="https://github.com/sindresorhus/LaunchAtLogin">LaunchAtLogin</a></li>
  <li>AirPods Battery refers to <a href="https://github.com/mohamed-arradi/AirpodsBattery-Monitor-For-Mac">AirPods Battery Monitor For MAC OS</a></li>
  <li>Dynamic Wallpaper processing refer to https://itnext.io/macos-mojave-dynamic-wallpaper-fd26b0698223 and <a href="https://github.com/mczachurski/wallpapper">wallpapper</a></li>
  <li><a href="https://github.com/elai950/AlertToast">AlertToast</a></li>
  <li><a href="https://github.com/syedhali/AudioStreamer">AudioStreamer</a> modified for live streaming</li>
  <li><a href="https://github.com/potato04/AudioSpectrum">AudioSpectrum</a> modified for AppKit</li>
  <li><a href="https://github.com/Alamofire/Alamofire">Alamofire</a></li>
  <li>Sound Source: <a href="https://mixkit.co">mixkit</a> and <a href="https://pixabay.com">pixabay</a></li>
  <li><a href="https://github.com/sindresorhus/KeyboardShortcuts">KeyboardShortcuts</a></li>
  <li>Apple Music &amp; Spotify Switch refer to <a href="https://github.com/kmikiy/SpotMenu">SpotMenu</a></li>
  <li>The idea of hiding menu bar icons from <a href="https://github.com/dwarvesf/hidden">Hidden</a></li>
  <li>FKey refer to <a href="https://github.com/Pyroh/Fluor">Fluor</a></li>
  <li>Hide Windows refer to <a href="https://github.com/alyssaxuu/later">Later</a></li>
  <li><a href="https://github.com/pointfreeco/swift-composable-architecture">The composable architecture</a></li>
  <li><a href="https://github.com/sparkle-project/Sparkle">Sparkle</a></li>
  <li>True Tone refers to <a href="https://github.com/thompsonate/Shifty">Shifty</a></li>
  <li><a href="https://github.com/gonzalezreal/swift-markdown-ui">swift-markdown-ui</a></li>
  <li>Key Light refers to <a href="https://github.com/rakalex/mac-brightnessctl">mac-brightnessctl</a></li>
</ul>

<h2 id="contributors">Contributors</h2>

<p><strong>Translation:</strong></p>

<table>
  <thead>
    <tr>
      <th>Language</th>
      <th>Contributor</th>
      <th style="text-align: left">Language</th>
      <th style="text-align: left">Contributor</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>German</td>
      <td>@C0d3Br3aker</td>
      <td style="text-align: left">Italian</td>
      <td style="text-align: left">@bellaposa</td>
    </tr>
    <tr>
      <td>Croatian</td>
      <td>@milotype</td>
      <td style="text-align: left">Russian</td>
      <td style="text-align: left">@kirillyakopov</td>
    </tr>
    <tr>
      <td>Turkish</td>
      <td>@berkbatuhans</td>
      <td style="text-align: left">Spanish</td>
      <td style="text-align: left">@kant</td>
    </tr>
    <tr>
      <td>Polish</td>
      <td>@kpacholak</td>
      <td style="text-align: left">Japanese</td>
      <td style="text-align: left">@ShogoKoyama</td>
    </tr>
    <tr>
      <td>Dutch</td>
      <td>Alex</td>
      <td style="text-align: left">Somali</td>
      <td style="text-align: left">@abdorizak</td>
    </tr>
    <tr>
      <td>Filipino</td>
      <td>Rosel</td>
      <td style="text-align: left">Korean</td>
      <td style="text-align: left">@iosdevted</td>
    </tr>
    <tr>
      <td>French</td>
      <td>@BtKent and Ange Lefrère</td>
      <td style="text-align: left">Ukrainian</td>
      <td style="text-align: left">@andryua</td>
    </tr>
    <tr>
      <td>Slovak</td>
      <td>@Svec-Tomas</td>
      <td style="text-align: left">Portuguese (BR)</td>
      <td style="text-align: left">@EvertonCa</td>
    </tr>
  </tbody>
</table>

<p>@wrngwrld for the volume slider of the radio player</p>

<p>@kant for syntax issue</p>

<h2 id="license">License</h2>
<p>MIT</p>

<h2 id="star-history">Star History</h2>
<p><a href="https://star-history.com/#jacklandrin/OnlySwitch&amp;Date"><img src="https://api.star-history.com/svg?repos=jacklandrin/OnlySwitch&amp;type=Date" alt="Star History Chart" /></a></p>]]></content><author><name></name></author><category term="MacOS App" /><category term="Swift" /><category term="SwiftUI" /><category term="MacOS App" /><summary type="html"><![CDATA[OnlySwitch provides a series of toggle switches to simply your routine work, such as Hiden desktop icons, dark mode and hide notch of new Macbook Pro. The switches show on your statusbar, you can control them effortlessly.Switch and Shortcuts items can be customized (remove/add or sort) to show on the list.]]></summary></entry><entry><title type="html">QRCobot</title><link href="https://www.jacklandrin.com/ios%20app/2021/10/26/qrcobot.html" rel="alternate" type="text/html" title="QRCobot" /><published>2021-10-26T00:00:00+00:00</published><updated>2021-10-26T00:00:00+00:00</updated><id>https://www.jacklandrin.com/ios%20app/2021/10/26/qrcobot</id><content type="html" xml:base="https://www.jacklandrin.com/ios%20app/2021/10/26/qrcobot.html"><![CDATA[<p><img src="/assets/img/images/QRCobot180.png" alt="" /></p>

<h2 id="english">English</h2>

<h3 id="what-is-qrcobot">What is QRCobot?</h3>

<p><strong>QRCobot</strong> is an extraordinary utility for QR &amp; Bar code. Users can easily create QR &amp; Bar codes that they want, and share them with others. The iOS widgets can show the favourite QR codes on Home screen, which helps users conveniently scan them.</p>

<h3 id="how-to-use-it">How to use it?</h3>

<ol>
  <li>Input your QR code content, such as an URL<br />
 <img src="/assets/img/images/qrcobot_1_2.jpeg" alt="" /></li>
  <li>Select a theme, for instance, Instagram<br />
 <img src="/assets/img/images/qrcobot_2_2.jpeg" alt="" /><br />
 or customize it<br />
 <img src="/assets/img/images/qrcobot_3_3.jpeg" alt="" /><br />
 You will get your individual QR code!<br />
 <img src="/assets/img/images/qrcobot_4_5.jpeg" alt="" /></li>
  <li>Press the first button under the QR code image, you can change the correction level. There are four levels, with 7%, 15%, 25%, 30%, respectively.<br />
 <img src="/assets/img/images/qrcobot_5.jpeg" alt="" /></li>
  <li>If you wanna share the image of QR code or save it on your Photos library, press the second button under image.</li>
  <li>Widget is an excellent feature since iOS 14. QRCobot also supports Widget.</li>
</ol>

<ul>
  <li>First, press the heart button to collect your current QR code, and name it. The QR code will be saved in <strong>My</strong> tab.<br />
  <img src="/assets/img/images/qrcobot_10_1.jpeg" alt="" /><br />
  You also can view Bar code on next page.<br />
  <img src="/assets/img/images/qrcobot_5_2.jpeg" alt="" /></li>
  <li>Second, add a QRCobot Widget on your Home Screen. The App provides three size of Widget for QRCode and medium size for Barcode.<br />
  <img src="/assets/img/images/qrcobot_7_1.jpeg" alt="" /></li>
  <li>Third, long press the widget and tap <strong>Edit Widget</strong> to select a QR code from your favourite list.<br />
  <img src="/assets/img/images/qrcobot_8.jpeg" alt="" /></li>
  <li>Now, the QR codes have been perfectly shown on your phone.<br />
  <img src="/assets/img/images/qrcobot_9.jpeg" alt="" /></li>
  <li>From Version 1.2, QRCobot supports barcode generation and Widget.<br />
  <img src="/assets/img/images/qrcobot_11_1.jpeg" alt="" /><br />
  You can add several medium barcode Widgets on your home screen, and drag them for overlay. They will merge into a <strong>Smart Stack</strong>, that helps can you more conveniently to show and change them.<br />
  <img src="/assets/img/images/barcodewidget_stack.jpeg" alt="" /></li>
  <li>From Version 1.6, you can DIY your QR code frame, when you share the code.<br />
  <img src="/assets/img/images/qrcobot_12_1.jpeg" alt="" /><br />
  You can swipe left or right to change frame. If you don’t want to add a frame, you can toggle to get a raw QR code image.</li>
</ul>

<h3 id="where-can-download-it">Where can download it?</h3>

<p>You can search <strong>“QRCobot”</strong> in App Store, or click <a href="https://apps.apple.com/cn/app/qrcobot/id1590006394?l=en">here</a>.</p>

<h3 id="whats-new">What’s New?</h3>
<h4 id="version-20">Version 2.0</h4>
<ul>
  <li>Support vCard QR Code</li>
  <li>fix bugs</li>
</ul>

<h4 id="version-19">Version 1.9</h4>
<ul>
  <li>Compatible with iPad</li>
  <li>Support selecting icon and watermark from Files</li>
</ul>

<h4 id="version-18">Version 1.8</h4>

<ul>
  <li>Add quick URL input. That supports http, https, Youtube, Bilibili, Instagram, Facebook, Whatsapp</li>
  <li>Support alternate icon, add Chrismac icon</li>
</ul>

<h4 id="version-17">Version 1.7</h4>

<ul>
  <li>fix bug: Barcode is too big to load<br />
  If you cannot load your barcode widget, you need to delete the barcodes that were generated since version 1.5, and generate them by the newest version again.</li>
</ul>

<h4 id="version-16">Version 1.6</h4>

<ul>
  <li>support sharing QRCode image with frame</li>
  <li>modern UI design</li>
</ul>

<h4 id="version-15">Version 1.5</h4>

<ul>
  <li>support code128 Barcode</li>
  <li>support calendar QR code(QR code to go for calendar is available).</li>
</ul>

<h4 id="version-14">Version 1.4</h4>

<ul>
  <li>provides some common icons of QR code.</li>
  <li>customize finder pattern.</li>
  <li>fix bugs</li>
</ul>

<h4 id="version-13">Version 1.3</h4>

<ul>
  <li>support Apple Watch to show QR code</li>
  <li>move favourite code list to “My” tab.</li>
  <li>new feature: QR Code to go. Press “Go~” button at QR code image back you can send SMS, connect Wifi or link to Map via QR code.</li>
  <li>fix bugs</li>
</ul>

<h4 id="version-12">Version 1.2</h4>

<ul>
  <li>support barcode (max 20 code in favourite list)<br />
  QRCobot also provides a medium Widget. Dragging several widgets in <strong>Smart Stack</strong> is better.</li>
  <li>add high brightness code display</li>
  <li>add delete button on code display page</li>
  <li>new figure for QRCobot</li>
  <li>fix bugs</li>
</ul>

<h4 id="version-11">Version 1.1</h4>

<ul>
  <li>support Chinese Simplified &amp; German.</li>
  <li>add 4 new types of QR code content, with raw text, Wifi, SMS and location.</li>
  <li>fix bugs.</li>
</ul>

<h3 id="requirement">Requirement</h3>

<p>iOS 14.0 +</p>

<h3 id="copyright">CopyRight</h3>

<p>QRCobot CopyRight © 2021 Bo Liu</p>

<hr />

<h2 id="中文">中文</h2>

<h3 id="什么是qrcobot">什么是QRCobot？</h3>

<p><strong>QRCobot</strong>是一个卓越的二维码、条形码管理工具。用户可以轻松的制作自己心仪的二维码和条形码，并且分享给他人。收藏的二维码可以在iOS小组件中被展示，扫码变得更加便捷。</p>

<h3 id="如何使用">如何使用？</h3>

<ol>
  <li>输入二维码的内容，例如网址：<br />
 <img src="/assets/img/images/qrcobot_1_2.jpeg" alt="" /></li>
  <li>选择一个风格，如Instagram：<br />
 <img src="/assets/img/images/qrcobot_2_2z.jpeg" alt="" /><br />
 或者选择自定义。<br />
 <img src="/assets/img/images/qrcobot_3_3z.jpeg" alt="" /><br />
 你便获得了你个人的二维码！<br />
 <img src="/assets/img/images/qrcobot_4_5.jpeg" alt="" /></li>
  <li>你可以通过点击二维码图片下面第一个按钮来改变二维码的容错等级。<br />
 <img src="/assets/img/images/qrcobot_5z.jpeg" alt="" /></li>
  <li>如果你想分享二维码或者保存至相册，点击二维码图片下方的分享按钮（第二个按钮）。</li>
  <li>小组件是iOS14以上版本支持的特性，QRCobot也支持小组件功能。</li>
</ol>

<ul>
  <li>首先，点击心形按钮来收藏当前生成的二维码，并将其命名。二维码就被保存在<strong>我的</strong>选项页里了。<br />
  <img src="/assets/img/images/qrcobot_10_1z.jpeg" alt="" /><br />
  你也可以在下个页面查看收藏的条形码。</li>
  <li>第二步，在手机的主界面添加一个QRCobot小组件。应用提供了三种二维码小组件尺寸和中等尺寸的条形码小组件。<br />
  <img src="/assets/img/images/qrcobot_7_1z.jpeg" alt="" /></li>
  <li>第三步，长按小组件，点击<strong>编辑小组件</strong>来选择一个你收藏列表中的二维码。<br />
  <img src="/assets/img/images/qrcobot_8z.jpeg" alt="" /></li>
  <li>现在，二维码小组件可以完美的展现在你的手机里啦~<br />
  <img src="/assets/img/images/qrcobot_9.jpeg" alt="" /></li>
  <li>从1.2版本开始，QRCobot支持条形码的生成和小组件。<br />
  <img src="/assets/img/images/qrcobot_11_1z.jpeg" alt="" /><br />
  你可以添加一些中等尺寸的条形码小组件到你的手机上，并将拖拽他们然后叠放。他们会合并于一个<strong>智能叠放</strong>中，这可以更好的帮助你展示和切换他们。<br />
  <img src="/assets/img/images/barcodewidget_stack.jpeg" alt="" /></li>
  <li>从1.6版本开始，当你分享二维码时，你可以自定义你的二维码外框。<br />
  <img src="/assets/img/images/qrcobot_12_1z.jpeg" alt="" /><br />
  你可以左右横滑来切换外框。如果你不需要外框，可以关闭下面<strong>带外框</strong>的开关。</li>
</ul>

<h3 id="下载qrcobot">下载QRCobot</h3>

<p>你可以在App Store中搜索<strong>QRCobot</strong>，或者点击<a href="https://apps.apple.com/cn/app/qrcobot/id1590006394?l=en">这里</a>下载。</p>

<h3 id="更新列表">更新列表</h3>

<h4 id="20版本">2.0版本</h4>
<ul>
  <li>支持vCard格式二维码</li>
  <li>修复bug</li>
</ul>

<h4 id="19版本">1.9版本</h4>
<ul>
  <li>兼容iPad</li>
  <li>支持从文件选择图标和水印</li>
</ul>

<h4 id="18版本">1.8版本</h4>

<ul>
  <li>增加快速网址输入。支持http, https, Youtube, Bilibili, Instagram, Facebook, Whatsapp</li>
  <li>支持切换icon，加入圣诞icon</li>
</ul>

<h4 id="17版本">1.7版本</h4>

<ul>
  <li>修复bug：条形码太大导致小组件无法加载<br />
  如果你的条形码小组件无法加载，你需要删除1.5版本之后生成的条形码，再用最新的版本重新将他们添加。</li>
</ul>

<h4 id="16版本">1.6版本</h4>

<ul>
  <li>支持分享二维码时带有外框</li>
  <li>全新的UI设计</li>
</ul>

<h4 id="15版本">1.5版本</h4>

<ul>
  <li>支持code128编码的条形码</li>
  <li>支持日历格式的二维码（可以通过Go~功能添加到系统日历）</li>
</ul>

<h4 id="14版本">1.4版本</h4>

<ul>
  <li>提供了一些二维码的通用图标</li>
  <li>可以自定义二维码定位区</li>
  <li>修复bugs</li>
</ul>

<h4 id="13版本">1.3版本</h4>

<ul>
  <li>支持Apple Watch展示收藏的二维码</li>
  <li>将收藏的二维码列表移到<strong>我的</strong>选项中</li>
  <li>新特性：Go~。点击二维码背面的<strong>Go~</strong>按钮，你可以通过二维码发送短信、连接Wifi或者跳转地图应用。</li>
  <li>修复bugs。</li>
</ul>

<h4 id="12版本">1.2版本</h4>

<ul>
  <li>支持条形码（最多收藏20个）。条形码也支持中等尺寸的小组件。将几个小组件拖拽到<strong>智能叠放</strong>里更好用。</li>
  <li>在展示二维码时提供高亮模式。</li>
  <li>在展示页面加入删除按钮。</li>
  <li>QRCobot机器人模型</li>
  <li>修复bugs</li>
</ul>

<h4 id="11版本">1.1版本</h4>

<ul>
  <li>支持简体中文和德语</li>
  <li>加入4中全新的二维码内容，包括纯文本、Wifi、短信、位置。</li>
  <li>修复bugs。</li>
</ul>

<h3 id="系统要求">系统要求</h3>

<p>支持iOS 14.0以上</p>

<h3 id="版权">版权</h3>

<p>QRCobot CopyRight © 2021 Bo Liu</p>]]></content><author><name></name></author><category term="iOS App" /><category term="Swift" /><category term="SwiftUI" /><category term="iOS App" /><summary type="html"><![CDATA[QRCobot is an extraordinary utility for QR & Bar code. Users can easily create QR & Bar codes that they want, and share them with others. The iOS widgets can show the favourite QR codes on Home screen, which helps users conveniently scan them.]]></summary></entry><entry><title type="html">JLConsoleLog</title><link href="https://www.jacklandrin.com/ios%20sdk/2020/04/28/jlconsolelog.html" rel="alternate" type="text/html" title="JLConsoleLog" /><published>2020-04-28T00:00:00+00:00</published><updated>2020-04-28T00:00:00+00:00</updated><id>https://www.jacklandrin.com/ios%20sdk/2020/04/28/jlconsolelog</id><content type="html" xml:base="https://www.jacklandrin.com/ios%20sdk/2020/04/28/jlconsolelog.html"><![CDATA[<h2 id="what-is-jlconsolelog">What is JLConsoleLog?</h2>

<p><strong>JLConsoleLog</strong> is an awesome tool In-App to help swift developer log information in both development and production environment. You won’t miss any key and useful logs about the bugs in non-debug mode. You also can integrate it in your project’s backdoor toolkit, it will help you solve vital issues.</p>

<h2 id="how-to-operate-it">How to operate it?</h2>

<p>JLConsoleLog supports three types of style (display mode) – <strong>Floating</strong>, <strong>Bubble</strong> and <strong>FullScreen</strong></p>

<p><img src="/assets/img/images/IMG_4730.png" alt="Floating" /></p>

<p><img src="/assets/img/images/IMG_4733.png" alt="Bubble" /></p>

<p><img src="/assets/img/images/IMG_4731.png" alt="FullScreen" /></p>

<p>There are four buttons on the option view of floating mode. The first button is setting button where you can clear all logs from this console, filter categories and levels. The second one is for switching between floating and fullscreen mode. If the third one is pressed, the console will be a translucent bubble that only displays warning and error count. The last one is close button.</p>

<p>The floating console could become translucent automatically after 5s, if you don’t touch it. Additionally, you can drag floating console and bubble to anywhere to avoid disturb you.</p>

<p>While you tap a log cell, you can enter the detail page of log.</p>

<p><img src="/assets/img/images/IMG_4734.png" alt="" /></p>

<hr />

<p>Performance monitor is a new function. You can invoke a monitor chart from bubble button now.</p>

<p><img src="/assets/img/images/IMG_4762.png" alt="" /></p>

<h2 id="how-to-use-it-in-your-project">How to use it in your project?</h2>

<p>The <strong>JLConsoleController</strong> is the console’s controller opened for developers. It contains a shared instance. You could set <strong>style</strong> and <strong>logEnabled</strong> via it. While you set its style (display mode), the console will immediately show in terms of you given. Like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if JLConsoleController.shared.style == .Hidden {
     JLConsoleController.shared.style = .Floating //show console in floating fashion
        } else {
    JLConsoleController.shared.style = .Hidden //hide console
        }
</code></pre></div></div>

<p>If <strong>logEnabled</strong> is true, the console will collect log data, vice verse.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>JLConsoleController.shared.logEnabled = true
</code></pre></div></div>

<p>A series functions are offered to log.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func JLLevelLog(level: JLConsoleLogLevel, category: JLConsoleLogCategory, hasFollowingAction:Bool = false, needPrint:Bool = false, contextData:Dictionary&lt;String,Any&gt; , formats: String...)

func JLVerboseLog( category: JLConsoleLogCategory, hasFollowingAction:Bool = false, needPrint:Bool = false, contextData:Dictionary&lt;String,Any&gt; , formats: String...) 

func JLDebugLog( category: JLConsoleLogCategory, hasFollowingAction:Bool = false, needPrint:Bool = false, contextData:Dictionary&lt;String,Any&gt; , formats: String...)

func JLInfoLog( category: JLConsoleLogCategory, hasFollowingAction:Bool = false, needPrint:Bool = false, contextData:Dictionary&lt;String,Any&gt; , formats: String...)

func JLWarningLog( category: JLConsoleLogCategory, hasFollowingAction:Bool = false, needPrint:Bool = false, contextData:Dictionary&lt;String,Any&gt; , formats: String...)

func JLErrorLog( category: JLConsoleLogCategory, hasFollowingAction:Bool = false, needPrint:Bool = false, contextData:Dictionary&lt;String,Any&gt; , formats: String...)
</code></pre></div></div>

<p>The <strong>JLConsoleLogLevel</strong> is an enum to sort by different levels. The numbers of warning and error are displayed on option view and bubble.</p>

<p>The <strong>JLConsoleLogCategory</strong> is your business category and is an alias of <strong>String</strong>. You can define your own categories met your demand, such as Video, TrackPage, Commodity Detail… If you need to filter your categories, you must register in this way in your code:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let SubPageTestLog:JLConsoleLogCategory = "com.consolelog.mybusiness" //declare a category

JLConsoleController.shared.register(newCategory: SubPageTestLog) //register it
</code></pre></div></div>

<p>The parameter, <strong>contextData</strong>, is a serializable Dictionary. The data will be shown on the detail page in Json.</p>

<p>The parameters, <strong>formats</strong>, is variadic parameters of String. The <strong>first value</strong> will be shown on the cell’s title in console.</p>

<p>If <strong>needPrint</strong> equals true, the log information will print in your Xcode console in Debug environment.</p>

<p>Otherwise, JLConsoleController provides a <strong>followingAction</strong> to operate other actions when you finish logging. For example, you can send a track point log to statistics server such as <em>Firebase</em> in followingAction closure. Meanwhile, please don’t forget to set <strong>hasFollowingAction</strong> as true while you log.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>JLErrorLog(category: SubPageTestLog, hasFollowingAction: true ,needPrint: true, contextData: ["test":5], formats: "Error!",#function,String(#line))
</code></pre></div></div>

<p>This is an error log example.</p>

<hr />

<h4 id="performance-monitor">Performance Monitor</h4>

<p>JLConsoleLog provides a performance monitor. You can add these to turn on it.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>JLConsoleController.shared.performanceMonitable = true
</code></pre></div></div>

<p>The git address is <a href="https://github.com/jacklandrin/JLConsoleLog">https://github.com/jacklandrin/JLConsoleLog</a></p>

<h2 id="requirement">Requirement</h2>

<ul>
  <li>iOS 12</li>
  <li>Swift 5.2</li>
  <li>Xcode 11</li>
</ul>

<h2 id="reference">Reference</h2>

<p><a href="https://github.com/woshiccm/PerformanceMonitor">PerformanceMonitor</a></p>]]></content><author><name></name></author><category term="iOS SDK" /><category term="Swift" /><category term="iOS SDK" /><summary type="html"><![CDATA[JLConsoleLog is an awesome tool In-App to help swift developer log information in both development and production environment. You won't miss any key and useful logs about the bugs in non-debug mode. You also can integrate it in your project's backdoor toolkit, it will help you solve vital issues.]]></summary></entry><entry><title type="html">Simple Talk about - MVVM pattern</title><link href="https://www.jacklandrin.com/programming/2020/04/15/simple-talk-about-mvvm-pattern.html" rel="alternate" type="text/html" title="Simple Talk about - MVVM pattern" /><published>2020-04-15T00:00:00+00:00</published><updated>2020-04-15T00:00:00+00:00</updated><id>https://www.jacklandrin.com/programming/2020/04/15/simple-talk-about-mvvm-pattern</id><content type="html" xml:base="https://www.jacklandrin.com/programming/2020/04/15/simple-talk-about-mvvm-pattern.html"><![CDATA[<h2 id="personal-history-about-mvvm">Personal History about MVVM</h2>

<p>About a decade ago, I started to learn client app programming. The first framework that I met was Microsoft WPF. It had a very powerful developing approach that was MVVM. Microsoft provided a series of original syntax and toolkits to help developer implement a client app with MVVM. You don’t only write a WPF client using it, but also Sliverlight and Windows Phone app. So, a C# programmer could easily develop client in different platforms with a same framework. A new markup language, XAML, which was offered by Microsoft, was used as describing UI; C# or other .Net programming languages could be responsible of business logic code. Although Sliverlight and Windows Phone have come down nowadays, the story of MVVM is just beginning.</p>

<p><img src="/assets/img/images/2C943AF5-C8F5-4465-A1EC-D592C7C6FF94.png" alt="Silverlight" /></p>

<p>Because the ecosystem of Windows Phone didn’t survive and grow, I transferred to be an iOS developer six years ago. However, I felt that the developing environment of iOS was primitive - Objective-C is a 50-year-old language and using Xib and Storyboard to describe View layer is a puerile way compared with XAML. The Storyboard will be chaotic and often stuck, while there are a lot of pages that have complex logical relations in a project. Most my colleagues, therefore, develop UI component using programming way rather than Xib and Storyboard, but it could make that the ViewController takes charge of both View and Controller in MVC architecture and it maybe have massive codes in a class. As well as a ViewController needs to maintain the correlation between Models and Views, you must write many equal symbol in your code to keep them update, so it has become a big pool coupling much logic. The samiliar problems also exist in other platforms, which makes MVVM appear in people’s vision again.</p>

<p>In the following years, vue.js, Rx, flutter and SwiftUI all make effort to popularize MVVM. <img src="/assets/img/images/E6301C12-A1BA-4E5C-AA3F-6091A3BCA7F4.jpeg" alt="Flutter" /></p>

<h2 id="what-is-mvvm">What is MVVM?</h2>

<p>There are three layers in a MVVM architecture - View, ViewModel and Model. Most articles explain the relation of layers referencing this following diagram: <img src="/assets/img/images/D98BE215-15C7-499F-B381-F30B9B1D0A4E.png" alt="MVVM" /></p>

<ul>
  <li><strong>View</strong>: describing the UI of components or pages. The information and animation is shown and interaction with users is offered in this layer. It’s merely binded with ViewModel, which means ViewModel is View’s unique data source - the data includes text, size, image etc. - and the users’ operations also trigger the event of ViewModel. So, View only does two things, declaring components and appointing their data source and event.</li>
  <li><strong>ViewModel</strong>: It has two important things, property and event. The ViewModel properties are always dynamic data, which means they are often changed. So, the setter method of property needs to be written. While a property is set, such as due to network response in Model layer, a signal will be published to an observer that is used to refresh View’s relevent data automatically. Besides, ViewModel can be invoked by View’s events, such as gesture, toggle, pressing button etc. These events also can change ViewModel’s properties . Meanwhile, ViewModel will update data of Model. Thus, Model was decoupled completely from ViewModel.</li>
  <li><strong>Model</strong>: It’s abstract model for non-UI data, though perhaps some fields are as same as ViewModel. Moreover, some foundemental data processing and business logic could be written in this layer, such as network request, database operation, communication with keep-alive server.</li>
</ul>

<p>This architecture has many advantages for from-end development.</p>

<ul>
  <li>It separates the UI and business logic. Designers could directly import their works to project as View layer from some design software like Sketch, since independent View layer doesn’t demand any programming logic. After that, the programmer just need to set the data source from ViewModel in View. Designer’s and developer’s job is distincted clearly in the structure of organisition, which they only pay attention to own fields in a software engineering. In order to archieve this, Microsoft published Blend for designers in its MVVM framework, which is used to design WPF, Windows Phone’s UI, product animation like Adobe Flash and event debug the app. <img src="/assets/img/images/CC54BA97-2DFE-40C9-812F-06B10C7DBF43.png" alt="Blend" /></li>
  <li>ViewModel helps View and Model decouple. You don’t longer pair complex relations between View and Model in a very large Controller. Modifying any layer won’t influence maginificantly each other. As well as ViewModel and Model could be reused in different project whose logic is similar, event you can easily redevelop a Mac application, if you have had a same business iOS app.</li>
  <li>The observer pattern provides automatic way to bind data, which reduces much workload of development and possibility of bugs. The developer will care data and workflow more rather than how to control View.</li>
</ul>

<p>Nevertheless, there are serval disadvantages of MVVM:</p>

<ul>
  <li>It’s hard to learn for beginners, especially the framework is not provided originally such as RxSwift. Although I have developed Microsoft’s MVVM framework for many years, the RxSwift document still make me boring. I think developing a framework that is easy to understand based on UIKit is a hard work. Fortunately, flutter and SwiftUI are published.</li>
</ul>

<p><img src="/assets/img/images/F4878A97-1EA4-4525-AC62-F194BA0828E9.jpeg" alt="RxSwift" /></p>

<ul>
  <li>It has a bit of complexity of binding data for some project. In some small projects, it actually brings more workload in binding, and some tiny groups don’t have a lot of memebers, so the way of distinctive View and ViewModel is unnecessary.</li>
  <li>The observers maintain a huge hashtable containing observable objects, which increases more memory consumption.</li>
</ul>

<p>In conclusion, whether chosing MVVM in your project or not, is dependent on many factors. Though these backwards will impact some people’s decision, I prefer to use it because of its actractive features. Flutter and SwiftUI both are good options for client developers.</p>]]></content><author><name></name></author><category term="programming" /><category term="programming" /><summary type="html"><![CDATA[bout a decade ago, I started to learn client app programming. The first framework that I met was Microsoft WPF. It had a very powerful developing approach that was MVVM. Microsoft provided a series of original syntax and toolkits to help developer implement a client app with MVVM. You don’t only write a WPF client using it, but also Sliverlight and Windows Phone app.]]></summary></entry><entry><title type="html">ChalkSeven</title><link href="https://www.jacklandrin.com/game/ios%20app/2020/04/13/chalkseven.html" rel="alternate" type="text/html" title="ChalkSeven" /><published>2020-04-13T00:00:00+00:00</published><updated>2020-04-13T00:00:00+00:00</updated><id>https://www.jacklandrin.com/game/ios%20app/2020/04/13/chalkseven</id><content type="html" xml:base="https://www.jacklandrin.com/game/ios%20app/2020/04/13/chalkseven.html"><![CDATA[<p><img src="/assets/img/images/icon-180.png" alt="" /></p>

<h2 id="what-is-chalkseven">What is ChalkSeven?</h2>

<p><strong>ChalkSeven</strong> is a drop 7 game developed with SwiftUI. You can drop down a ball with number to a proper location into the grid. If a ball’s number equals the count of continuous balls in its row or column, the ball will explode. Besides, there are two special balls, <strong>solid ball</strong> and <strong>pending ball</strong>. If a solid ball nearby a ball exploding, it’ll be a pending ball; if a pending ball nearby a ball exploding, it’ll be a normal ball with a number.</p>

<p>In every level, you have 20 opportunities to drop balls. When you finish your all balls, a row of solid balls will emerge from the bottom to thrust up the balls in the grid. If these balls could be pushed out of the grid, the game will be over.</p>

<p>Have fun!</p>

<p><img src="/assets/img/images/chalkball_demo.png" alt="" /></p>

<p>The git address is <a href="https://github.com/jacklandrin/ChalkSeven">https://github.com/jacklandrin/ChalkSeven</a></p>

<h2 id="references">References</h2>

<p>Thank Anh, mixkit and freesound for effect sounds. The background music is created by Anh. The other effect sounds come from these sources: <a href="https://mixkit.co/free-sound-effects/game/?page=2">https://mixkit.co/free-sound-effects/game/?page=2</a> <a href="https://freesound.org/people/cameronmusic/sounds/138410/">https://freesound.org/people/cameronmusic/sounds/138410/</a> <a href="https://freesound.org/people/ash_rez/sounds/518887/">https://freesound.org/people/ash_rez/sounds/518887/</a> <a href="https://freesound.org/people/Mr._Fritz_/sounds/544015/">https://freesound.org/people/Mr._Fritz_/sounds/544015/</a></p>

<h2 id="requirement">Requirement</h2>

<ul>
  <li>iOS 13</li>
  <li>Swift 5.2</li>
  <li>Xcode 11</li>
</ul>]]></content><author><name></name></author><category term="game" /><category term="iOS App" /><category term="Swift" /><category term="SwiftUI" /><category term="game" /><category term="iOS App" /><summary type="html"><![CDATA[ChalkSeven is a drop 7 game developed with SwiftUI. You can drop down a ball with number to a proper location into the grid. If a ball's number equals the count of continuous balls in its row or column, the ball will explode. Besides, there are two special balls, solid ball and pending ball. If a solid ball nearby a ball exploding, it'll be a pending ball; if a pending ball nearby a ball exploding, it'll be a normal ball with a number.]]></summary></entry><entry><title type="html">JLQuizCard</title><link href="https://www.jacklandrin.com/ios%20app/2020/04/10/jlquizcard.html" rel="alternate" type="text/html" title="JLQuizCard" /><published>2020-04-10T00:00:00+00:00</published><updated>2020-04-10T00:00:00+00:00</updated><id>https://www.jacklandrin.com/ios%20app/2020/04/10/jlquizcard</id><content type="html" xml:base="https://www.jacklandrin.com/ios%20app/2020/04/10/jlquizcard.html"><![CDATA[<p><img src="http://www.jacklandrin.com/wp-content/uploads/2021/12/quiz_card_180.png" alt="" /></p>
<h2 id="app-store">App Store</h2>
<p>https://apps.apple.com/us/app/wallcard/id1601311095</p>

<h2 id="what-is-jlquizcard">What is JLQuizCard?</h2>
<p><strong>JLQuizCard</strong> is little Anki card app developed with SwiftUI. You can swipe the card to shift questions, and edit your questions and answers. The flippable effect derives from an Apple watchkit sample, PopQuiz.</p>
<p align="center">
<img alt="Sits in the status bar" src="https://www.jacklandrin.com/wp-content/uploads/2021/12/quizcard_main.png" width="40%" align="center" />
</p>

<p>28.03.2021 Update:
Now, you can import batch card from CSV file (The head is <strong>question, answer, example, group</strong>). You also can divid cards into different groups. Beside, the card data could store in Core Data and sync among your devices by iCloud.</p>

<p align="center">
<img alt="Sits in the status bar" src="https://www.jacklandrin.com/wp-content/uploads/2021/12/quizcard_wallpaper.png" width="40%" align="center" />
</p>

<p>20.12.2012 Update:</p>
<ul>
  <li>new UI</li>
  <li>You can set QuizCard as your wallpaper on lock screen via <strong>Shortcuts</strong></li>
</ul>

<p>The git address is <a href="https://github.com/jacklandrin/JLQuizCard">https://github.com/jacklandrin/JLQuizCard</a></p>
<h2 id="requirement">Requirement</h2>
<ul>
  <li>iOS 14 *</li>
  <li>Swift 5.5</li>
  <li>Xcode 13</li>
</ul>]]></content><author><name></name></author><category term="iOS App" /><category term="Swift" /><category term="SwiftUI" /><category term="iOS App" /><summary type="html"><![CDATA[JLQuizCard is little Anki card app developed with SwiftUI. You can swipe the card to shift questions, and edit your questions and answers.]]></summary></entry><entry><title type="html">JLPinBubble Mergeable PinBubble with SwiftUI</title><link href="https://www.jacklandrin.com/ios%20sdk/2020/04/04/jlpinbubble-mergeable-pinbubble-with-swiftui.html" rel="alternate" type="text/html" title="JLPinBubble Mergeable PinBubble with SwiftUI" /><published>2020-04-04T00:00:00+00:00</published><updated>2020-04-04T00:00:00+00:00</updated><id>https://www.jacklandrin.com/ios%20sdk/2020/04/04/jlpinbubble-mergeable-pinbubble-with-swiftui</id><content type="html" xml:base="https://www.jacklandrin.com/ios%20sdk/2020/04/04/jlpinbubble-mergeable-pinbubble-with-swiftui.html"><![CDATA[<h2 id="what-is-jlpinbubble">What is JLPinBubble?</h2>

<p><strong>JPinBubble</strong> is a control that contains a series of pin bubbles which can be merged and divided when they are closed to each other. It could be applied to map apps as indicator of specific locations. As users pinch the screen to zoom the map in , the two overlapped bubbles will merge into one, vice versa.</p>

<p>The git address is <a href="https://github.com/jacklandrin/JLPinBubble">https://github.com/jacklandrin/JLPinBubble</a></p>

<h2 id="requirement">Requirement</h2>

<ul>
  <li>iOS 13</li>
  <li>Swift 5.2</li>
  <li>Xcode 11</li>
</ul>

<h2 id="how-to-use-it">How to use it?</h2>

<p><strong>JLBubbleCanvas</strong> should be declared in your View’s body. You can define the bubble’s tap action in the initial function, and it has a viewbuilder that you can add the background view on the canvas. For example:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>JLBubbleCanvas(bubbleTapAction: {bubble in
            ...tapAction
        }){
            Image("image name")
        }
</code></pre></div></div>

<p><strong>JLBubbleCanvasViewModel</strong> is the view model of JLBubbleCanvas. It declares the bubbles array, bubble’s size, the switch of showing number and the background image’s name. In addition, serval functions that control merge and division are defined in this class. There are two functions provided for the View:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func judgetOverlap(_ scale:CGFloat)
func judgeDivided(_ scale:CGFloat)
</code></pre></div></div>

<p><strong>JLBubbleViewModel</strong> is the view model of <strong>JLBubbleView</strong> that is used for showing a pin bubble. A pin bubble contains a image as bubble’s background picture, a text, a num and its position information. While two bubbles merge into a new bubble, the new one’s subBubble will put them into itself in case they could be restored.</p>]]></content><author><name></name></author><category term="iOS SDK" /><category term="Swift" /><category term="SwiftUI" /><category term="iOS SDK" /><summary type="html"><![CDATA[JPinBubble is a control that contains a series of pin bubbles which can be merged and divided when they are closed to each other. It could be applied to map apps as indicator of specific locations. As users pinch the screen to zoom the map in , the two overlapped bubbles will merge into one, vice versa.]]></summary></entry></feed>