iOSアップデートで突然消えた神GPSアプリ、自作を諦めかけた僕がSafariで奇跡を起こした話 ※プロンプト付 ※プログラム付
ある朝突然奪われた、僕の快適な日常と絶望
愛用していたアプリが、ある朝突然消えました。
OSのアップデートひとつで、長年寄り添った相棒があっけなく動かなくなる絶望。
あのアラート音が鳴らない日常は、まるで味のしないぬるいスープを飲まされているような不快感でした。
日常の小さな快適さが奪われた瞬間、胸の奥がギュッと締め付けられるような虚無感に襲われました。
アプリが作れなくても、Safariの力で奇跡は起きるのか
プログラミングの専門知識もない自分が、理想のツールを取り戻すことなんてできるのか。
画面に並ぶエラーの山を前に、一度は諦めそうになりました。
しかし、毎日の不便さを指をくわえて見過ごすわけにはいきません。
そこで目をつけたのが、iPhoneのSafariで動くブックマークレットという仕組みでした。
アプリを作れなくても、ブラウザの力を借りれば自分だけのツールを再現できるはずです。
マップ上にピンを立て、その場所に近づいたら通知を飛ばす機能の開発が始まりました。
冷たい画面からの拒絶、そして背筋がゾクッとした解決の瞬間
一筋縄ではいかない開発の壁と、奇跡の瞬間について紹介します。
地図は表示されるのに、タップしてもピンが立たないもどかしさ。
画面をいくら叩いても反応しない冷たいガラス越しの拒絶に、何度も投げ出しそうになりました。
原因はブラウザ特有の制限で、直接入力画面を出すのをやめ自作の枠を浮かび上がらせる方式で解決しました。
硬かった画面が嘘のように素直に反応し、自分の手で打ち込んだピンが地図に浮かび上がりました。
アプリと違ってバックグラウンドやスリープ中には動かず、画面を開いている間しか機能しないという小さな制約はあります。
それでも、画面の向こうで青い現在地がピンに近づきアラートが鳴った瞬間、背筋がゾクッとするほどの感動が走りました。
諦めかけたアイデアが形になる、自分専用ツールの誕生
今回作成した仕組みと、実現できた機能の一覧です。
地図上の好きな場所をタップして簡単にピンを設置
ピンごとの警戒半径を自由に変更可能
画面を開いて移動中にエリア進入時アラートを表示
現在地を自動で追いかけるリアルタイム追従機能
入力エラーを防ぐ独自フォームの採用
欲しい機能がないなら、自分の手で作り出す時代です。
日常の小さなイライラを諦めず、知恵をしぼって解決できたときの達成感は格別です。
諦めかけたアイデアも、視点を変えれば必ず形になります。

以上いかがでしたでしょうか?
もし共感したら、コメントやスキを押してくれると励みになります。
この記事が少しでもお役に立てたら、今後の活動の励みになりますので、広告を見ていただいたり、チップいただけると嬉しいです! なお、チップは全て地元NPOへ寄付させていただきます。
#iOSアップデート #iPhone裏技 #ブックマークレット #神アプリ #位置情報 #自作アプリ #Safari活用 #便利ツール #業務効率化 #プログラミング初心者
#悪用厳禁 #失敗から学ぶ
※ブックマークを編集してURLの箇所に下記コードをコピーして使えます。
javascript:(function(){if(window.__osmAlertApp)return;window.__osmAlertApp=!0;var c=document.createElement("link");c.rel="stylesheet",c.href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css",document.head.appendChild(c);var d=document.createElement("script");d.src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js",d.onload=function(){var a=document.createElement("div");a.style="position:fixed;top:0;left:0;width:100vw;height:100dvh;z-index:999999;background:#fff;display:flex;flex-direction:column;font-family:-apple-system,sans-serif;",a.innerHTML='<div id="b-map" style="flex:1;width:100%;height:100%;"></div><div style="height:130px;background:#f0f0f0;padding:8px;overflow-y:auto;border-top:2px solid #0078d4;font-size:12px;"><div style="display:flex;justify-content:space-between;margin-bottom:6px;"><button id="b-close" style="padding:4px 8px;">✕ 閉じる</button><button id="b-follow" style="padding:4px 8px;background:#0078d4;color:#fff;border:none;border-radius:4px;">追従: オフ</button></div><div id="b-list"></div></div><div id="b-dialog" style="display:none;position:fixed;top:0;left:0;width:100vw;height:100dvh;background:rgba(0,0,0,0.5);z-index:1000000;justify-content:center;align-items:center;"><div style="background:#fff;padding:16px;border-radius:8px;width:280px;box-shadow:0 4px 12px rgba(0,0,0,0.3);"><h4 style="margin:0 0 10px 0;color:#0078d4;">ピンの追加</h4><label style="font-size:12px;display:block;margin-bottom:4px;">名称</label><input type="text" id="b-input-name" value="地点" style="width:100%;padding:6px;margin-bottom:10px;box-sizing:border-box;"><label style="font-size:12px;display:block;margin-bottom:4px;">警戒半径 (m)</label><input type="number" id="b-input-r" value="100" style="width:100%;padding:6px;margin-bottom:12px;box-sizing:border-box;"><div style="display:flex;gap:8px;"><button id="b-cancel" style="flex:1;padding:8px;background:#8a8886;color:#fff;border:none;border-radius:4px;">キャンセル</button><button id="b-save" style="flex:1;padding:8px;background:#0078d4;color:#fff;border:none;border-radius:4px;font-weight:bold;">保存</button></div></div></div>',document.body.appendChild(a),document.getElementById("b-close").onclick=function(){document.body.removeChild(a),delete window.__osmAlertApp};var b=L.map("b-map",{tap:!1}).setView([34.7037,137.7348],14);L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(b),setTimeout(function(){b.invalidateSize()},300);var e=JSON.parse(localStorage.getItem("bm_osm_pins")||"[]"),f=[],g=null,h=!1,i=null,j=null,k=null;function l(){localStorage.setItem("bm_osm_pins",JSON.stringify(e))}function m(){f.forEach(function(a){b.removeLayer(a)}),f=[];var a=document.getElementById("b-list");a.innerHTML=e.length?"":"地図上をタップしてピンを追加",e.forEach(function(c,d){var g=L.marker([c.lat,c.lng]).addTo(b).bindPopup(c.name),h=L.circle([c.lat,c.lng],{color:"red",radius:c.r}).addTo(b);f.push(g,h);var i=document.createElement("div");i.style="display:flex;justify-content:space-between;align-items:center;background:#fff;margin-bottom:4px;padding:4px 8px;border-radius:4px;",i.innerHTML="<span><b>"+c.name+"</b> ("+c.r+"m)</span>";var j=document.createElement("button");j.textContent="削除",j.style="background:#d13438;color:#fff;border:none;padding:2px 6px;border-radius:3px;",j.onclick=function(){e.splice(d,1),l(),m()},i.appendChild(j),a.appendChild(i)})}m(),b.on("click",function(a){k=a.latlng,document.getElementById("b-dialog").style.display="flex"}),document.getElementById("b-cancel").onclick=function(){document.getElementById("b-dialog").style.display="none",k=null},document.getElementById("b-save").onclick=function(){if(k){var a=document.getElementById("b-input-name").value.trim()||"地点",b=parseFloat(document.getElementById("b-input-r").value)||100;e.push({lat:k.lat,lng:k.lng,name:a,r:b,alerted:!1}),l(),m(),document.getElementById("b-dialog").style.display="none",k=null}};var n=document.getElementById("b-follow");n.onclick=function(){h=!h,n.textContent="追従: "+(h?"オン":"オフ"),h&&i&&b.panTo([i,j])},navigator.geolocation&&navigator.geolocation.watchPosition(function(a){if(i=a.coords.latitude,j=a.coords.longitude,g&&b.removeLayer(g),g=L.circleMarker([i,j],{color:"#0078d4",radius:7}).addTo(b),h&&b.panTo([i,j]),e.forEach(function(a){var c;c=6371000*2*Math.atan2(Math.sqrt(Math.sin((a.lat-i)*Math.PI/360)**2+Math.cos(i*Math.PI/180)*Math.cos(a.lat*Math.PI/180)*Math.sin((a.lng-j)*Math.PI/360)**2),Math.sqrt(1-(Math.sin((a.lat-i)*Math.PI/360)**2+Math.cos(i*Math.PI/180)*Math.cos(a.lat*Math.PI/180)*Math.sin((a.lng-j)*Math.PI/360)**2)));c<=a.r&&!a.alerted?(alert("【接近アラート】\n「"+a.name+"」の近く("+Math.round(c)+"m)に到達しました!"),a.alerted=!0,l()):c>a.r&&a.alerted&&(a.alerted=!1,l())}),!i)return},null,{enableHighAccuracy:!0})},document.head.appendChild(d)})();<参考プロンプト>
上記のやりとりを元にして、ふと以前使っていたエリア内に入ったら通知してくれるアプリがiOSアプデに伴って無くなっていたので、それっぽいのって作れないか模索して、そこそこ高機能なものが出来た時点で、iPhoneのブックマークレットに落とし込めないかをトライしてみたというストーリーで、次の点を考慮してnote向けの記事を書いてください。
①noteで注目を集めるキーワードを織り交ぜる。
②冒頭に共感を誘うような強めのネガティブ要素もしっかり入れる。
③総じて「共感→問題提起→解決策→感動」の構成とする。
④五感を刺激する「シズル」を織り込む。
⑤身近なものや日常のことに例えること。
⑥章に分けて、各章のタイトルは共感を呼ぶ刺激的な内容で大きい文字とする。
⑦記事のタイトルも作ってください。切り口としては、失敗したけど解決出来た風で共感が持てて検索に掛かり易く、また4U法則を交えたものにする。
⑧表になる内容は、表は使わず箇条書きにする。
⑨ 記事の内容に沿うように、SEOに強いワードを入れてください。
⑩ 絵文字や特殊記号は使わないでください。
⑪視覚的な読みやすさを最優先してください。
⑫すべての文 の「。」の後に改行を入れ、その行(空行になるはずの行)に全角スペースを1つだけ入力し、さらに改行を入れてから、次の文を開始してください。
⑬文章をダラダラと繋げず、1文1文を短く区切って配置してください。
⑭記事全体で1000文字以内に収まる様にしてください。
記事が終わった後に下記の#文末テキストを挿入してください。
その後に続いて、noteでヒットしそうな記事内容と関連したハッシュタグも作ってください。ハッシュタグは改行せずに半角スペースで区切って横にならべてください。
#文末テキスト
以上いかがでしたでしょうか?
もし共感したら、コメントやスキを押してくれると励みになります。
この記事が少しでもお役に立てたら、今後の活動の励みになりますので、広告を見ていただいたり、チップいただけると嬉しいです!
なお、チップは全て地元NPOへ寄付させていただきます。
いいなと思ったら応援しよう!
ここまで読んでくださり、ありがとうございます。
静岡生まれの還暦オヤジ、「とりあえずやってみる」を合言葉に記事を書いています。
もし「ちょっと応援してやるか」と思っていただけたら、チップで励ましてもらえると次の“やってみる”の力になります😊