NetNewsWire/Frameworks/Account/AccountTests/Feedly/feedly-5-removefeedsandfolders/starred.json

1129 lines
257 KiB
JSON

{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"items": [
{
"originId": "com.sixcolors.931113_features_of_ios_13_files_improvements",
"fingerprint": "b321d04b",
"id": "Ai/HDbZBn/DqS4YSFb8RbnuS8su16El+mi83Mpt/WqQ=_16d88a4dca2:50e96:18991ffa",
"author": "Jason Snell",
"summary": {
"direction": "ltr",
"content": "<p><figure><img alt=\"\" src=\"https://sixcolors.com/images/content/2019/ios13-files-usb-key-6c.jpg\">\n<figcaption>Funny how something as basic as inserting a thumbdrive can feel like a colossal victory.</figcaption>\n</figure></p>\n<p>The Finder places files and folders at the center of the Mac, but on iOS, apps are at the center. Still, managing documents is a fact of life in many cases, and over the past few years Apple has been evolving the Files app to become a more full-featured file browser utility. In iOS 13, Files takes a huge step forward in numerous areas\u2026 though there\u2019s still more to be done.</p>\n<p>Perhaps most important is the simple fact that Files can now see destinations that aren\u2019t cloud services or other apps. You can add local SMB file servers to Files by tapping the ellipsis icon in the Browse pane and choosing Connect to Server, then entering the address of your SMB server. While you\u2019re connected, that server will appear in the Shared segment of the Browse pane. (Strangely, Files doesn\u2019t use Bonjour to detect nearby servers and display them, as Finder does.) I have a Mac mini on my home network that I use as a file server, and it\u2019s been a delight to access files on it, directly, from within Files and apps that use Apple\u2019s file interface.</p>\n<p><figure><img alt=\"\" src=\"https://sixcolors.com/images/content/2019/shortcuts-ios11-ipad-6c.jpg\">\n<figcaption>Browsing a local SMB server in column view, as you do.</figcaption>\n</figure></p>\n<p>USB drives are also supported. It\u2019s kind of hard to believe that I\u2019m celebrating USB disk access in late 2019, but here we are. You can attach USB drives to any device running iOS 13, but this feature certainly feels best when you plug a USB-C cable or thumbdrive directly into an iPad Pro. As an iPad Pro user, that\u2019s a moment that really makes the iPad Pro feel like it\u2019s been welcomed into the community of personal computers. And if you\u2019re someone who has ever been handed a thumbdrive by a colleague who expects you to access it on your iPad, well, now you can do that instead of sheepishly admitting that it\u2019s completely useless to you. I\u2019ve used this feature to attach my portable audio recorder directly to my iPad to import recordings, something I previously <a href=\"https://sixcolors.com/post/2017/12/transferring-sd-card-data-to-ios-fast/\">had to use a breakout box to accomplish</a>.</p>\n<p>You can even create new folders now. Yes. It\u2019s true. And there\u2019s a new Column View, which is an approach to file browsing that I\u2019ve never liked on macOS, but actually makes more sense to me on iOS for some reason.</p>\n<p><figure><img alt=\"shortcuts-ios11-iphone\" src=\"https://sixcolors.com/images/content/2019/shortcuts-ios11-iphone-6c.jpg\">\n<figcaption>Tap and hold to view everything you can do to a given file.</figcaption>\n</figure></p>\n<p>iOS 13 also lets users perform many more actions on files than ever before by tapping and holding on an icon to reveal a contextual menu. Among the actions found here are options to compress files into an archive, decompress zip files, edit tags, preview a file in Quick Look, and display an Info pane with detailed information about a file\u2019s attributes\u2014basically, the stuff you\u2019d expect from a file browser is mostly there. (It\u2019s a bit strange that you can\u2019t set items from Shortcuts to display directly in this contextual menu, as you can in the share sheets elsewhere on iOS 13. Instead, you have to tap and hold on a file, choose Share, and <em>then</em> pick a Shortcuts item.</p>\n<p>Files separates iOS storage into two buckets, On My iPad/iPhone and iCloud Drive. On My iPad is basically what you\u2019d consider \u201cthe hard drive\u201d on a Mac\u2014it\u2019s local storage that is not synced over the cloud. If you want to save a huge file on your iPad and not have it swamp your current connection in an attempt to sync all that data to the cloud, put it in On My iPad/iPhone. If you want it available everywhere, put it in iCloud Drive.</p>\n<p>Alas, not all is sunshine and roses in the land of iOS file access. Files is still a remarkably immature app. It sometimes fails to update file listings, frequently stalls out and provides me with a blank or incomplete listing, and, most frustratingly, the Save to Files extension for third-party apps fails to provide any feedback about the progress of a file transfer. That unreliability, combined with a slow file transfer to a remote server, leads to some pretty uncomfortable moments when you have no idea if your file is going to arrive or if the whole thing has failed silently.</p>\n<p>Apple\u2019s taken a few cues from the Mac in building up Files, so it\u2019s time to take a few more. Progress indicators are vital. Allowing the user to get a detailed view about what\u2019s transferring and how long it will take are must-have features, but when I try to save items within third-party apps, all I get is an endless spinner with no feedback. I realize this isn\u2019t an issue with the Files app itself\u2014it does show a little circular upload/download progress bar\u2014but it is an issue with Apple\u2019s greater approach to file transfers.</p>\n<p>Still, Files has come a long way. It has gone from being an iCloud Drive client app to a neither-fish-nor-fowl representation of Apple\u2019s ambivalence to file management on iOS to what it is today\u2014a pretty capable file browser that\u2019s still got plenty of room for improvement. Files in iOS 13 is a major upgrade\u2014I just hope Apple doesn\u2019t consider the job done.</p>"
},
"alternate": [
{
"href": "https://sixcolors.com/post/2019/10/13-features-of-ios-13-files-improvements/",
"type": "text/html"
}
],
"crawled": 1569955568802,
"title": "13 Features of iOS 13: Files improvements",
"published": 1569952320000,
"origin": {
"streamId": "feed/http://feedpress.me/sixcolors",
"htmlUrl": "https://www.sixcolors.com/",
"title": "Six Colors"
},
"unread": false,
"readTime": 4981,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815",
"label": "Macintosh"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572579193115
},
{
"originId": "tag:daringfireball.net,2019://1.36188",
"fingerprint": "ae19d945",
"id": "ZTHt7g74IlVC5A2IgEvcn/aop5teo99gzFaGU2TCGxs=_16e052937dc:173f1:d4506071",
"updated": 1572042321000,
"author": "John Gruber",
"summary": {
"direction": "ltr",
"content": "What\u2019s the point of having only two buttons and all that unused whitespace on the left side?"
},
"alternate": [
{
"href": "https://daringfireball.net/2019/10/mails_message_action_toolbar_in_ios_13",
"type": "text/html"
}
],
"crawled": 1572044617692,
"title": "\u2605 The Curious Design of Mail\u2019s Message Action Toolbar in iOS 13",
"published": 1572042320000,
"origin": {
"streamId": "feed/http://daringfireball.net/index.xml",
"htmlUrl": "https://daringfireball.net/",
"title": "Daring Fireball"
},
"content": {
"direction": "ltr",
"content": "<p><a href=\"https://www.nbcnews.com/tech/apple/iphone-update-leaves-apple-fans-fuming-over-deleted-emails-n1071591\">David Ingram, writing for NBC News</a>:</p>\n<blockquote>\n<p>Shannon Watts always replied to emails the same way: by touching\nthe reply icon, tucked in a familiar spot near the bottom right\ncorner of her iPhone. Then, one day a few weeks ago, the icon\nwasn\u2019t there\u2009\u2014\u2009and neither was the email. It was deleted by\naccident.</p>\n<p>It\u2019s happened dozens of times since, frustrating Watts and many\nother iPhone users who\u2019ve been tripped up by a minor change rolled\nout last month by Apple, a company renowned for its\nforward-thinking design.</p>\n<p>In the newest version of the iPhone email app, the trash icon is\nnow where the reply icon used to be. And they\u2019re too close\ntogether for some people.</p>\n</blockquote>\n<p>The change is perfectly illustrated and summarized <a href=\"https://twitter.com/chockenberry/status/1187461445186834434\">in this tweet by Craig Hockenberry</a>: </p>\n<blockquote>\n<p>Muscle memory is a bitch.</p>\n<p><img width=\"450\" src=\"https://daringfireball.net/misc/2019/10/chock-mail-toolbar.jpeg\"></p>\n</blockquote>\n<p>Things worth noting:</p>\n<ul>\n<li>You can long-press on the Trash icon to get an option to Archive instead.</li>\n<li>You can change the default from Trash to Archive in Settings \u2192 Passwords &amp; Accounts. Tap on an email account and navigate to Mail: Advanced, and you can change the default action for \u201cMove Discarded Messages Into:\u201d from Deleted Mailbox to Archive Mailbox.</li>\n<li>Trashing and Archiving are undoable actions. Just shake your iPhone or use the <a href=\"https://www.macworld.com/article/3410596/ios-13-and-ipados-13-how-to-use-the-new-gestures-for-cut-copy-paste-undo-and-redo.html\">new three-finger swipe gestures for Undo and Redo</a>. But as this NBC News article makes clear, most people don\u2019t know that Undo is pervasive system-wide on iOS.</li>\n</ul>\n<p>The new toolbar in iOS 13 Mail is just strange. The old toolbar had discrete buttons for Flag, Move, Trash/Archive, Reply, and New Message. Now it\u2019s just Trash and Reply, with all of the other functionality stashed in the new Reply action sheet, pictured here <a href=\"https://daringfireball.net/misc/2019/10/ios-13-reply-half.png\">half-height</a> and <a href=\"https://daringfireball.net/misc/2019/10/ios-13-reply-full.png\">full-height</a>. That new \u201cReply\u201d action sheet is really a \u201cDo Something With This Message\u201d sheet\u2009\u2014\u2009I\u2019m not sure what the icon for this should be, but the Reply icon seems like an odd choice. I know a few people who assumed that iOS 13 removed the ability to move messages to other mailboxes because the folder button was removed from the toolbar. They\u2009\u2014\u2009reasonably!\u2009\u2014\u2009never thought to look for it by tapping what clearly looks like the old familiar Reply icon.</p>\n<p>The Print command has long been stashed in the Reply action sheet\u2009\u2014\u2009so arguably it\u2019s always been more of a \u201cDo Something With This Message\u201d button than just a \u201cReply or Forward\u201d button. But the iOS 13 Mail toolbar takes this to an extreme. It\u2019s one thing to put new features (for which there\u2019s no room on the toolbar) in the Reply action sheet; it\u2019s another to move commands like Flag and Move that already had positions on the toolbar.</p>\n<p>I like the new \u201cDo Something With This Message\u201d action sheet in and of itself a lot\u2009\u2014\u2009it\u2019s an interesting design to fit more functionality in the limited screen real estate of the iPhone. There are a lot of apps that have run out of space in their toolbars that could borrow from this design. I particularly like that in the new action sheet, all the actions are labeled with words in addition to icons. But iOS 13 should have included a first-run explainer <em>showing</em> users where these features moved to.</p>\n<p>And it just seems odd to me that they moved all these features there in the first place. The iPhone really only has room for five toolbar buttons. Flag, Move, Trash, Reply, and New Message seemed like good ones. What\u2019s the point of having only two buttons and all that unused whitespace on the left side? In addition to the fact that it\u2019s not intuitive to look for Flag and Move commands behind a button that clearly looks like \u201cReply\u201d, it\u2019s also a bit frustrating to me that there\u2019s no longer a way to just create a new message from this screen\u2009\u2014\u2009you have to go back one level in the navigation controller to the list of messages to create a new (non-reply) message.</p>\n<p>At the very least, if the toolbar is only going to have these two buttons, why not place the Trash button on the far left, and put the whitespace between the two buttons? That would eliminate inadvertent taps on the Trash button from either pre-iOS 13 muscle memory or from proximity to the Reply button.</p>"
},
"visual": {
"url": "http://b.vimeocdn.com/ts/451/794/451794956_1280.jpg",
"width": 1280,
"height": 720,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 3129,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572579174490
},
{
"originId": "tag:daringfireball.net,2019:/linked//6.36197",
"recrawled": 1572296763725,
"updateCount": 1,
"fingerprint": "298625a9",
"id": "ZTHt7g74IlVC5A2IgEvcn/aop5teo99gzFaGU2TCGxs=_16e13f9b1a7:19a2c:d4506071",
"updated": 1572296240000,
"author": "John Gruber",
"alternate": [
{
"href": "https://www.apple.com/airpods-pro/",
"type": "text/html"
}
],
"crawled": 1572293161383,
"title": "Apple\u2019s AirPods Pro Web Page: Scrolljacking Hell",
"published": 1572289670000,
"origin": {
"streamId": "feed/http://daringfireball.net/index.xml",
"htmlUrl": "https://daringfireball.net/",
"title": "Daring Fireball"
},
"content": {
"direction": "ltr",
"content": "<p>The AirPods Pro \u201coverview\u201d web page is a strange beast. It pegs my 2015 MacBook Pro\u2019s CPU\u2009\u2014\u2009<em>even when I\u2019m not scrolling</em>. I closed the tab a few minutes ago and my fan is still running. The animation is very jerky and scrolling feels so slow. There\u2019s so much <a href=\"https://www.discoverydesign.co.uk/blog/post/scroll-hijacking-why-scrolljacking-is-a-usability-nightmare/\">scrolljacking</a> that you have to scroll or page down several times just to go to the next section of the page. The animation is at least smooth on my iPad and iPhone, but even there, it feels like a thousand swipes to get to the bottom of the page. It\u2019s a design that makes it feel like they don\u2019t want you to keep reading. </p>\n<p>Disable JavaScript (easily toggled if you enable <a href=\"https://support.apple.com/guide/safari/use-the-developer-tools-in-the-develop-menu-sfri20948/mac\">Safari\u2019s Develop menu</a>) and the page is easy to read and looks great. I can\u2019t recall an example where scrolljacking makes a website so much worse.</p>\n<p><strong>Update:</strong> Nick Heer (of <a href=\"https://pxlnv.com/\">Pixel Envy</a> fame) messaged me to point out that the <a href=\"https://www.apple.com/ipad-pro/\">iPad Pro product page</a> gives the AirPods Pro page a run for its money for top spot in the Scrolljacking Hall of Shame. The iPad Pro page doesn\u2019t peg my MacBook Pro\u2019s CPU, but it scrolls the view <em>horizontally</em> while you scroll vertically.</p>\n<div>\n<a title=\"Permanent link to \u2018Apple\u2019s AirPods Pro Web Page: Scrolljacking Hell\u2019\" href=\"https://daringfireball.net/linked/2019/10/28/airpods-pro-scrolljacking-hell\">\u00a0\u2605\u00a0</a>\n</div>"
},
"visual": {
"url": "http://cdn1.sbnation.com/entry_photo_images/9188405/LG_G_Flex-3_large_verge_medium_landscape.jpg",
"width": 640,
"height": 426,
"contentType": "image/jpg"
},
"unread": false,
"readTime": 6570,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572579162176
},
{
"originId": "tag:daringfireball.net,2019:/linked//6.36201",
"fingerprint": "dec1a24f",
"id": "ZTHt7g74IlVC5A2IgEvcn/aop5teo99gzFaGU2TCGxs=_16e15437a6d:19e93:d4506071",
"updated": 1572313520000,
"author": "John Gruber",
"alternate": [
{
"href": "https://popular.info/p/facebook-allows-prominent-right-wing",
"type": "text/html"
}
],
"crawled": 1572314774125,
"title": "Facebook Allows Prominent Right-Wing Website to Break the Rules",
"published": 1572313519000,
"origin": {
"streamId": "feed/http://daringfireball.net/index.xml",
"htmlUrl": "https://daringfireball.net/",
"title": "Daring Fireball"
},
"content": {
"direction": "ltr",
"content": "<p>Judd Legum, writing for Popular Info:</p>\n<blockquote>\n<p>The Daily Wire, the right-wing website founded by pundit Ben\nShapiro, is a <a href=\"https://www.mediamatters.org/daily-wire/daily-wire-cesspool-hatred-and-bigotry\">cesspool</a> of misogyny, bigotry, and misinformation.\nIts toxic content is also fantastically successful on Facebook,\nwith each story reaching more people than any other major media\noutlet. A Popular Information investigation reveals some of this\nsuccess is attributable to a clandestine network of 14 large\nFacebook pages that purport to be independent but exclusively\npromote content from The Daily Wire in a coordinated fashion.</p>\n<p>This kind of \u201cinauthentic coordinated behavior\u201d violates\nFacebook\u2019s rules. Facebook has taken down smaller and less\ncoordinated networks that promoted liberal content. But Facebook\ntold Popular Information that it will continue to allow this\nnetwork to operate and amplify The Daily Wire\u2019s content.</p>\n</blockquote>\n<p>As a complete sidenote to the main point of this\u2009\u2014\u2009that Facebook is a right-wing company\u2009\u2014\u2009notice how nice and clean and fast the Popular Info website is. The best websites these days aren\u2019t from web publishers\u2009\u2014\u2009they\u2019re from mailing list publishers with websites.</p>\n<div>\n<a title=\"Permanent link to \u2018Facebook Allows Prominent Right-Wing Website to Break the Rules\u2019\" href=\"https://daringfireball.net/linked/2019/10/28/facebook-daily-wire-legum\">\u00a0\u2605\u00a0</a>\n</div>"
},
"unread": false,
"readTime": 1124,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572579157406
},
{
"originId": "tag:daringfireball.net,2019://1.36209",
"recrawled": 1572448047706,
"updateCount": 2,
"fingerprint": "3576a6cd",
"id": "ZTHt7g74IlVC5A2IgEvcn/aop5teo99gzFaGU2TCGxs=_16e1b466c6b:1b876:d4506071",
"updated": 1572447167000,
"author": "John Gruber",
"summary": {
"direction": "ltr",
"content": "Apple invited a few dozen media folks to New York today for a briefing and early access to the new AirPods Pro. My initial impression: I like them."
},
"alternate": [
{
"href": "https://daringfireball.net/2019/10/airpods_pro_first_impressions",
"type": "text/html"
}
],
"crawled": 1572415630443,
"title": "\u2605 AirPods Pro First Impressions",
"published": 1572407940000,
"origin": {
"streamId": "feed/http://daringfireball.net/index.xml",
"htmlUrl": "https://daringfireball.net/",
"title": "Daring Fireball"
},
"content": {
"direction": "ltr",
"content": "<p>Apple invited a few dozen media folks to New York today for a briefing and early access to the new AirPods Pro. My initial impression: I like them.</p>\n<p>I left for home around 2:30 in the afternoon, and wore the AirPods Pro for the next three hours: on the subway in Manhattan, waiting (briefly, mercifully) in the cacophonous Penn Station, on the train ride home to Philadelphia, walking home through Center City Philadelphia, and then in my house. The subway, a train ride, and busy city streets are pretty good tests for noise cancellation.</p>\n<p>Noise cancellation worked really well for me. I own a pair of Bose over-the-ear noise canceling wireless headphones, but almost exclusively wear them only on airplanes and trains. Wearing noise-canceling earbuds on the subway and walking through the city is going to take some getting used to. It\u2019s so good you really do lose sense of your surrounding aural environment.</p>\n<p>I was a dummy and didn\u2019t take my Bose headphones on my trip today, so I can\u2019t say how they compare side-by-side on the train, but there\u2019s no question how AirPods Pro compare to regular AirPods. The difference is like night and day. Amtrak trains are pretty noisy\u2009\u2014\u2009especially at what we in the U.S. so adorably consider \u201chigh speeds\u201d\u2009\u2014\u2009but with AirPods Pro the clackety-clack rumble was effectively blocked out.</p>\n<p>The \u201cTransparency\u201d mode is interesting and a little mind-bending. It really does make it possible to conduct a conversation while still enjoying the benefits of noise cancellation. Because the silicone tips seal against your inner ear, when you turn AirPods Pro noise cancellation completely off, you really can\u2019t hear much around you. They\u2019re like earplugs. Transparency lets you hear <em>parts</em> of the world around you. One obvious use case for this: jogging or running and maybe just plain walking on streets where you <em>want</em> to hear the sounds of traffic.</p>\n<p>My corner store has a noisy refrigeration unit. With AirPods Pro on\u2009\u2014\u2009playing nothing\u2009\u2014\u2009I couldn\u2019t hear it at all. I couldn\u2019t tell that my dishwasher was running even though I was sitting right across from it in my kitchen. As someone who doesn\u2019t generally write while listening to music, I\u2019m likely to use AirPods Pro, playing nothing, just to tune out the world around me in a noisy space.</p>\n<p>The force sensor\u2009\u2014\u2009the flat section on the earbuds stem that faces forward when in your ear\u2009\u2014\u2009is effectively a button. But it\u2019s not a button. It doesn\u2019t actually move, and it doesn\u2019t provide haptic feedback. But it acts like a button and\u2009\u2014\u2009most importantly\u2009\u2014\u2009<em>sounds</em> like a button. When you press it, the AirPod Pro plays a click. I use the singular <em>AirPod</em> there because the click only plays in the bud whose force sensor you pressed. The effect is uncannily like clicking a real button. In a similar way to how force touch trackpads on modern MacBooks and Touch ID iPhone home buttons feel like they truly click, the AirPods Pro force sensors feel like actual clicking buttons. They actually have more of a premium clicky feel than the truly clicking buttons on Apple\u2019s wired EarPods, even though they don\u2019t actually click. It\u2019s uncanny, and Apple at its best.</p>\n<p>Another nice Apple-at-its-best touch: in Control Center on iOS, <a href=\"https://daringfireball.s3.us-east-1.amazonaws.com/misc/2019/10/airpods-pro-control-center.mp4\">you can long-press the volume control while wearing AirPods Pro to get a nice little three-way selector</a> to choose between noise cancellation, off, and transparency. The selection indicator animates nicely, the sounds are delightful (although you can\u2019t hear them in the movie linked above), and you can change the setting both by tapping another option or by dragging the selection indicator. It\u2019s a simple little interaction done exquisitely well.</p>\n<p>Force sensor actions:</p>\n<ul>\n<li>Single-click: play/pause</li>\n<li>Double-click: next track</li>\n<li>Triple-click: previous track</li>\n</ul>\n<p>By default, press-and-hold toggles between regular noise cancellation and transparency modes. That means, by default, the only way to invoke Siri is through the \u201cHey Siri\u201d verbal command. But if you want to invoke Siri through a long-press, you can change that in the Bluetooth section of Settings on your iPhone or iPad. And, you can change it per-ear\u2009\u2014\u2009so you can have your left AirPod Pro toggle transparency and the right one invoke Siri.</p>\n<p>Also in the Bluetooth settings is the Ear Tip Fit Test. It\u2019s very easy. Put the AirPods Pro in your ears, and start the test. It plays a song for about five seconds and decides whether you have a good fit with the current size tips. There\u2019s nothing \u201csmart\u201d about the silicone tips themselves\u2009\u2014\u2009the AirPods Pro don\u2019t \u201cknow\u201d which size tips you\u2019re currently wearing. The Fit Test just tells you if the current ones in your ear are a good fit. For me, the default medium tips feel best and the Ear Tip Fit Test consistently agrees. For my son, the medium tips felt uncomfortable, and the Fit Test agreed they weren\u2019t a good fit. For him, the small tips felt better and the Fit Test agreed. According to Apple, many people have differently-shaped ears and might need a different tip size for each ear, and if that\u2019s the case the Fit Test will suggest it.</p>\n<p>Swapping the tips is easy, but it takes a bit more pull than I expected to pop them off. Don\u2019t be afraid\u2009\u2014\u2009the tips seem rugged. And replacement tips from Apple will cost only $4\u2009\u2014\u2009truly cheap.</p>\n<p>The AirPods Pro case is about 15% larger by volume than the regular AirPods case. That\u2019s unfortunate, but it\u2019s not noticeable in a regular pants pocket, and it still fits in <a href=\"https://www.huffpost.com/entry/small-pocket-jeans-watches-cowboys_n_56a7720ce4b0b87beec5eb5f\">the fifth pocket</a> of a pair of Levi\u2019s 501 jeans.</p>\n<p>Battery life, so far, is exactly in line with Apple\u2019s stated specs. My review unit started at 75% (both the buds and the case). After three straight hours of use, the buds were down to about 10%. So if three hours of use consumed two-thirds of the battery, a full charge should last about 4.5 hours\u2009\u2014\u2009which is <em>exactly</em> Apple\u2019s claim.</p>\n<p>Comfort-wise, my ears felt fine after those three consecutive hours of use. It\u2019s a very different feeling compared to regular AirPods, but I like it. I\u2019ve never had a problem with regular AirPods falling out of my ears, but AirPods Pro feel <em>way</em> more secure. Without question, how they feel is subjective\u2009\u2014\u2009so the good news is you can request a try-on in any Apple Store.</p>"
},
"visual": {
"url": "http://cdn1.sbnation.com/entry_photo_images/9188405/LG_G_Flex-3_large_verge_medium_landscape.jpg",
"width": 640,
"height": 426,
"contentType": "image/jpg"
},
"unread": false,
"readTime": 4178,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572579133239
},
{
"originId": "tag:blogger.com,1999:blog-8954608646904080796.post-8772112161384908748",
"fingerprint": "80075e70",
"thumbnail": [
{
"url": "https://1.bp.blogspot.com/-pMon836tLyo/XatsZ0Tv9MI/AAAAAAAADTs/90dBB5-ohkk2yOW4--zh7M0p_JicFuC4QCLcBGAsYHQ/s72-c/017.jpg",
"width": 72,
"height": 72
}
],
"id": "v0v+7Ya8tssIZvd3/pcnFRr3HwvY/5YK3FGc2t65c0Y=_16de5ccc6bb:ffbc:d4506071",
"updated": 1571515782582,
"author": "Edward Feser",
"alternate": [
{
"href": "http://edwardfeser.blogspot.com/2019/10/masculinity-and-marvel-movies.html",
"type": "text/html"
}
],
"crawled": 1571518465723,
"title": "Masculinity and the Marvel movies",
"published": 1571515740000,
"origin": {
"streamId": "feed/http://edwardfeser.blogspot.com/feeds/posts/default",
"htmlUrl": "http://edwardfeser.blogspot.com/",
"title": "Edward Feser"
},
"content": {
"direction": "ltr",
"content": "<br><div><a href=\"https://1.bp.blogspot.com/-pMon836tLyo/XatsZ0Tv9MI/AAAAAAAADTs/90dBB5-ohkk2yOW4--zh7M0p_JicFuC4QCLcBGAsYHQ/s1600/017.jpg\"><img border=\"0\" src=\"https://1.bp.blogspot.com/-pMon836tLyo/XatsZ0Tv9MI/AAAAAAAADTs/90dBB5-ohkk2yOW4--zh7M0p_JicFuC4QCLcBGAsYHQ/s200/017.jpg\" data-original-width=\"255\" width=\"200\" data-original-height=\"163\" height=\"127\"></a></div><div><span>Some time back, John Haldane gave a Thomistic Institute talk here in Los Angeles on the theme of <span><a href=\"https://soundcloud.com/thomisticinstitute/john-haldane-darkness-in-the-city-of-angels-evil-as-a-theme-and-vice-as-a-fact?utm_source=soundcloud&utm_campaign=share&utm_medium=facebook\">evil in the movies and in the movie industry</a></span>.\u00a0 During the Q and A (at about the 40 minute mark, and again after the 1:16 mark) the subject of superhero movies came up, and Haldane was critical of their current prevalence.\u00a0 In developing this criticism, he draws a useful distinction between <i>fantasy</i>and <i>imagination</i>.</span></div><a name=\"more\"></a> \u00a0<br> <div><span>Imagination, as Haldane uses the term, is a way of exploring aspects of reality and possibilities that are grounded in reality, even though it makes use of scenarios that are fictional or even impossible.<span>\u00a0 </span>Imagination is healthy and can increase our understanding of the moral and social worlds.<span>\u00a0 </span>Fantasy, by contrast, is unanchored in reality, and indeed it reflects a flight from reality and the discipline it imposes and responsibility that it entails.<span>\u00a0 </span>Haldane gives as an example the movie <i>Pretty Woman</i>, an absurdly unrealistic portrayal of prostitution and human relationships.</span></div><div><span><br></span></div><div><span>Fantasy can be harmless in small doses, Haldane allows, but when a culture becomes dominated by it, that is a sign that it has become decadent and unwilling to face reality.<span>\u00a0 </span>And the prevalence of superhero movies, Haldane says, is an indication that American society is increasingly retreating into fantasy and away from reality.<span>\u00a0 </span>He rejects the suggestion that such movies can be compared to the myths of the gods in ancient cultures.<span>\u00a0 </span>Such myths, he says, are essentially exercises in imagination, whereas superhero movies are sheer fantasy.</span></div><div><span><br></span></div><div><span>I think there is some truth to this analysis, but only some.<span>\u00a0 </span>Some superhero movies are indeed exercises in fantasy, but some are, in my view, clearly exercises in imagination.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Not long after hearing Haldane\u2019s talk, I happened to come across <span><a href=\"https://www.youtube.com/watch?v=T6wp0Qbf4Cw\">a 1978 television interview</a></span> with the late Harlan Ellison during which (beginning just before the 5 minute mark) Ellison criticizes the movies <i>Close Encounters of the Third Kind</i> and <i>Star Wars,</i> and modern American society in general, on exactly the same grounds raised by Haldane.<span>\u00a0 </span>He doesn\u2019t use Haldane\u2019s terminology, and in fact partially inverts it.<span>\u00a0 </span>Ellison uses \u201cfantasy\u201d to mean what Haldane means by \u201cimagination,\u201d and he uses the expression \u201cspace opera\u201d to refer to one type of what Haldane calls \u201cfantasy.\u201d<span>\u00a0 </span>But in substance, the distinction and the sort of points Haldane and Ellison are making are identical.</span></div><div><span><br></span></div><div><span>(Side note: Remember when you could find extended intelligent discussion like this on television?<span>\u00a0 </span>Remember when you could casually smoke on television, as Ellison does during the interview?<span>\u00a0 </span>Remember Laraine Newman, another guest on the show who also contributes to the discussion?)</span></div><div><span><br></span></div><div><span>Interestingly, though, Ellison was also well-known to be an enthusiast for comics, including superhero comics, and even wrote them from time to time (though this doesn\u2019t come up in the interview).<span>\u00a0 </span>I don\u2019t think there is any inconsistency there.</span></div><div><span><br></span></div><div><span>Suppose that, like me and like Haldane (though unlike Ellison) you are a conservative Catholic.<span>\u00a0 </span>Then, I would suggest, it is easy to see that there are themes in many superhero movies, and especially in the <i>Avengers</i> series that is currently the most popular of all, that are clearly reflections of imagination rather than fantasy.</span></div><div><span><br></span></div><div><span>Take the characters who, in the <i>Avengers</i> movies as in the comics, have been regarded as \u201cthe Big Three\u201d: Captain America, Thor, and Iron Man.<span>\u00a0 </span>Captain America represents patriotism, the military virtues, the earnest decency of the common man, and in general a Norman Rockwell style nostalgia for a simpler time.<span>\u00a0 </span>Thor \u2013 as part of the Asgardian pantheon ruled by stern Odin, to whom he must prove his worthiness \u2013 represents the higher realm spoken of by religion, and our obligations to the divine patriarchal authority who governs it.<span>\u00a0 </span>Iron Man is a business magnate who represents confident masculinity, superior ability and great wealth, and the <i>noblesse oblige</i>and rebuke to egalitarianism implied by them.<span>\u00a0 </span>These are deeply conservative themes, and it is astounding that these characters are as popular as they are in a society increasingly suffocated by political correctness. </span></div><div><span><br></span></div><div><span>Or maybe not.<span>\u00a0 </span>For such themes have appeal because they reflect human nature, and human nature does not change however much we try to paper over it with ideology and propaganda, and however corrupt human behavior and human societies become as a result.<span>\u00a0 </span>People will yearn in at least an inchoate way for the traditional institutions and ideals without which they cannot fulfill their nature, even when they are told they ought not to and have halfway convinced themselves that they ought not to.</span></div><div><span><br></span></div><div><span>I would suggest that the Marvel movies have the appeal they do at least in part precisely because they both convey these traditional ideals, but do so in a way that is fantastic enough that the offense to political correctness is not blatant.<span>\u00a0 </span>A film series whose heroes are a square patriotic soldier, the son of a heavenly Father come to earth, and a strutting capitalist alpha male sounds like something tailor-made for a Red State audience, and the last thing that would attract A-list actors and billions in investment from a major studio.<span>\u00a0 </span>Put these characters in colorful costumes, scenarios drawn from science fiction, and a little PC window dressing (such as portraying their girlfriends as a soldier, a scientist, and a businesswoman, respectively), and suddenly even a Blue State crowd can get on board.</span></div><div><span><br></span></div><div><span>Now, there are no traditional ideals more battered in contemporary Western society than masculinity, and the paternal role that is the fulfilment of masculinity.<span>\u00a0 </span>But these are precisely the key themes of many of the Marvel movies.<span>\u00a0 </span>The longing for a lost father or father figure is the core of all of the Spider-Man movies, as I noted in <span><a href=\"https://edwardfeser.blogspot.com/2014/07/marvel-team-up-spider-man-and-patriarchy.html\">a post from a few years back</a></span>.<span>\u00a0 </span>(In the Spider-Man movies that have appeared since that post was written, Tony Stark has become the father figure whose instruction and example Peter Parker strives to live up to.)<span>\u00a0 </span>The theme is also central to the <i>Guardians of the Galaxy</i> series, to <i>Black Panther</i>, to the <i>Daredevil</i> movie and Netflix series, and to the <i>Luke Cage</i> and <i>Iron Fist</i> Netflix series.<span>\u00a0 </span>The <i>Thor</i>movies are largely about the conflicted relationships Thor and Loki have with their father Odin, whose approval each of them nevertheless seeks.<span>\u00a0 </span>The bad consequences of <i>rebellion</i> against a father or father figure is the theme of the original Spider-Man series (wherein Peter initially refuses to heed his Uncle Ben\u2019s admonitions), of the first <i>Thor</i>movie, and of <i>Avengers: Age of Ultron</i>(whose wayward son is the robotic Ultron, at odds with his \u201cfather\u201d Stark). </span></div><div><span><br></span></div><div><span>The <i>Hulk</i> movies are largely about the consequences of failure as a father (whether Bruce Banner\u2019s father in the original <i>Hulk</i> movie, or Betty Ross\u2019s father in <i>The Incredible Hulk</i>).<span>\u00a0 </span><i>Ant-Man</i>is essentially about two men (Scott Lang and Hank Pym) who have partially failed as fathers and are trying to make up for it.<span>\u00a0 </span>The <i>Punisher </i>Netflix series is essentially about a husband and father seeking vengeance for the family that was taken from him.</span></div><div><span><br></span></div><div><span>But it is the two stars of the Marvel movies \u2013 Tony Stark/Iron Man and Steve Rogers/Captain America \u2013 who are the most obvious examples of idealized masculinity.<span>\u00a0 </span>And their character arcs through the series are about realizing that ideal.<span>\u00a0 </span>Each of them starts out as an imperfect specimen of the masculine ideal, albeit in very different ways.<span>\u00a0 </span>With Stark it is a vice of deficiency and with Rogers it is a vice of excess.<span>\u00a0 </span>But by the end of their arcs, in <i>Avengers: Endgame</i>, each achieves the right balance.<span>\u00a0 </span>(It might seem odd to think of <i>Rogers</i>rather than Stark as the one prone to a kind of excess.<span>\u00a0 </span>Bear with me and you\u2019ll see what I mean.)</span></div><div><span><br></span></div><div><span>On the traditional understanding of masculinity, a man\u2019s life\u2019s work has a twofold purpose.<span>\u00a0 </span>First, it is ordered toward providing for his wife and children.<span>\u00a0 </span>Second, it contributes something distinctive and necessary to the larger social order of which he and his family are parts.<span>\u00a0 </span>Society needs farmers, butchers, tailors, manual laborers, soldiers, scholars, doctors, lawyers, etc. and a man finds purpose both by being a husband and father and by filling one of these social roles.<span>\u00a0 </span>Though the traditional view regards women as \u201cthe weaker sex\u201d and as less assertive than men, it understands a man\u2019s worth and nobility in terms of the extent to which his strength and assertiveness are directed toward the <i>service of others</i>.</span></div><div><span><br></span></div><div><span>Liberal individualism, both in its libertarian form and its egalitarian form, replaced this social and other-directed model of a man\u2019s life\u2019s work with an individualist and careerist model, on which work is essentially about self-expression and self-fulfillment \u2013 making one\u2019s mark in the world, gaining its attention and adulation, attaining fame, power and influence, and so forth. <span>\u00a0</span>Nor is it even about providing for wife and children, since sex and romance too came to be regarded as a means of self-fulfillment rather than the creation of the fundamental social unit, the family.<span>\u00a0 </span>(Feminism took this corrupted individualist understanding of the meaning of a man\u2019s work and relationships and, rather than critiquing it, urged women to ape it as well.)</span></div><div><span><br></span></div><div><span>In the first two <i>Iron Man</i> movies, Stark is initially a specimen of this individualist mentality.<span>\u00a0 </span>His work is oriented toward attaining wealth, fame, and power.<span>\u00a0 </span>He uses women as playthings.<span>\u00a0 </span>He has a conflicted relationship with his late father, and is contemptuous of authority in general.<span>\u00a0 </span>He is judged by SHIELD to be \u201cvolatile, self-obsessed, and [unable to] play well with others.\u201d<span>\u00a0 </span>But he is gradually chastened by the consequences of his hubris \u2013 by being captured and injured in the first <i>Iron Man</i> movie; by being forced to face up to the limitations on his power to stop an alien invasion like the one that occurred in <i>Avengers</i>; and by the miscalculation that led to Ultron\u2019s rebellion and the many deaths it caused.<span>\u00a0 </span>By <i>Captain America: Civil War</i>, Stark is humbled enough to accept government oversight, and being left defeated and near-dead by Thanos in <i>Avengers: Infinity War</i> completes his chastening.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>By <i>Avengers: Endgame</i> Stark has become a family man.<span>\u00a0 </span><span>\u00a0</span>By way of time travel, he makes peace of a sort with his father.<span>\u00a0 </span>In the first <i>Avengers</i> movie, he had casually dismissed Rogers\u2019 talk of the need for self-sacrifice with the confidence that an alternative solution would always be possible for a clever person like himself.<span>\u00a0 </span>By contrast, in <i>Endgame</i>, he sees that he needs to lay down his life in order to save his wife and daughter and the world in general, and he willingly does it.<span>\u00a0 </span>To be sure, he is in no way neutered. <span>\u00a0</span>He retains his masculine assertiveness, strength, and self-confidence.<span>\u00a0 </span>But they are now directed toward the service of something larger than himself.</span></div><div><span><br></span></div><div><span>Rogers, by contrast, is from the first <i>Captain America</i> movie onward driven by a sense of duty to his country and to the social order more generally, and is willing to sacrifice everything for it, including even his own happiness and indeed his own life.<span>\u00a0 </span>He is also a perfect gentleman, and his only interest where women are concerned is with the one he would like to marry and settle down with if only he had the chance.<span>\u00a0 </span>Like Stark, he is relentlessly assertive, confident, and competent, but unlike Stark these traits are from the start directed toward the service of a larger good.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Rogers\u2019 flaw is that he is if anything a bit <i>too</i>absorbed in this larger good.<span>\u00a0 </span>At least initially, he is too much the man of action and the good soldier, with all the virtues but also with the flaws that that entails.<span>\u00a0 </span>He is a little too deferential to authority.<span>\u00a0 </span>In the first <i>Avengers</i> movie he glibly asserts: \u201cWe have orders.<span>\u00a0 </span>We should follow them\u201d \u2013 only to find out that perhaps he should have questioned them.<span>\u00a0 </span>The way institutions and authorities can become corrupted is impressed upon him far more dramatically in <i>Captain America: Winder Soldier</i>, to the point that in <i>Civil War</i> it is <i>Rogers</i> who is urging <i>Stark</i> to be more skeptical of authority.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>In general, Rogers\u2019 optimistic \u201ccan do\u201d spirit sometimes borders on na\u00efvet\u00e9, and it takes the catastrophe of <i>Infinity War</i> to teach him that the good guys don\u2019t always win and that some problems can only be managed or mitigated rather than solved.<span>\u00a0 </span>For much of the series, Rogers also has little life outside some military or quasi-military organization \u2013 the army, SHIELD, the Avengers.<span>\u00a0 </span>Without a war to fight, he doesn\u2019t know what to do with himself.<span>\u00a0 </span>He is square, prone to speechifying, and awkward with women \u2013 in <i>Winter Soldier</i> proclaiming himself \u201ctoo busy\u201d for romance, preferring to lose himself in one mission after the other.<span>\u00a0 </span>Only after near-death and victory in a \u201cmother of all battles\u201d in <i>Endgame</i>does he become convinced that he has the right to retire and \u201ctry some of that life Tony was telling me to get\u201d \u2013 traveling back in time to marry the woman he thought he\u2019d lost forever.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>The theme of the parallels and differences between the two characters provides a backbone to the Marvel movies.<span>\u00a0 </span>Both Stark and Rogers are supremely confident and competent.<span>\u00a0 </span>They are both natural leaders.<span>\u00a0 </span>Each stubbornly insists on pursuing the course he is convinced is the correct one.<span>\u00a0 </span>They are too similar in these respects \u2013 though also too different in the other ways just described \u2013 to like each other much at first.<span>\u00a0 </span>The world is not big enough for both egos.<span>\u00a0 </span>They learn to like and respect each other only gradually, through many ups and downs.</span></div><div><span><br></span></div><div><span>Hence, in the first <i>Avengers </i>movie, Stark is jealous of the admiration that his father had had for Rogers, and Rogers is amazed that Howard Stark could have had a son as frivolous and unworthy as Tony.<span>\u00a0 </span>By <i>Civil War</i>, Rogers ends up having to defend the man who had (under mind control) murdered Howard \u2013 defending him from Tony, who seeks to avenge his father and now (temporarily) judges <i>Rogers</i> unworthy of his father\u2019s admiration.<span>\u00a0 </span>Stark starts out arrogantly rejecting any government control over his activity as Iron Man, only to insist on government control in <i>Civil War</i>.<span>\u00a0 </span>Rogers starts out dutifully following orders in the first <i>Captain America</i> and <i>Avengers</i> movies, only stubbornly to reject government control over the team in <i>Civil War</i>.<span>\u00a0 </span>In <i>Age of Ultron</i>, Rogers criticizes Stark for acting independently of the team, and in <i>Civil War</i>, Stark criticizes Rogers for acting independently of the team.<span>\u00a0 </span>Rogers feels guilt for failing to prevent the death of Bucky, his comrade-in-arms.<span>\u00a0 </span>Stark feels guilt for failing to prevent the death of Peter Parker, to whom he has become a father figure.<span>\u00a0 </span>Rogers lays down his life in the first <i>Captain America</i> movie, only to get it back.<span>\u00a0 </span>Stark preserves his life against all odds throughout the whole series, only to lay it down in the last <i>Avengers</i> movie.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>I submit that its complex portrayal of these competing models of masculinity is part of what makes the Marvel series of movies a genuine exercise in <i>imagination</i> rather than fantasy, in Haldane\u2019s sense of the terms.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>One wonders, however, whether this will last.<span>\u00a0 </span>A few years ago, Marvel\u2019s comics division notoriously reoriented their titles to reflect greater \u201cdiversity\u201d and political correctness \u2013 an experiment that critics labeled \u201cSJW Marvel\u201d and that <span><a href=\"https://thefederalist.com/2017/04/12/forcing-political-correctness-employees-characters-killing-marvel-comics/\">resulted in a dramatic decline in sales</a></span>.<span>\u00a0 </span>The trend has been partially reversed and did not at the time affect the movies, where much more money is at stake.<span>\u00a0 </span>But <a href=\"https://thefederalist.com/2019/09/05/next-slate-marvel-movies-feature-characters-dulled-identity-politics/\">there are signs</a> that a milder form of the \u201cSJW Marvel\u201d approach will make its way into the Marvel Cinematic Universe in the next phase of movies.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>For example, the title character of <i>Captain Marvel</i>is portrayed with little emotion, no love interest, and lacking any of the femininity, vulnerability, and complexity of characters like Scarlett Johannsen\u2019s Black Widow or Elizabeth Olsen\u2019s Scarlet Witch.<span>\u00a0 </span>As Kyle Smith <a href=\"https://www.nationalreview.com/2019/03/captain-marvel-movie-review-dull-directionless/\">noted in <i>National Review</i></a>, Brie Larson portrays her instead as \u201cfiercer than fierce, braver than brave\u2026 insouciant, kicking butt, delivering her lines in an I-got-this monotone\u2026 amazingly strong and resilient at the beginning, middle, and end. <span>\u00a0</span>This isn\u2019t an arc, it\u2019s a straight line.\u201d<span>\u00a0 </span>Into the bargain, this C-list character, dropped into the Marvel Cinematic Universe out of nowhere, is <a href=\"https://www.looper.com/147990/the-mcu-most-powerful-character-is-confirmed-captain-marvel/\">suddenly proclaimed</a> \u201cthe most powerful character\u201d in that universe.</span></div><div><span><br></span></div><div><span>In short, <i>Captain Marvel</i> is transparently an exercise in feminist wish fulfilment.<span>\u00a0 </span>More to the present point, it is sheer <i>fantasy</i> in Haldane\u2019s sense, rather than imagination \u2013 a portrayal of the way a certain mindset <i>wishes</i> the world to be, rather than a fanciful representation of the way it really is.<span>\u00a0 </span>And, as Smith points out, its title character is for that reason completely boring.<span>\u00a0 </span>(Contrast this with Marvel\u2019s Netflix series <i>Jessica Jones</i>, which \u2013 despite its own feminist undercurrents \u2013 is <i>not</i> boring, and whose female characters are well-rounded and interesting.)<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>If future Marvel movies follow in this identity politics oriented direction, they will in fact become what Haldane (in my view mistakenly) thinks they already are.</span></div><div><span><br></span></div><div><span>Further reading:</span></div><div><span><br></span></div><div><span><a href=\"https://edwardfeser.blogspot.com/2011/09/pop-culture-roundup.html\">Pop culture roundup</a></span></div>"
},
"unread": true,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/fbdcd69b-7e27-4b6a-bfed-6584b944155d",
"label": "\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb Renamed"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578985412
},
{
"originId": "tag:blogger.com,1999:blog-8954608646904080796.post-8613145924738251081",
"fingerprint": "473d1ae4",
"thumbnail": [
{
"url": "https://1.bp.blogspot.com/-P_7aCRZVVKo/XbollnDDTuI/AAAAAAAADUU/y6TgUEudc0EU89QnGt1IxZ1Frdro3GwVQCLcBGAsYHQ/s72-c/047.jpg",
"width": 72,
"height": 72
}
],
"id": "v0v+7Ya8tssIZvd3/pcnFRr3HwvY/5YK3FGc2t65c0Y=_16e1f35113f:1cfaa:d4506071",
"updated": 1572480433981,
"author": "Edward Feser",
"alternate": [
{
"href": "http://edwardfeser.blogspot.com/2019/10/new-from-editiones-scholasticae.html",
"type": "text/html"
}
],
"crawled": 1572481601855,
"title": "New from Editiones Scholasticae",
"published": 1572480420000,
"origin": {
"streamId": "feed/http://edwardfeser.blogspot.com/feeds/posts/default",
"htmlUrl": "http://edwardfeser.blogspot.com/",
"title": "Edward Feser"
},
"content": {
"direction": "ltr",
"content": "<br><div><a href=\"https://1.bp.blogspot.com/-P_7aCRZVVKo/XbollnDDTuI/AAAAAAAADUU/y6TgUEudc0EU89QnGt1IxZ1Frdro3GwVQCLcBGAsYHQ/s1600/047.jpg\"><img border=\"0\" src=\"https://1.bp.blogspot.com/-P_7aCRZVVKo/XbollnDDTuI/AAAAAAAADUU/y6TgUEudc0EU89QnGt1IxZ1Frdro3GwVQCLcBGAsYHQ/s200/047.jpg\" data-original-width=\"251\" width=\"200\" data-original-height=\"180\" height=\"143\"></a></div><div><span>Editiones Scholasticae, the publisher of my books <span><i><a href=\"https://www.amazon.com/Scholastic-Metaphysics-A-Contemporary-Introduction/dp/3868385444/ref=sr_1_1?ie=UTF8&qid=1391482601&sr=8-1&keywords=scholastic+metaphysics+a+contemporary+introduction\">Scholastic Metaphysics</a></i></span> and <span><i><a href=\"https://www.amazon.com/Aristotles-Revenge-Metaphysical-Foundations-Biological/dp/3868382003/\">Aristotle\u2019s Revenge</a></i></span>, informs me that both of them will within a few days be available in eBook versions.\u00a0 Also new from the publisher is a German translation of my book <span><i><a href=\"https://www.editiones-scholasticae.de/index.php?page=shop.product_details&flypage=flypage.tpl&product_id=452&category_id=31&keyword=feser&option=com_virtuemart&Itemid=19\">Philosophy of Mind</a></i></span>. \u00a0(Previously they had published German translations of <span><i><a href=\"https://www.editiones-scholasticae.de/index.php?page=shop.product_details&flypage=flypage.tpl&product_id=371&category_id=31&keyword=feser&option=com_virtuemart&Itemid=19\">The Last Superstition</a></i></span> and <span><i><a href=\"https://www.editiones-scholasticae.de/index.php?page=shop.product_details&flypage=flypage.tpl&product_id=440&category_id=31&keyword=feser&option=com_virtuemart&Itemid=19\">Five Proofs of the Existence of God</a></i></span>.) \u00a0Take a look at <span><a href=\"https://www.editiones-scholasticae.com/\">Editiones Scholasticae\u2019s new webpage</a></span> for further information, as well as for information about other new releases from the publisher.\u00a0 You will find both new works by contemporary writers in the Scholastic tradition, and reprints of older and long out of print works in that tradition.\u00a0 (The original webpage <span><a href=\"https://www.editiones-scholasticae.de/\">is still online as well</a></span>.)</span></div>"
},
"visual": {
"url": "https://cdn.vox-cdn.com/thumbor/qEtBNTmNKQvUro7McqHPXL-2OOM=/0x0:6720x4480/1310x873/cdn.vox-cdn.com/uploads/chorus_image/image/59664621/marshall_majorIII_aniconinthemaking_product_rgb_highres_2.0.jpg",
"width": 1310,
"height": 878,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 2725,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/fbdcd69b-7e27-4b6a-bfed-6584b944155d",
"label": "\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb Renamed"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.unsaved",
"label": "Unsaved"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578978618
},
{
"keywords": [
"Apple",
"Business"
],
"originId": "http://www.loopinsight.com/?p=100501",
"fingerprint": "5554fc75",
"id": "A4VVV8iwf2HD21qpAa7ABDI8MY8lm8dIbsVbE6sVKNA=_16e226a819a:1e01f:d4506071",
"author": "Dave Mark",
"summary": {
"direction": "ltr",
"content": "Kif Leswing, CNBC:\n<blockquote>\nUnder the argument for an iPhone subscription, which some people call Apple Prime after the Amazon program of the same name, Apple would bundle hardware upgrades with services like iCloud storage or Apple TV+ content and hardware for a single monthly fee. This would let it switch iPhone sales from a transactional model to a subscription model, potentially driving the stock price up without having to increase product sales or prices dramatically.\n</blockquote>\nAnd:\n<blockquote>\n\u2033In terms of hardware as a service or as a bundle, if you will, there are customers today that essentially view the hardware like that because they\u2019re on upgrade plans and so forth,\u201d Cook said during an earnings call. \u201cSo to some degree that exists today.\u201d\n</blockquote>\nAnd, most importantly:\n<blockquote>\n\u201cMy perspective is that will grow in the future to larger numbers. It will grow disproportionately\u201d\n</blockquote>\nI had the chance to be on John Gruber's show (recorded yesterday, guessing it'll drop today or tomorrow, assuming John is not too horrified with the results), and we were talking about this, peripherally. John mentioned the future possibility of Apple Prime, a concept similar to Amazon Prime. From the article:\n<blockquote>\nUnder the argument for an iPhone subscription, which some people call Apple Prime after the Amazon program of the same name, Apple would bundle hardware upgrades with services like iCloud storage or Apple TV+ content and hardware for a single monthly fee.\n</blockquote>\nI suspect we'll all eventually be subscribing from a menu of services, including column A, software, column B, traditional services, and column C, hardware. Intriguing.<a rel=\"bookmark\" href=\"https://www.loopinsight.com/2019/10/31/apple-is-laying-the-groundwork-for-an-iphone-subscription/\" title=\"Permanent link to 'Apple is laying the groundwork for an iPhone subscription'\">\u221e Read this on The Loop</a>"
},
"alternate": [
{
"href": "https://www.cnbc.com/2019/10/30/apple-lays-groundwork-for-iphone-or-apple-prime-subscription.html",
"type": "text/html"
}
],
"crawled": 1572535435674,
"title": "Apple is laying the groundwork for an iPhone subscription",
"published": 1572532001000,
"origin": {
"streamId": "feed/http://www.loopinsight.com/feed/",
"htmlUrl": "https://www.loopinsight.com",
"title": "The Loop"
},
"content": {
"direction": "ltr",
"content": "<p>Kif Leswing, CNBC:</p>\n<blockquote>\n<p>Under the argument for an iPhone subscription, which some people call Apple Prime after the Amazon program of the same name, Apple would bundle hardware upgrades with services like iCloud storage or Apple TV+ content and hardware for a single monthly fee. This would let it switch iPhone sales from a transactional model to a subscription model, potentially driving the stock price up without having to increase product sales or prices dramatically.</p>\n</blockquote>\n<p>And:</p>\n<blockquote>\n<p>\u2033In terms of hardware as a service or as a bundle, if you will, there are customers today that essentially view the hardware like that because they\u2019re on upgrade plans and so forth,\u201d Cook said during an earnings call. \u201cSo to some degree that exists today.\u201d</p>\n</blockquote>\n<p>And, most importantly:</p>\n<blockquote>\n<p>\u201cMy perspective is that will grow in the future to larger numbers. It will grow disproportionately\u201d</p>\n</blockquote>\n<p>I had the chance to be on John Gruber\u2019s show (recorded yesterday, guessing it\u2019ll drop today or tomorrow, assuming John is not too horrified with the results), and we were talking about this, peripherally. John mentioned the future possibility of Apple Prime, a concept similar to Amazon Prime. From the article:</p>\n<blockquote>\n<p>Under the argument for an iPhone subscription, which some people call Apple Prime after the Amazon program of the same name, Apple would bundle hardware upgrades with services like iCloud storage or Apple TV+ content and hardware for a single monthly fee.</p>\n</blockquote>\n<p>I suspect we\u2019ll all eventually be subscribing from a menu of services, including column A, software, column B, traditional services, and column C, hardware. Intriguing.</p>\n<p><a rel=\"bookmark\" href=\"https://www.loopinsight.com/2019/10/31/apple-is-laying-the-groundwork-for-an-iphone-subscription/\" title=\"Permanent link to 'Apple is laying the groundwork for an iPhone subscription'\">\u221e Read this on The Loop</a></p>"
},
"visual": {
"url": "https://cdn.vox-cdn.com/thumbor/fhKs50EFS0SJPjSjfCR7lXwcMfs=/0x0:2040x1360/1310x873/cdn.vox-cdn.com/uploads/chorus_image/image/59667903/acastro_180508_1777_google_IO_0002.0.jpg",
"width": 1310,
"height": 873,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 20737,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578952687
},
{
"keywords": [
"Apple"
],
"originId": "https://9to5mac.com/?p=617610",
"fingerprint": "48affe9c",
"id": "BmoAzSEWHFzR01wyxBZAhNEo11Vy8oDR1qKDe+tKVEQ=_16e1de23321:1c6e5:d4506071",
"author": "Chance Miller",
"summary": {
"direction": "ltr",
"content": "<div><img src=\"https://9to5mac.com/wp-content/uploads/sites/6/2019/10/SCREEN-SHOT-2019-10-30-AT-12.55.55-PM.jpeg?quality=82&strip=all&w=1600\"></div>\n<p>Microsoft is planning several updates to its Outlook app for iPhone and iPad. As explained by <a href=\"https://www.theverge.com/2019/10/30/20940228/outlook-ios-mobile-ipados-split-view-do-not-disturb-smart-folders-features\"><em>The Verge</em></a>, Microsoft will roll out features such as iPad Split View, smart folders, and more to the Outlook app over the coming weeks.</p>\n<p> <a href=\"https://9to5mac.com/2019/10/30/microsoft-outlook-split-view-more/#more-617610\">more\u2026</a></p>\n<p>The post <a rel=\"nofollow\" href=\"https://9to5mac.com/2019/10/30/microsoft-outlook-split-view-more/\">Microsoft Outlook for iPhone and iPad adding Split View, Do Not Disturb, more</a> appeared first on <a rel=\"nofollow\" href=\"https://9to5mac.com\">9to5Mac</a>.</p>"
},
"alternate": [
{
"href": "https://9to5mac.com/2019/10/30/microsoft-outlook-split-view-more/",
"type": "text/html"
}
],
"crawled": 1572459393825,
"title": "Microsoft Outlook for iPhone and iPad adding Split View, Do Not Disturb, more",
"published": 1572458509000,
"origin": {
"streamId": "feed/http://9to5mac.com/feed/",
"htmlUrl": "https://9to5mac.com",
"title": "9to5Mac"
},
"unread": false,
"readTime": 13858,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815",
"label": "Macintosh"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578905515
},
{
"keywords": [
"Miscellaneous"
],
"originId": "https://nshipster.com/device-identifiers",
"fingerprint": "5e66b947",
"id": "08l+9ftpGejQ9f/2DZ6dom5rSnNJJO9OCox6I3nUnWg=_16e22ccc11a:1e495:d4506071",
"updated": 1572505200000,
"author": "Mattt",
"summary": {
"direction": "ltr",
"content": "<p>For every era, there\u2019s a monster that embodies the anxieties of the age.</p>"
},
"alternate": [
{
"href": "https://nshipster.com/device-identifiers/",
"type": "text/html"
}
],
"crawled": 1572541874458,
"title": "Device Identifiers and Fingerprinting on iOS",
"published": 1572505200000,
"origin": {
"streamId": "feed/http://nshipster.com/feed.xml",
"htmlUrl": "https://nshipster.com/",
"title": "NSHipster"
},
"content": {
"direction": "ltr",
"content": "<p>For every era,\nthere\u2019s a monster that embodies the anxieties of the age.</p>\n<p>At the dawn of the <a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Holocene\">Holocene</a>,\nour ancestors traced the contours of shadows cast by the campfire\nas they kept watch over the darkness.\nOnce we learned to read the night sky for navigation,\nsailors swapped stories of sea creatures like\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Leviathan\">Leviathan</a> and\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Siren_%28mythology%29\">Siren</a>\nto describe the dangers of open ocean\n(and the perils to be found on unfamiliar shores).</p>\n<p><a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Frankenstein%27s_monster\">Frankenstein\u2019s monster</a>\nwas as much the creation of Mary Shelley\nas it was a spiritual collaboration with\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Luigi_Galvani\">Luigi Galvani</a>.\nAnd Bram Stoker\u2019s\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/The_Jewel_of_Seven_Stars\">fictionalized account of the mummy\u2019s curse</a>\nwas more a response to the\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Egyptomania\">Egyptomania</a>\nand European colonialism\nof the nineteenth century\nthan any personal account of the Middle Kingdom.</p>\n<p>More recently,\nthe <a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/The_Beach_Girls_and_the_Monster\">\u201cmonster ruins a beach party\u201d</a>\ntrope of the 1960s\narose from concerns of teenager morality.\nWhile the\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/The_Day_Mars_Invaded_Earth\">Martians</a>\nwho invaded those same drive-in double features\nserved as a proxy for Cold War fears at the height of the\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Space_Race\">Space Race</a>.</p>\n<hr>\n<p>All of which begs the question:\n<em>\u201cWhat monster best exemplifies our present age?\u201d</em></p>\n<p>Consider the unnamed monster from the film\n<em><a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/It_Follows\">It Follows</a></em>:\na formless, supernatural being that relentlessly pursues its victims\nanywhere on the planet.</p>\n<p>Sounds a bit like the state of\n<dfn title=\"advertising technology\">ad tech</dfn>\nin 2019, no?</p>\n<aside>\n<p>Setting aside its central theme of carnal karma,\nwhich follows the same well-trodden path of horror as our aforementioned beach monsters\u2026</p>\n</aside>\n<hr>\n<p>This week on NSHipster \u2014\nin celebration of our favorite holiday\n<abbr title=\"(Halloween)\">\ud83c\udf83</abbr> \u2014\nwe\u2019re taking a look at the myriad ways that\nyou\u2019re being tracked on iOS,\nboth sanctioned and unsanctioned,\nhistorically and presently.\nSo gather around the campfire,\nand allow us to trace the contours of the unseen, formless monsters\nthat stalk us under cover of <a href=\"https://nshipster.com/dark-mode/\">Dark Mode</a>.</p>\n<hr>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#the-cynicism-of-marketing-and-advertising-technology\"></a>The Cynicism of Marketing and Advertising Technology</h2>\n<p>Contrary to our intuitions about natural selection in the marketplace,\nhistory is littered with examples of\ninferior-but-better-marketed products winning out over superior alternatives:\n<em>VHS vs. Betamax</em>,\n<em>Windows vs. Macintosh</em>,\netc.\n(According to the common wisdom of business folks, at least.)\nRegardless,\nmost companies reach a point where\n<em>\u201cif you build it, they will come\u201d</em>\nceases to be a politically viable strategy,\nand someone authorizes a marketing budget.</p>\n<p>Marketers are tasked with growing market share\nby identifying and communicating with as many potential customers as possible.\nAnd many \u2014\neither out of a genuine belief or formulated as a post hoc rationalization \u2014\ntake the potential benefit of their product\nas a license to flouting long-established customs of personal privacy.\nSo they enlist the help of one or more\nadvertising firms,\nwho promise to maximize their allocated budget and\nprovide some accountability for their spending\nby using technology to\n<dfn><strong>target</strong></dfn>,\n<dfn><strong>deliver</strong></dfn>, and\n<dfn><strong>analyze</strong></dfn>\nmessaging to consumers.</p>\n<p><strong>Each of these tasks is predicated on a consistent identity,\nwhich is why advertisers go to such great lengths to track you.</strong></p>\n<ul>\n<li>Without knowing who you are,\nmarketers have no way to tell if you\u2019re a likely or even potential customer.</li>\n<li>Without knowing where you are,\nmarketers have no way to reach you\nother than to post ads where they\u2019re likely to be seen.</li>\n<li>Without knowing what you do,\nmarketers have no way to tell if their ads worked\nor were seen at all.</li>\n</ul>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#apple-sanctioned-identifiers\"></a>Apple-Sanctioned Identifiers</h2>\n<p>Apple\u2019s provided various APIS to facilitate user identification\nfor various purposes:</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#universal-identifiers-udid\"></a>Universal Identifiers (UDID)</h3>\n<p>In the early days of iOS,\nApple provided a <code>unique<wbr>Identifier</code> property on <code>UIDevice</code> \u2014\naffectionately referred to as a\n<abbr title=\"Universal Device Identifier\">UDID</abbr>\n(<a href=\"https://nshipster.com/uuid-udid-unique-identifier/\">not to be confused with a UUID</a>).\nAlthough such functionality seems unthinkable today,\nthat property existed until iOS 5,\nuntil it was\ndeprecated and replaced by <code>identifier<wbr>For<wbr>Vendor</code> in iOS 6.</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#vendor-identifiers-idfv\"></a>Vendor Identifiers (IDFV)</h3>\n<p>Starting in iOS 6,\ndevelopers can use the\n<code>identifier<wbr>For<wbr>Vendor</code> property on <code>UIDevice</code>\nto generate a unique identifier that\u2019s shared across apps and extensions\ncreated by the same vendor\n(<abbr title=\"Identifier for Vendor\">IDFV</abbr>).</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>UIKit</span>\n <span>let</span> <span>idfv</span> <span>=</span> <span>UIDevice</span><span>.</span><span>current</span><span>.</span><span>identifier<wbr>For<wbr>Vendor</span> <span>// BD43813E-CFC5-4EEB-ABE2-94562A6E76CA</span>\n </code></pre>\n<aside>\n<p>According to <a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor\">the documentation</a>\n<code>identifier<wbr>For<wbr>Vendor</code> return <code>nil</code>\n\u201cafter the device has been restarted but before the user has unlocked the device.\u201d\nIt\u2019s unclear when that would be the case,\nbut something to keep in mind if your app does anything in the background.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#advertising-identifiers-idfa\"></a>Advertising Identifiers (IDFA)</h3>\n<p>Along with <code>identifier<wbr>For<wbr>Vendor</code> came the introduction of a new\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/adsupport\">AdSupport framework</a>,\nwhich Apple created to help distinguish\nidentification necessary for app functionality\nfrom anything in the service of advertising.</p>\n<p>The resulting\n<code>advertisingidentifier</code> property\n(affectionately referred to as\n<abbr title=\"Identifier for Advertisers\">IDFA</abbr> by its associates)\ndiffers from <code>identifier<wbr>For<wbr>Vendor</code>\nby returning the same value for everyone.\nThe value can change, for example,\nif the user <a rel=\"noopener noreferrer\" href=\"https://support.apple.com/en-us/HT205223\">resets their Advertising Identifier</a>\nor erases their device.</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Ad<wbr>Support</span>\n <span>let</span> <span>idfa</span> <span>=</span> <span>ASIdentifier<wbr>Manager</span><span>.</span><span>shared</span><span>()</span><span>.</span><span>advertising<wbr>Identifier</span>\n </code></pre>\n<p>If advertising tracking is limited,\nthe property returns a zeroed-out UUID instead.</p>\n<pre data-lang=\"Swift\"><code><span>idfa</span><span>.</span><span>uuid<wbr>String</span> <span>==</span> <span>&quot;00000000-0000-0000-0000-000000000000&quot;</span> <span>// true if the user has limited ad tracking</span>\n </code></pre>\n<aside>\n<p>Curiously,\nmacOS Mojave introduced a\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/adsupport/asidentifiermanager/2998811-clearadvertisingidentifier\"><code>clear<wbr>Advertising<wbr>Identifier()</code> method</a>,\nwhich appears to create a <em>\u201ctragedy of the commons\u201d</em> situation,\nwhere a single app could spoil things for everyone else\n<em>(not that this is a bad thing from the user\u2019s perspective!)</em></p>\n</aside>\n<aside>\n<p>There\u2019s also the curious case of the\n<code>is<wbr>Advertising<wbr>Tracking<wbr>Enabled</code> property.\nAccording to\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier\">the documentation</a>:</p>\n<blockquote>\n<p>Check the value of this property\nbefore performing any advertising tracking.\nIf the value is false,\nuse the advertising identifier only for the following purposes:\nfrequency capping,\nattribution,\nconversion events,\nestimating the number of unique users,\nadvertising fraud detection,\nand debugging.</p>\n</blockquote>\n<p>This kind of <em>\u201chonor system\u201d</em> approach compliance is confusing.\nAnd it makes you wonder what kind of usage\n<em>wouldn\u2019t</em> fall within these broad allowances.</p>\n<p>If you have any insight into how this is policed,\n<a rel=\"noopener noreferrer\" href=\"https://twitter.com/nshipster\">drop us a line</a> \u2014\nwe\u2019d love to hear more.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#devicecheck\"></a>DeviceCheck</h3>\n<p><code>identifier<wbr>For<wbr>Vendor</code> and <code>advertising<wbr>Identifier</code>\nprovide all the same functionality as the <code>unique<wbr>Identifier</code> property\nthey replaced in iOS 6,\nsave for one:\nthe ability to persist across device resets and app uninstalls.</p>\n<p>In iOS 11,\nApple quietly introduced the\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/devicecheck\">DeviceCheck framework</a>,\nwhich allows developers to assign two bits of information\nthat are persisted by Apple\n<strong>until the developer manually removes them</strong>.</p>\n<p>Interacting with the DeviceCheck framework should be familiar to\nanyone familiar with <a href=\"https://nshipster.com/apns-device-tokens\">APNS</a>:\nafter setting things up on App Store Connect and your servers,\nthe client generates tokens on the device,\nwhich are sent to your servers to set or query two bits of information:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Device<wbr>Check</span>\n <span>let</span> <span>device</span> <span>=</span> <span>DCDevice</span><span>.</span><span>current</span>\n <span>if</span> <span>device</span><span>.</span><span>is<wbr>Supported</span> <span>{</span>\n <span>device</span><span>.</span><span>generate<wbr>Token</span> <span>{</span> <span>data</span><span>,</span> <span>error</span> <span>in</span>\n <span>if</span> <span>let</span> <span>token</span> <span>=</span> <span>data</span><span>?</span><span>.</span><span>base64Encoded<wbr>String</span><span>()</span> <span>{</span>\n <var>send token to your server</var>\n <span>}</span>\n <span>}</span>\n <span>}</span>\n </code></pre>\n<p>Based on the device token and other information sent by the client,\nthe server tells Apple to set each bit value\nby sending a JSON payload like this:</p>\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;device_token&quot;</span><span>:</span><span> </span><span>&quot;QTk4Qk<wbr>FDNEIt<wbr>NTBDMy00Qjc5LTh<wbr>BRUEt<wbr>MDQ5RTQz<wbr>Rj<wbr>NGQz<wbr>U0Cg==&quot;</span><span>,</span><span>\n</span><span>&quot;transaction_id&quot;</span><span>:</span><span> </span><span>&quot;D98BA630-E225-4A2F-AFEC-BE3A3D591708&quot;</span><span>,</span><span>\n</span><span>&quot;timestamp&quot;</span><span>:</span><span> </span><span>1572531720</span><span>,</span><span>\n</span><span>&quot;bit0&quot;</span><span>:</span><span> </span><span>true</span><span>,</span><span>\n</span><span>&quot;bit1&quot;</span><span>:</span><span> </span><span>false</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n<p>To retrieve those two bits at a later point in time,\nthe server sends a payload without <code>bit0</code> and <code>bit1</code> fields:</p>\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;device_token&quot;</span><span>:</span><span> </span><span>&quot;QTk4Qk<wbr>FDNEIt<wbr>NTBDMy00Qjc5LTh<wbr>BRUEt<wbr>MDQ5RTQz<wbr>Rj<wbr>NGQz<wbr>U0Cg==&quot;</span><span>,</span><span>\n</span><span>&quot;transaction_id&quot;</span><span>:</span><span> </span><span>&quot;D98BA630-E225-4A2F-AFEC-BE3A3D591708&quot;</span><span>,</span><span>\n</span><span>&quot;timestamp&quot;</span><span>:</span><span> </span><span>1572532500</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n<p>If everything worked,\nApple\u2019s servers would respond with a <code>200</code> status code\nand the following JSON payload:</p>\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;bit0&quot;</span><span> </span><span>:</span><span> </span><span>true</span><span>\n</span><span>&quot;bit1&quot;</span><span> </span><span>:</span><span> </span><span>false</span><span>,</span><span>\n</span><span>&quot;last_update_time&quot;</span><span> </span><span>:</span><span> </span><span>&quot;2019-10&quot;</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n<aside>\n<p>Apple allegedly created the DeviceCheck framework\nto meet the needs of Uber\nin limiting the abuse of promotional codes.\nAlthough DeviceCheck proports to store <em>only</em> two bits of information\n(just enough to, for example,\ndetermine whether a device has ever been used to create an account\nand whether the device was ever associated with fraudulent activity),\nwe have (admittedly vague) concerns that the timestamp, even with truncation,\ncould be exploited to store more than two bits of information.</p>\n</aside>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#fingerprinting-in-todays-ios\"></a>Fingerprinting in Today\u2019s iOS</h2>\n<p>Despite these affordances by Apple,\nadvertisers have continued to work to circumvent user privacy protections\nand use any and all information at their disposal\nto identify users by other means.</p>\n<p>Over the years,\nApple\u2019s restricted access to information about\ndevice hardware,\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl\">installed apps</a>,\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_networking_wifi-info\">nearby WiFi networks</a>.\nThey\u2019ve required apps to request permission to\nget your current location,\naccess your camera and microphone,\nflip through your contacts, and\nfind and connect to Bluetooth accessories.\nThey\u2019ve taken bold steps to <a rel=\"noopener noreferrer\" href=\"https://webkit.org/blog/8828/intelligent-tracking-prevention-2-2/\">prevent user tracking in Safari</a>.</p>\n<p>For lack of this information,\ncompanies have had to get creative,\nlooking to forge unique identities from the scraps of what\u2019s still available.\nThis process of identification by a combination of external factors\nis known as <dfn><a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Fingerprint_%28computing%29\">fingerprinting</a></dfn>.</p>\n<p>The unfortunate reality is that we can be uniquely identified\nby vanishingly small amounts of information.\nFor example,\nindividuals within a population can be singled out by as few as\nfour timestamped coordinates\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#de_montjoye_2013\">(de Montjoye, Hidalgo, Verleysen, &amp; Blondel, 2013)</a>\nor little more than a birthday and a ZIP code\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#sweeney_2000\">(Sweeney, 2000)</a>.</p>\n<p>Every WWDC since 2012 has featured a session about Privacy,\nbut the only mention of fingerprinting specifically was\n<a rel=\"noopener noreferrer\" href=\"https://asciiwwdc.com/2014/sessions/715?q=fingerprinting\">a brief discussion in 2014</a>\nabout how to avoid doing it.</p>\n<p>By our count,\na determined party could use conventional, unrestricted APIs\nto generate a few dozen bits of randomness:</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#locale-information-36-bits\"></a>Locale Information (~36 bits)</h3>\n<p>Locale information is the greatest source of identifying information\non Apple platforms.\nThe combination of your\npreferred languages, region, calendar, time zone,\nand which keyboards you have installed\nsay a lot about who you are \u2014\nespecially if you have less conventional preferences.</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Foundation</span>\n <span>Locale</span><span>.</span><span>current</span><span>.</span><span>language<wbr>Code</span>\n <span>log2</span><span>(</span><span>Double</span><span>(</span><span>Locale</span><span>.</span><span>iso<wbr>Language<wbr>Codes</span><span>.</span><span>count</span><span>))</span> <span>// 9.217 bits</span>\n <span>Locale</span><span>.</span><span>current</span><span>.</span><span>region<wbr>Code</span>\n <span>log2</span><span>(</span><span>Double</span><span>(</span><span>Locale</span><span>.</span><span>iso<wbr>Region<wbr>Codes</span><span>.</span><span>count</span><span>))</span> <span>// 8 bits</span>\n <span>Locale</span><span>.</span><span>current</span><span>.</span><span>calendar</span><span>.</span><span>identifier</span>\n <span>// ~2^4 (16) Calendars</span>\n <span>Time<wbr>Zone</span><span>.</span><span>current</span><span>.</span><span>identifier</span>\n <span>log2</span><span>(</span><span>Double</span><span>(</span><span>Time<wbr>Zone</span><span>.</span><span>known<wbr>Time<wbr>Zone<wbr>Identifiers</span><span>.</span><span>count</span><span>))</span> <span>// 8.775 bits</span>\n <span>User<wbr>Defaults</span><span>.</span><span>standard</span><span>.</span><span>object</span><span>(</span><span>for<wbr>Key</span><span>:</span> <span>&quot;Apple<wbr>Keyboards&quot;</span><span>)</span>\n <span>// ~2^6 (64) i<wbr>OS keyboards</span>\n </code></pre>\n<aside>\n<p>We recently <a rel=\"noopener noreferrer\" href=\"https://twitter.com/mattt/status/1175817188646612992\">Tweeted</a>\nabout apps having unrestricted access to emoji keyboard information.\nWe\u2019ve since been informed that Apple is investigating the issue.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#accessibility-10-bits\"></a>Accessibility (~10 bits)</h3>\n<p>Accessibility preferences also provide a great deal of information,\nwith each individual setting contributing a single potential bit:</p>\n<pre data-lang=\"Swift\"><code><span>UIAccessibility</span><span>.</span><span>is<wbr>Bold<wbr>Text<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Shake<wbr>To<wbr>Undo<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Reduce<wbr>Motion<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Darker<wbr>System<wbr>Colors<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Reduce<wbr>Transparency<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Assistive<wbr>Touch<wbr>Running</span>\n </code></pre>\n<p>Of the approximately ~25% of users who take advantage of\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically\">Dynamic Type</a>\nby configuring a preferred font size,\nthat selection may also be used to fingerprint you:</p>\n<pre data-lang=\"Swift\"><code><span>let</span> <span>application</span> <span>=</span> <span>UIApplication</span><span>.</span><span>shared</span>\n <span>application</span><span>.</span><span>preferred<wbr>Content<wbr>Size<wbr>Category</span>\n </code></pre>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#hardware-information-5-or-6-bits\"></a>Hardware Information (~5 or ~6 bits)</h3>\n<p>Although most of the juiciest bits have been locked down\nin OS updates over the years,\nthere\u2019s just enough to contribute a few more bits for purposes of identification.</p>\n<p>On iOS,\nyou can get the current model and amount of storage of a user\u2019s device:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>UIKit</span>\n <span>let</span> <span>device</span> <span>=</span> <span>UIDevice</span><span>.</span><span>current</span>\n <span>device</span><span>.</span><span>name</span> <span>// &quot;i<wbr>Phone 11 Pro&quot;</span>\n <span>let</span> <span>file<wbr>Manager</span> <span>=</span> <span>File<wbr>Manager</span><span>.</span><span>default</span>\n <span>if</span> <span>let</span> <span>path</span> <span>=</span> <span>file<wbr>Manager</span><span>.</span><span>urls</span><span>(</span><span>for</span><span>:</span> <span>.</span><span>library<wbr>Directory</span><span>,</span> <span>in</span><span>:</span> <span>.</span><span>system<wbr>Domain<wbr>Mask</span><span>)</span><span>.</span><span>last</span><span>?</span><span>.</span><span>path</span><span>,</span>\n <span>let</span> <span>system<wbr>Size</span> <span>=</span> <span>try</span><span>?</span> <span>file<wbr>Manager</span><span>.</span><span>attributes<wbr>Of<wbr>File<wbr>System</span><span>(</span><span>for<wbr>Path</span><span>:</span> <span>path</span><span>)[</span><span>.</span><span>system<wbr>Size</span><span>]</span> <span>as?</span> <span>Int</span>\n <span>{</span>\n <span>Measurement</span><span>&lt;</span><span>Unit<wbr>Information<wbr>Storage</span><span>></span><span>(</span><span>value</span><span>:</span> <span>Double</span><span>(</span><span>system<wbr>Size</span><span>),</span> <span>unit</span><span>:</span> <span>.</span><span>bytes</span><span>)</span>\n <span>.</span><span>converted</span><span>(</span><span>to</span><span>:</span> <span>.</span><span>gigabytes</span><span>)</span> <span>// ~256GB</span>\n <span>}</span>\n </code></pre>\n<p>With <a rel=\"noopener noreferrer\" href=\"https://support.apple.com/guide/iphone/supported-models-iphe3fa5df43/ios\">14 supported iOS devices</a>,\nmost having 3 configurations each,\nlet\u2019s say that this contributes about 32 possibilities, or 5 bits.</p>\n<p>You can go a few steps further on macOS,\nto further differentiate hardware by its processor count and amount of RAM:</p>\n<pre data-lang=\"Swift\"><code><span>process<wbr>Info</span><span>.</span><span>processor<wbr>Count</span> <span>// 8</span>\n <span>Measurement</span><span>&lt;</span><span>Unit<wbr>Information<wbr>Storage</span><span>></span><span>(</span><span>value</span><span>:</span> <span>Double</span><span>(</span><span>process<wbr>Info</span><span>.</span><span>physical<wbr>Memory</span><span>),</span>\n <span>unit</span><span>:</span> <span>.</span><span>bytes</span><span>)</span>\n <span>.</span><span>converted</span><span>(</span><span>to</span><span>:</span> <span>.</span><span>gigabytes</span><span>)</span> <span>// 16GB</span>\n </code></pre>\n<p>It\u2019s hard to get a sense of\n<a rel=\"noopener noreferrer\" href=\"https://everymac.com/systems/by_capability/minimum-macos-supported.html\">how many different Mac models are in use</a>,\nbut a reasonable estimate would be on the order of 2<sup>6</sup> or 2<sup>7</sup>.</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#cellular-network-2-bits\"></a>Cellular Network (~2 bits)</h3>\n<p>Knowing whether someone\u2019s phone is on Verizon or Vodaphone\ncan also be factored into a fingerprint.\nYou can use the <code>CTTelephony<wbr>Network<wbr>Info</code> class from the\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/coretelephony\">CoreTelephony framework</a>\nto lookup the providers for devices with cellular service:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Core<wbr>Telephony</span>\n <span>let</span> <span>network<wbr>Info</span> <span>=</span> <span>CTTelephony<wbr>Network<wbr>Info</span><span>()</span>\n <span>let</span> <span>carriers</span> <span>=</span> <span>network<wbr>Info</span><span>.</span><span>service<wbr>Subscriber<wbr>Cellular<wbr>Providers</span><span>?</span><span>.</span><span>values</span>\n <span>carriers</span><span>?</span><span>.</span><span>map</span> <span>{</span> <span>(</span><span>$0</span><span>.</span><span>mobile<wbr>Network<wbr>Code</span><span>,</span> <span>$0</span><span>.</span><span>mobile<wbr>Country<wbr>Code</span><span>)</span> <span>}</span>\n </code></pre>\n<p>The number of providers varies per country,\nbut using the 4 major carriers in United States\nas a guideline,\nwe can say carrier information would contribute about 2 bits\n(or more if you have multiple SIM cards installed).</p>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#communication-preferences-2-bits\"></a>Communication Preferences (2 bits)</h2>\n<p>More generally,\neven knowing whether someone can send texts or email at all\ncan be factored into a fingerprint.\nThis information can be gathered without permissions via\nthe <a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/messageui\">MessageUI framework</a>.</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Message<wbr>UI</span>\n <span>MFMail<wbr>Compose<wbr>View<wbr>Controller</span><span>.</span><span>can<wbr>Send<wbr>Mail</span><span>()</span>\n <span>MFMessage<wbr>Compose<wbr>View<wbr>Controller</span><span>.</span><span>can<wbr>Send<wbr>Text</span><span>()</span>\n </code></pre>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#additional-sources-of-identifying-information\"></a>Additional Sources of Identifying Information</h2>\n<p>If the use of digital fingerprinting seems outlandish,\nthat\u2019s just scratching the surface of how companies and researchers\nhave figured out how to circumvent your privacy.</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#geoip-and-relative-network-speeds\"></a>GeoIP and Relative Network Speeds</h3>\n<p>Although access to geolocation through conventional APIs\nrequires explicit authorization,\nthird parties may be able to get a general sense of where you are in the world\nbased on how you access the Internet.</p>\n<p><a rel=\"noopener noreferrer\" href=\"https://ipinfo.io\">Geolocation by source IP address</a>\nis used extensively for things like region locking and localization.\nYou could also combine this information with\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/library/archive/samplecode/SimplePing/Introduction/Intro.html#//apple_ref/doc/uid/DTS10000716\">ping-time measurements</a>\nto hosts in known locations\nto get a more accurate pinpoint on location <a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#weinberg_2018\">(Weinberg, Cho, Christin, Sekar, &amp; Gill, 2018)</a>:</p>\n<pre data-lang=\"Terminal\"><code><span>ping -c 5 99.24.18.13 #</span> San Francisco, USA\n <span>\n--- 99.24.18.13 ping statistics ---\n5 packets transmitted, 5 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 11.900/12.184/12.895/0.380 ms\n</span><span>ping -c 5 203.47.10.37 #</span> Adelaide, Australia\n <span>\n--- 203.47.10.37 ping statistics ---\n5 packets transmitted, 5 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 202.122/202.433/203.436/0.504 ms\n</span></code></pre>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#battery-health\"></a>Battery Health</h3>\n<p>It\u2019s unclear whether this is a concern in iOS,\nbut depending on how precise the results of <code>UIDevice</code> battery APIs are,\nyou may be able to use them to identify a device by its battery health.\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#olejnik_2015\">(Olejnik, Acar, Castelluccia, &amp; Diaz, 2016)</a></p>\n<pre data-lang=\"Swift\"><code><span>var</span> <span>timestamped<wbr>Battery<wbr>Levels</span><span>:</span> <span>[(</span><span>Date</span><span>,</span> <span>Float</span><span>)]</span> <span>=</span> <span>[]</span>\n <span>if</span> <span>UIDevice</span><span>.</span><span>current</span><span>.</span><span>is<wbr>Battery<wbr>Monitoring<wbr>Enabled</span> <span>{</span>\n <span>timestamped<wbr>Battery<wbr>Levels</span><span>.</span><span>append</span><span>((</span><span>Date</span><span>(),</span> <span>UIDevice</span><span>.</span><span>current</span><span>.</span><span>battery<wbr>Level</span><span>))</span>\n <span>}</span>\n </code></pre>\n<aside>\n<p>For this reason,\nbattery level APIs were\n<a rel=\"noopener noreferrer\" href=\"https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API\">removed in Firefox 55</a>.</p>\n<p>If this seems outlandish,\nconsider that Apple recently released a security update for iOS after researchers\ndemonstrated that small discrepancies in gyroscope calibration settings\ncould be used to uniquely identify devices.\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#zhang_2019\">(Zhang, Beresford, &amp; Sheret, 2019)</a></p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#and-so-on\"></a>And so on\u2026</h3>\n<p>Everything from your heartbeat, to your gait, to your\n<a rel=\"noopener noreferrer\" href=\"https://www.wired.co.uk/article/surveillance-technology-biometrics\">butt shape</a>\nseem capable of leaking your identity.\nIt can all be quite overwhelming.</p>\n<p>I mean,\nif a motivated individual can find your home address by\n<a rel=\"noopener noreferrer\" href=\"https://www.theverge.com/2019/10/11/20910551/stalker-attacked-pop-idol-reflection-pupils-selfies-videos-photos-google-street-view-japan\">cross-referencing the reflection in your eyes against Google Street view</a>,\nhow can we even stand a chance out there?</p>\n<hr>\n<p>Much as we may bemoan the current duopoly of mobile operating systems,\nwe might take some solace in the fact that\nat least one of the players actually cares about user privacy.\nThough it\u2019s unclear whether that\u2019s a fight that can ever be won.</p>\n<p>At times,\nour fate of being tracked and advertised to\nmay seem as inevitable as the victims in <em>It Follows</em>.</p>\n<p>But let\u2019s not forget that,\nas technologists, as people with a voice,\nwe\u2019re in a position to fight back.</p>\n<footer>\n<h5>References</h5>\n<ol>\n<li><span>de Montjoye, Y.-A., Hidalgo, C. A., Verleysen, M., &amp; Blondel, V. D. (2013). Unique in the Crowd: The privacy bounds of human mobility. <i>Scientific Reports</i>, <i>3</i>, 1376. https://doi.org/10.1038/srep01376</span></li>\n<li><span>Sweeney, L. (2000). Simple Demographics Often Identify People Uniquely. <i>Carnegie Mellon University, Data Privacy</i>. Working paper. Retrieved from http://dataprivacylab.org/projects/identifiability/</span></li>\n<li><span>Weinberg, Z., Cho, S., Christin, N., Sekar, V., &amp; Gill, P. (2018). How to Catch when Proxies Lie: Verifying the Physical Locations of Network Proxies with Active Geolocation. In <i>Proceedings of the Internet Measurement Conference 2018</i> (pp. 203\u2013217). New York, NY, USA: ACM. https://doi.org/10.1145/3278532.3278551</span></li>\n<li><span>Olejnik, \\L., Acar, G., Castelluccia, C., &amp; Diaz, C. (2016). The Leaking Battery. In <i>Revised Selected Papers of the 10th International Workshop on Data Privacy Management, and Security Assurance - Volume 9481</i> (pp. 254\u2013263). New York, NY, USA: Springer-Verlag New York, Inc. https://doi.org/10.1007/978-3-319-29883-2_18</span></li>\n<li><span>Zhang, J., Beresford, A. R., &amp; Sheret, I. (2019). SensorID: Sensor Calibration Fingerprinting for Smartphones. In <i>Proceedings of the 40th IEEE Symposium on Security and Privacy (SP)</i>. IEEE.</span></li>\n</ol>\n</footer>"
},
"visual": {
"url": "https://cdn.vox-cdn.com/thumbor/BkK9uk46u1ujrjGO0Jav3PCQ3g0=/0x225:5363x3800/1310x873/cdn.vox-cdn.com/uploads/chorus_image/image/59608177/PIA22227_full.0.jpg",
"width": 1310,
"height": 873,
"contentType": "image/jpeg"
},
"unread": true,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/885f2e01-d314-4e63-abac-17dcb063f5b5",
"label": "Programming"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578876975
},
{
"keywords": [
"Miscellaneous"
],
"originId": "https://nshipster.com/device-identifiers",
"fingerprint": "2f52765d",
"id": "CmHb1hXBWguYpGAhzgwJM9xvPVSYJFbt7KLqF3nqYQ0=_16e22eb0ef0:1e551:d4506071",
"updated": 1572505200000,
"author": "Mattt",
"summary": {
"direction": "ltr",
"content": "<p>For every era, there\u2019s a monster that embodies the anxieties of the age.</p>"
},
"alternate": [
{
"href": "http://feedproxy.google.com/~r/NSHipster/~3/hXb7k2avhFE/",
"type": "text/html"
}
],
"canonical": [
{
"href": "https://nshipster.com/device-identifiers/",
"type": "text/html"
}
],
"crawled": 1572543860464,
"title": "Device Identifiers and Fingerprinting on iOS",
"published": 1572505200000,
"origin": {
"streamId": "feed/http://feeds.feedburner.com/NSHipster",
"htmlUrl": "https://nshipster.com/",
"title": "NSHipster"
},
"content": {
"direction": "ltr",
"content": "<p>For every era,\nthere\u2019s a monster that embodies the anxieties of the age.</p>\n<p>At the dawn of the <a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Holocene\">Holocene</a>,\nour ancestors traced the contours of shadows cast by the campfire\nas they kept watch over the darkness.\nOnce we learned to read the night sky for navigation,\nsailors swapped stories of sea creatures like\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Leviathan\">Leviathan</a> and\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Siren_%28mythology%29\">Siren</a>\nto describe the dangers of open ocean\n(and the perils to be found on unfamiliar shores).</p>\n<p><a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Frankenstein%27s_monster\">Frankenstein\u2019s monster</a>\nwas as much the creation of Mary Shelley\nas it was a spiritual collaboration with\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Luigi_Galvani\">Luigi Galvani</a>.\nAnd Bram Stoker\u2019s\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/The_Jewel_of_Seven_Stars\">fictionalized account of the mummy\u2019s curse</a>\nwas more a response to the\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Egyptomania\">Egyptomania</a>\nand European colonialism\nof the nineteenth century\nthan any personal account of the Middle Kingdom.</p>\n<p>More recently,\nthe <a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/The_Beach_Girls_and_the_Monster\">\u201cmonster ruins a beach party\u201d</a>\ntrope of the 1960s\narose from concerns of teenager morality.\nWhile the\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/The_Day_Mars_Invaded_Earth\">Martians</a>\nwho invaded those same drive-in double features\nserved as a proxy for Cold War fears at the height of the\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Space_Race\">Space Race</a>.</p>\n<hr>\n<p>All of which begs the question:\n<em>\u201cWhat monster best exemplifies our present age?\u201d</em></p>\n<p>Consider the unnamed monster from the film\n<em><a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/It_Follows\">It Follows</a></em>:\na formless, supernatural being that relentlessly pursues its victims\nanywhere on the planet.</p>\n<p>Sounds a bit like the state of\n<dfn title=\"advertising technology\">ad tech</dfn>\nin 2019, no?</p>\n<aside>\n<p>Setting aside its central theme of carnal karma,\nwhich follows the same well-trodden path of horror as our aforementioned beach monsters\u2026</p>\n</aside>\n<hr>\n<p>This week on NSHipster \u2014\nin celebration of our favorite holiday\n<abbr title=\"(Halloween)\">\ud83c\udf83</abbr> \u2014\nwe\u2019re taking a look at the myriad ways that\nyou\u2019re being tracked on iOS,\nboth sanctioned and unsanctioned,\nhistorically and presently.\nSo gather around the campfire,\nand allow us to trace the contours of the unseen, formless monsters\nthat stalk us under cover of <a href=\"https://nshipster.com/dark-mode/\">Dark Mode</a>.</p>\n<hr>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#the-cynicism-of-marketing-and-advertising-technology\"></a>The Cynicism of Marketing and Advertising Technology</h2>\n<p>Contrary to our intuitions about natural selection in the marketplace,\nhistory is littered with examples of\ninferior-but-better-marketed products winning out over superior alternatives:\n<em>VHS vs. Betamax</em>,\n<em>Windows vs. Macintosh</em>,\netc.\n(According to the common wisdom of business folks, at least.)\nRegardless,\nmost companies reach a point where\n<em>\u201cif you build it, they will come\u201d</em>\nceases to be a politically viable strategy,\nand someone authorizes a marketing budget.</p>\n<p>Marketers are tasked with growing market share\nby identifying and communicating with as many potential customers as possible.\nAnd many \u2014\neither out of a genuine belief or formulated as a post hoc rationalization \u2014\ntake the potential benefit of their product\nas a license to flouting long-established customs of personal privacy.\nSo they enlist the help of one or more\nadvertising firms,\nwho promise to maximize their allocated budget and\nprovide some accountability for their spending\nby using technology to\n<dfn><strong>target</strong></dfn>,\n<dfn><strong>deliver</strong></dfn>, and\n<dfn><strong>analyze</strong></dfn>\nmessaging to consumers.</p>\n<p><strong>Each of these tasks is predicated on a consistent identity,\nwhich is why advertisers go to such great lengths to track you.</strong></p>\n<ul>\n<li>Without knowing who you are,\nmarketers have no way to tell if you\u2019re a likely or even potential customer.</li>\n<li>Without knowing where you are,\nmarketers have no way to reach you\nother than to post ads where they\u2019re likely to be seen.</li>\n<li>Without knowing what you do,\nmarketers have no way to tell if their ads worked\nor were seen at all.</li>\n</ul>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#apple-sanctioned-identifiers\"></a>Apple-Sanctioned Identifiers</h2>\n<p>Apple\u2019s provided various APIS to facilitate user identification\nfor various purposes:</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#universal-identifiers-udid\"></a>Universal Identifiers (UDID)</h3>\n<p>In the early days of iOS,\nApple provided a <code>unique<wbr>Identifier</code> property on <code>UIDevice</code> \u2014\naffectionately referred to as a\n<abbr title=\"Universal Device Identifier\">UDID</abbr>\n(<a href=\"https://nshipster.com/uuid-udid-unique-identifier/\">not to be confused with a UUID</a>).\nAlthough such functionality seems unthinkable today,\nthat property existed until iOS 5,\nuntil it was\ndeprecated and replaced by <code>identifier<wbr>For<wbr>Vendor</code> in iOS 6.</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#vendor-identifiers-idfv\"></a>Vendor Identifiers (IDFV)</h3>\n<p>Starting in iOS 6,\ndevelopers can use the\n<code>identifier<wbr>For<wbr>Vendor</code> property on <code>UIDevice</code>\nto generate a unique identifier that\u2019s shared across apps and extensions\ncreated by the same vendor\n(<abbr title=\"Identifier for Vendor\">IDFV</abbr>).</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>UIKit</span>\n <span>let</span> <span>idfv</span> <span>=</span> <span>UIDevice</span><span>.</span><span>current</span><span>.</span><span>identifier<wbr>For<wbr>Vendor</span> <span>// BD43813E-CFC5-4EEB-ABE2-94562A6E76CA</span>\n </code></pre>\n<aside>\n<p>According to <a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor\">the documentation</a>\n<code>identifier<wbr>For<wbr>Vendor</code> return <code>nil</code>\n\u201cafter the device has been restarted but before the user has unlocked the device.\u201d\nIt\u2019s unclear when that would be the case,\nbut something to keep in mind if your app does anything in the background.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#advertising-identifiers-idfa\"></a>Advertising Identifiers (IDFA)</h3>\n<p>Along with <code>identifier<wbr>For<wbr>Vendor</code> came the introduction of a new\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/adsupport\">AdSupport framework</a>,\nwhich Apple created to help distinguish\nidentification necessary for app functionality\nfrom anything in the service of advertising.</p>\n<p>The resulting\n<code>advertisingidentifier</code> property\n(affectionately referred to as\n<abbr title=\"Identifier for Advertisers\">IDFA</abbr> by its associates)\ndiffers from <code>identifier<wbr>For<wbr>Vendor</code>\nby returning the same value for everyone.\nThe value can change, for example,\nif the user <a rel=\"noopener noreferrer\" href=\"https://support.apple.com/en-us/HT205223\">resets their Advertising Identifier</a>\nor erases their device.</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Ad<wbr>Support</span>\n <span>let</span> <span>idfa</span> <span>=</span> <span>ASIdentifier<wbr>Manager</span><span>.</span><span>shared</span><span>()</span><span>.</span><span>advertising<wbr>Identifier</span>\n </code></pre>\n<p>If advertising tracking is limited,\nthe property returns a zeroed-out UUID instead.</p>\n<pre data-lang=\"Swift\"><code><span>idfa</span><span>.</span><span>uuid<wbr>String</span> <span>==</span> <span>&quot;00000000-0000-0000-0000-000000000000&quot;</span> <span>// true if the user has limited ad tracking</span>\n </code></pre>\n<aside>\n<p>Curiously,\nmacOS Mojave introduced a\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/adsupport/asidentifiermanager/2998811-clearadvertisingidentifier\"><code>clear<wbr>Advertising<wbr>Identifier()</code> method</a>,\nwhich appears to create a <em>\u201ctragedy of the commons\u201d</em> situation,\nwhere a single app could spoil things for everyone else\n<em>(not that this is a bad thing from the user\u2019s perspective!)</em></p>\n</aside>\n<aside>\n<p>There\u2019s also the curious case of the\n<code>is<wbr>Advertising<wbr>Tracking<wbr>Enabled</code> property.\nAccording to\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier\">the documentation</a>:</p>\n<blockquote>\n<p>Check the value of this property\nbefore performing any advertising tracking.\nIf the value is false,\nuse the advertising identifier only for the following purposes:\nfrequency capping,\nattribution,\nconversion events,\nestimating the number of unique users,\nadvertising fraud detection,\nand debugging.</p>\n</blockquote>\n<p>This kind of <em>\u201chonor system\u201d</em> approach compliance is confusing.\nAnd it makes you wonder what kind of usage\n<em>wouldn\u2019t</em> fall within these broad allowances.</p>\n<p>If you have any insight into how this is policed,\n<a rel=\"noopener noreferrer\" href=\"https://twitter.com/nshipster\">drop us a line</a> \u2014\nwe\u2019d love to hear more.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#devicecheck\"></a>DeviceCheck</h3>\n<p><code>identifier<wbr>For<wbr>Vendor</code> and <code>advertising<wbr>Identifier</code>\nprovide all the same functionality as the <code>unique<wbr>Identifier</code> property\nthey replaced in iOS 6,\nsave for one:\nthe ability to persist across device resets and app uninstalls.</p>\n<p>In iOS 11,\nApple quietly introduced the\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/devicecheck\">DeviceCheck framework</a>,\nwhich allows developers to assign two bits of information\nthat are persisted by Apple\n<strong>until the developer manually removes them</strong>.</p>\n<p>Interacting with the DeviceCheck framework should be familiar to\nanyone familiar with <a href=\"https://nshipster.com/apns-device-tokens\">APNS</a>:\nafter setting things up on App Store Connect and your servers,\nthe client generates tokens on the device,\nwhich are sent to your servers to set or query two bits of information:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Device<wbr>Check</span>\n <span>let</span> <span>device</span> <span>=</span> <span>DCDevice</span><span>.</span><span>current</span>\n <span>if</span> <span>device</span><span>.</span><span>is<wbr>Supported</span> <span>{</span>\n <span>device</span><span>.</span><span>generate<wbr>Token</span> <span>{</span> <span>data</span><span>,</span> <span>error</span> <span>in</span>\n <span>if</span> <span>let</span> <span>token</span> <span>=</span> <span>data</span><span>?</span><span>.</span><span>base64Encoded<wbr>String</span><span>()</span> <span>{</span>\n <var>send token to your server</var>\n <span>}</span>\n <span>}</span>\n <span>}</span>\n </code></pre>\n<p>Based on the device token and other information sent by the client,\nthe server tells Apple to set each bit value\nby sending a JSON payload like this:</p>\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;device_token&quot;</span><span>:</span><span> </span><span>&quot;QTk4Qk<wbr>FDNEIt<wbr>NTBDMy00Qjc5LTh<wbr>BRUEt<wbr>MDQ5RTQz<wbr>Rj<wbr>NGQz<wbr>U0Cg==&quot;</span><span>,</span><span>\n</span><span>&quot;transaction_id&quot;</span><span>:</span><span> </span><span>&quot;D98BA630-E225-4A2F-AFEC-BE3A3D591708&quot;</span><span>,</span><span>\n</span><span>&quot;timestamp&quot;</span><span>:</span><span> </span><span>1572531720</span><span>,</span><span>\n</span><span>&quot;bit0&quot;</span><span>:</span><span> </span><span>true</span><span>,</span><span>\n</span><span>&quot;bit1&quot;</span><span>:</span><span> </span><span>false</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n<p>To retrieve those two bits at a later point in time,\nthe server sends a payload without <code>bit0</code> and <code>bit1</code> fields:</p>\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;device_token&quot;</span><span>:</span><span> </span><span>&quot;QTk4Qk<wbr>FDNEIt<wbr>NTBDMy00Qjc5LTh<wbr>BRUEt<wbr>MDQ5RTQz<wbr>Rj<wbr>NGQz<wbr>U0Cg==&quot;</span><span>,</span><span>\n</span><span>&quot;transaction_id&quot;</span><span>:</span><span> </span><span>&quot;D98BA630-E225-4A2F-AFEC-BE3A3D591708&quot;</span><span>,</span><span>\n</span><span>&quot;timestamp&quot;</span><span>:</span><span> </span><span>1572532500</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n<p>If everything worked,\nApple\u2019s servers would respond with a <code>200</code> status code\nand the following JSON payload:</p>\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;bit0&quot;</span><span> </span><span>:</span><span> </span><span>true</span><span>\n</span><span>&quot;bit1&quot;</span><span> </span><span>:</span><span> </span><span>false</span><span>,</span><span>\n</span><span>&quot;last_update_time&quot;</span><span> </span><span>:</span><span> </span><span>&quot;2019-10&quot;</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n<aside>\n<p>Apple allegedly created the DeviceCheck framework\nto meet the needs of Uber\nin limiting the abuse of promotional codes.\nAlthough DeviceCheck proports to store <em>only</em> two bits of information\n(just enough to, for example,\ndetermine whether a device has ever been used to create an account\nand whether the device was ever associated with fraudulent activity),\nwe have (admittedly vague) concerns that the timestamp, even with truncation,\ncould be exploited to store more than two bits of information.</p>\n</aside>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#fingerprinting-in-todays-ios\"></a>Fingerprinting in Today\u2019s iOS</h2>\n<p>Despite these affordances by Apple,\nadvertisers have continued to work to circumvent user privacy protections\nand use any and all information at their disposal\nto identify users by other means.</p>\n<p>Over the years,\nApple\u2019s restricted access to information about\ndevice hardware,\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl\">installed apps</a>,\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_networking_wifi-info\">nearby WiFi networks</a>.\nThey\u2019ve required apps to request permission to\nget your current location,\naccess your camera and microphone,\nflip through your contacts, and\nfind and connect to Bluetooth accessories.\nThey\u2019ve taken bold steps to <a rel=\"noopener noreferrer\" href=\"https://webkit.org/blog/8828/intelligent-tracking-prevention-2-2/\">prevent user tracking in Safari</a>.</p>\n<p>For lack of this information,\ncompanies have had to get creative,\nlooking to forge unique identities from the scraps of what\u2019s still available.\nThis process of identification by a combination of external factors\nis known as <dfn><a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Fingerprint_%28computing%29\">fingerprinting</a></dfn>.</p>\n<p>The unfortunate reality is that we can be uniquely identified\nby vanishingly small amounts of information.\nFor example,\nindividuals within a population can be singled out by as few as\nfour timestamped coordinates\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#de_montjoye_2013\">(de Montjoye, Hidalgo, Verleysen, &amp; Blondel, 2013)</a>\nor little more than a birthday and a ZIP code\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#sweeney_2000\">(Sweeney, 2000)</a>.</p>\n<p>Every WWDC since 2012 has featured a session about Privacy,\nbut the only mention of fingerprinting specifically was\n<a rel=\"noopener noreferrer\" href=\"https://asciiwwdc.com/2014/sessions/715?q=fingerprinting\">a brief discussion in 2014</a>\nabout how to avoid doing it.</p>\n<p>By our count,\na determined party could use conventional, unrestricted APIs\nto generate a few dozen bits of randomness:</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#locale-information-36-bits\"></a>Locale Information (~36 bits)</h3>\n<p>Locale information is the greatest source of identifying information\non Apple platforms.\nThe combination of your\npreferred languages, region, calendar, time zone,\nand which keyboards you have installed\nsay a lot about who you are \u2014\nespecially if you have less conventional preferences.</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Foundation</span>\n <span>Locale</span><span>.</span><span>current</span><span>.</span><span>language<wbr>Code</span>\n <span>log2</span><span>(</span><span>Double</span><span>(</span><span>Locale</span><span>.</span><span>iso<wbr>Language<wbr>Codes</span><span>.</span><span>count</span><span>))</span> <span>// 9.217 bits</span>\n <span>Locale</span><span>.</span><span>current</span><span>.</span><span>region<wbr>Code</span>\n <span>log2</span><span>(</span><span>Double</span><span>(</span><span>Locale</span><span>.</span><span>iso<wbr>Region<wbr>Codes</span><span>.</span><span>count</span><span>))</span> <span>// 8 bits</span>\n <span>Locale</span><span>.</span><span>current</span><span>.</span><span>calendar</span><span>.</span><span>identifier</span>\n <span>// ~2^4 (16) Calendars</span>\n <span>Time<wbr>Zone</span><span>.</span><span>current</span><span>.</span><span>identifier</span>\n <span>log2</span><span>(</span><span>Double</span><span>(</span><span>Time<wbr>Zone</span><span>.</span><span>known<wbr>Time<wbr>Zone<wbr>Identifiers</span><span>.</span><span>count</span><span>))</span> <span>// 8.775 bits</span>\n <span>User<wbr>Defaults</span><span>.</span><span>standard</span><span>.</span><span>object</span><span>(</span><span>for<wbr>Key</span><span>:</span> <span>&quot;Apple<wbr>Keyboards&quot;</span><span>)</span>\n <span>// ~2^6 (64) i<wbr>OS keyboards</span>\n </code></pre>\n<aside>\n<p>We recently <a rel=\"noopener noreferrer\" href=\"https://twitter.com/mattt/status/1175817188646612992\">Tweeted</a>\nabout apps having unrestricted access to emoji keyboard information.\nWe\u2019ve since been informed that Apple is investigating the issue.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#accessibility-10-bits\"></a>Accessibility (~10 bits)</h3>\n<p>Accessibility preferences also provide a great deal of information,\nwith each individual setting contributing a single potential bit:</p>\n<pre data-lang=\"Swift\"><code><span>UIAccessibility</span><span>.</span><span>is<wbr>Bold<wbr>Text<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Shake<wbr>To<wbr>Undo<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Reduce<wbr>Motion<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Darker<wbr>System<wbr>Colors<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Reduce<wbr>Transparency<wbr>Enabled</span>\n <span>UIAccessibility</span><span>.</span><span>is<wbr>Assistive<wbr>Touch<wbr>Running</span>\n </code></pre>\n<p>Of the approximately ~25% of users who take advantage of\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically\">Dynamic Type</a>\nby configuring a preferred font size,\nthat selection may also be used to fingerprint you:</p>\n<pre data-lang=\"Swift\"><code><span>let</span> <span>application</span> <span>=</span> <span>UIApplication</span><span>.</span><span>shared</span>\n <span>application</span><span>.</span><span>preferred<wbr>Content<wbr>Size<wbr>Category</span>\n </code></pre>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#hardware-information-5-or-6-bits\"></a>Hardware Information (~5 or ~6 bits)</h3>\n<p>Although most of the juiciest bits have been locked down\nin OS updates over the years,\nthere\u2019s just enough to contribute a few more bits for purposes of identification.</p>\n<p>On iOS,\nyou can get the current model and amount of storage of a user\u2019s device:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>UIKit</span>\n <span>let</span> <span>device</span> <span>=</span> <span>UIDevice</span><span>.</span><span>current</span>\n <span>device</span><span>.</span><span>name</span> <span>// &quot;i<wbr>Phone 11 Pro&quot;</span>\n <span>let</span> <span>file<wbr>Manager</span> <span>=</span> <span>File<wbr>Manager</span><span>.</span><span>default</span>\n <span>if</span> <span>let</span> <span>path</span> <span>=</span> <span>file<wbr>Manager</span><span>.</span><span>urls</span><span>(</span><span>for</span><span>:</span> <span>.</span><span>library<wbr>Directory</span><span>,</span> <span>in</span><span>:</span> <span>.</span><span>system<wbr>Domain<wbr>Mask</span><span>)</span><span>.</span><span>last</span><span>?</span><span>.</span><span>path</span><span>,</span>\n <span>let</span> <span>system<wbr>Size</span> <span>=</span> <span>try</span><span>?</span> <span>file<wbr>Manager</span><span>.</span><span>attributes<wbr>Of<wbr>File<wbr>System</span><span>(</span><span>for<wbr>Path</span><span>:</span> <span>path</span><span>)[</span><span>.</span><span>system<wbr>Size</span><span>]</span> <span>as?</span> <span>Int</span>\n <span>{</span>\n <span>Measurement</span><span>&lt;</span><span>Unit<wbr>Information<wbr>Storage</span><span>></span><span>(</span><span>value</span><span>:</span> <span>Double</span><span>(</span><span>system<wbr>Size</span><span>),</span> <span>unit</span><span>:</span> <span>.</span><span>bytes</span><span>)</span>\n <span>.</span><span>converted</span><span>(</span><span>to</span><span>:</span> <span>.</span><span>gigabytes</span><span>)</span> <span>// ~256GB</span>\n <span>}</span>\n </code></pre>\n<p>With <a rel=\"noopener noreferrer\" href=\"https://support.apple.com/guide/iphone/supported-models-iphe3fa5df43/ios\">14 supported iOS devices</a>,\nmost having 3 configurations each,\nlet\u2019s say that this contributes about 32 possibilities, or 5 bits.</p>\n<p>You can go a few steps further on macOS,\nto further differentiate hardware by its processor count and amount of RAM:</p>\n<pre data-lang=\"Swift\"><code><span>process<wbr>Info</span><span>.</span><span>processor<wbr>Count</span> <span>// 8</span>\n <span>Measurement</span><span>&lt;</span><span>Unit<wbr>Information<wbr>Storage</span><span>></span><span>(</span><span>value</span><span>:</span> <span>Double</span><span>(</span><span>process<wbr>Info</span><span>.</span><span>physical<wbr>Memory</span><span>),</span>\n <span>unit</span><span>:</span> <span>.</span><span>bytes</span><span>)</span>\n <span>.</span><span>converted</span><span>(</span><span>to</span><span>:</span> <span>.</span><span>gigabytes</span><span>)</span> <span>// 16GB</span>\n </code></pre>\n<p>It\u2019s hard to get a sense of\n<a rel=\"noopener noreferrer\" href=\"https://everymac.com/systems/by_capability/minimum-macos-supported.html\">how many different Mac models are in use</a>,\nbut a reasonable estimate would be on the order of 2<sup>6</sup> or 2<sup>7</sup>.</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#cellular-network-2-bits\"></a>Cellular Network (~2 bits)</h3>\n<p>Knowing whether someone\u2019s phone is on Verizon or Vodaphone\ncan also be factored into a fingerprint.\nYou can use the <code>CTTelephony<wbr>Network<wbr>Info</code> class from the\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/coretelephony\">CoreTelephony framework</a>\nto lookup the providers for devices with cellular service:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Core<wbr>Telephony</span>\n <span>let</span> <span>network<wbr>Info</span> <span>=</span> <span>CTTelephony<wbr>Network<wbr>Info</span><span>()</span>\n <span>let</span> <span>carriers</span> <span>=</span> <span>network<wbr>Info</span><span>.</span><span>service<wbr>Subscriber<wbr>Cellular<wbr>Providers</span><span>?</span><span>.</span><span>values</span>\n <span>carriers</span><span>?</span><span>.</span><span>map</span> <span>{</span> <span>(</span><span>$0</span><span>.</span><span>mobile<wbr>Network<wbr>Code</span><span>,</span> <span>$0</span><span>.</span><span>mobile<wbr>Country<wbr>Code</span><span>)</span> <span>}</span>\n </code></pre>\n<p>The number of providers varies per country,\nbut using the 4 major carriers in United States\nas a guideline,\nwe can say carrier information would contribute about 2 bits\n(or more if you have multiple SIM cards installed).</p>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#communication-preferences-2-bits\"></a>Communication Preferences (2 bits)</h2>\n<p>More generally,\neven knowing whether someone can send texts or email at all\ncan be factored into a fingerprint.\nThis information can be gathered without permissions via\nthe <a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/messageui\">MessageUI framework</a>.</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>Message<wbr>UI</span>\n <span>MFMail<wbr>Compose<wbr>View<wbr>Controller</span><span>.</span><span>can<wbr>Send<wbr>Mail</span><span>()</span>\n <span>MFMessage<wbr>Compose<wbr>View<wbr>Controller</span><span>.</span><span>can<wbr>Send<wbr>Text</span><span>()</span>\n </code></pre>\n<h2>\n<a href=\"https://nshipster.com/device-identifiers/#additional-sources-of-identifying-information\"></a>Additional Sources of Identifying Information</h2>\n<p>If the use of digital fingerprinting seems outlandish,\nthat\u2019s just scratching the surface of how companies and researchers\nhave figured out how to circumvent your privacy.</p>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#geoip-and-relative-network-speeds\"></a>GeoIP and Relative Network Speeds</h3>\n<p>Although access to geolocation through conventional APIs\nrequires explicit authorization,\nthird parties may be able to get a general sense of where you are in the world\nbased on how you access the Internet.</p>\n<p><a rel=\"noopener noreferrer\" href=\"https://ipinfo.io\">Geolocation by source IP address</a>\nis used extensively for things like region locking and localization.\nYou could also combine this information with\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/library/archive/samplecode/SimplePing/Introduction/Intro.html#//apple_ref/doc/uid/DTS10000716\">ping-time measurements</a>\nto hosts in known locations\nto get a more accurate pinpoint on location <a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#weinberg_2018\">(Weinberg, Cho, Christin, Sekar, &amp; Gill, 2018)</a>:</p>\n<pre data-lang=\"Terminal\"><code><span>ping -c 5 99.24.18.13 #</span> San Francisco, USA\n <span>\n--- 99.24.18.13 ping statistics ---\n5 packets transmitted, 5 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 11.900/12.184/12.895/0.380 ms\n</span><span>ping -c 5 203.47.10.37 #</span> Adelaide, Australia\n <span>\n--- 203.47.10.37 ping statistics ---\n5 packets transmitted, 5 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 202.122/202.433/203.436/0.504 ms\n</span></code></pre>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#battery-health\"></a>Battery Health</h3>\n<p>It\u2019s unclear whether this is a concern in iOS,\nbut depending on how precise the results of <code>UIDevice</code> battery APIs are,\nyou may be able to use them to identify a device by its battery health.\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#olejnik_2015\">(Olejnik, Acar, Castelluccia, &amp; Diaz, 2016)</a></p>\n<pre data-lang=\"Swift\"><code><span>var</span> <span>timestamped<wbr>Battery<wbr>Levels</span><span>:</span> <span>[(</span><span>Date</span><span>,</span> <span>Float</span><span>)]</span> <span>=</span> <span>[]</span>\n <span>if</span> <span>UIDevice</span><span>.</span><span>current</span><span>.</span><span>is<wbr>Battery<wbr>Monitoring<wbr>Enabled</span> <span>{</span>\n <span>timestamped<wbr>Battery<wbr>Levels</span><span>.</span><span>append</span><span>((</span><span>Date</span><span>(),</span> <span>UIDevice</span><span>.</span><span>current</span><span>.</span><span>battery<wbr>Level</span><span>))</span>\n <span>}</span>\n </code></pre>\n<aside>\n<p>For this reason,\nbattery level APIs were\n<a rel=\"noopener noreferrer\" href=\"https://developer.mozilla.org/en-US/docs/Web/API/Battery_Status_API\">removed in Firefox 55</a>.</p>\n<p>If this seems outlandish,\nconsider that Apple recently released a security update for iOS after researchers\ndemonstrated that small discrepancies in gyroscope calibration settings\ncould be used to uniquely identify devices.\n<a rel=\"noopener noreferrer\" href=\"https://nshipster.com/device-identifiers/#zhang_2019\">(Zhang, Beresford, &amp; Sheret, 2019)</a></p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/device-identifiers/#and-so-on\"></a>And so on\u2026</h3>\n<p>Everything from your heartbeat, to your gait, to your\n<a rel=\"noopener noreferrer\" href=\"https://www.wired.co.uk/article/surveillance-technology-biometrics\">butt shape</a>\nseem capable of leaking your identity.\nIt can all be quite overwhelming.</p>\n<p>I mean,\nif a motivated individual can find your home address by\n<a rel=\"noopener noreferrer\" href=\"https://www.theverge.com/2019/10/11/20910551/stalker-attacked-pop-idol-reflection-pupils-selfies-videos-photos-google-street-view-japan\">cross-referencing the reflection in your eyes against Google Street view</a>,\nhow can we even stand a chance out there?</p>\n<hr>\n<p>Much as we may bemoan the current duopoly of mobile operating systems,\nwe might take some solace in the fact that\nat least one of the players actually cares about user privacy.\nThough it\u2019s unclear whether that\u2019s a fight that can ever be won.</p>\n<p>At times,\nour fate of being tracked and advertised to\nmay seem as inevitable as the victims in <em>It Follows</em>.</p>\n<p>But let\u2019s not forget that,\nas technologists, as people with a voice,\nwe\u2019re in a position to fight back.</p>\n<footer>\n<h5>References</h5>\n<ol>\n<li><span>de Montjoye, Y.-A., Hidalgo, C. A., Verleysen, M., &amp; Blondel, V. D. (2013). Unique in the Crowd: The privacy bounds of human mobility. <i>Scientific Reports</i>, <i>3</i>, 1376. https://doi.org/10.1038/srep01376</span></li>\n<li><span>Sweeney, L. (2000). Simple Demographics Often Identify People Uniquely. <i>Carnegie Mellon University, Data Privacy</i>. Working paper. Retrieved from http://dataprivacylab.org/projects/identifiability/</span></li>\n<li><span>Weinberg, Z., Cho, S., Christin, N., Sekar, V., &amp; Gill, P. (2018). How to Catch when Proxies Lie: Verifying the Physical Locations of Network Proxies with Active Geolocation. In <i>Proceedings of the Internet Measurement Conference 2018</i> (pp. 203\u2013217). New York, NY, USA: ACM. https://doi.org/10.1145/3278532.3278551</span></li>\n<li><span>Olejnik, \\L., Acar, G., Castelluccia, C., &amp; Diaz, C. (2016). The Leaking Battery. In <i>Revised Selected Papers of the 10th International Workshop on Data Privacy Management, and Security Assurance - Volume 9481</i> (pp. 254\u2013263). New York, NY, USA: Springer-Verlag New York, Inc. https://doi.org/10.1007/978-3-319-29883-2_18</span></li>\n<li><span>Zhang, J., Beresford, A. R., &amp; Sheret, I. (2019). SensorID: Sensor Calibration Fingerprinting for Smartphones. In <i>Proceedings of the 40th IEEE Symposium on Security and Privacy (SP)</i>. IEEE.</span></li>\n</ol>\n</footer>\n<img width=\"1\" alt=\"\" src=\"http://feeds.feedburner.com/~r/NSHipster/~4/hXb7k2avhFE\" height=\"1\">"
},
"visual": {
"url": "http://www.blogcdn.com/www.engadget.com/media/2013/10/irlbanner-1382819058.jpg",
"width": 620,
"height": 194,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 5062,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/e31b3fcb-27f6-4f3e-b96c-53902586e366",
"label": "Weblogs"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578867134
},
{
"originId": "https://inessential.com/2019/10/31/amateurs",
"fingerprint": "a55a55f8",
"id": "+jHfsXnBCVfCstSIW1WDumAyigT4rnsUPnI5WFxgnAU=_16e23877a2b:1e9e9:d4506071",
"summary": {
"direction": "ltr",
"content": "<p>One thing I\u2019m weirdly proud of is my position as an amateur programmer.</p>\n<p>When I point that out, people say, \u201cWell, but\u2026\u201d \u2014\u00a0and I know where they\u2019re going, that after 25 years of professional experience I\u2019m not what you think of when you think of \u201camateur.\u201d</p>\n<p>And yet, it\u2019s still <em>true</em>. It\u2019s just that I\u2019ve come out the other side, and now I get to work on exactly what I want to, the way I want to, without any thoughts of trying to make money at it.</p>\n<p>I can take risks! I can work with anybody who shows up! It\u2019s a pure thrill. It\u2019s like writing single-malt apps.</p>\n<p>And I would wish for more people to find themselves in this position \u2014 eventually, anyway \u2014\u00a0because I want to see what <em>they</em> would make.</p>\n<p>PS The Dictionary app on my Mac says of the origin of the word \u201camateur\u201d:</p>\n<blockquote>\n<p>late 18th century: from French, from Italian <em>amatore</em>, from Latin <em>amator</em> \u2018lover\u2019, from <em>amare</em> \u2018to love\u2019.</p>\n</blockquote>\n<p>Spot-on.</p>"
},
"alternate": [
{
"href": "https://inessential.com/2019/10/31/amateurs",
"type": "text/html"
}
],
"crawled": 1572554111531,
"title": "Amateurs",
"published": 1572553200000,
"origin": {
"streamId": "feed/http://ranchero.com/xml/rss.xml",
"htmlUrl": "https://inessential.com/",
"title": "inessential.com"
},
"visual": {
"url": "none"
},
"unread": true,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572578844326
},
{
"originId": "tag:blogger.com,1999:blog-8954608646904080796.post-6562845574025332924",
"fingerprint": "57441f5a",
"thumbnail": [
{
"url": "https://1.bp.blogspot.com/-nSjfvVEYsOE/XZ6cEycVw3I/AAAAAAAADTI/UMdV1Seh7R8c0GdV2RgwjuAoJLW47it1gCLcBGAsYHQ/s72-c/074.jpg",
"width": 72,
"height": 72
}
],
"id": "v0v+7Ya8tssIZvd3/pcnFRr3HwvY/5YK3FGc2t65c0Y=_16db6126dbf:685a:d4506071",
"updated": 1570675865985,
"author": "Edward Feser",
"alternate": [
{
"href": "http://edwardfeser.blogspot.com/2019/10/transubstantiation-and-hylemorphism.html",
"type": "text/html"
}
],
"crawled": 1570717724095,
"title": "Transubstantiation and hylemorphism",
"published": 1570675860000,
"origin": {
"streamId": "feed/http://edwardfeser.blogspot.com/feeds/posts/default",
"htmlUrl": "http://edwardfeser.blogspot.com/",
"title": "Edward Feser"
},
"content": {
"direction": "ltr",
"content": "<br><div><a href=\"https://1.bp.blogspot.com/-nSjfvVEYsOE/XZ6cEycVw3I/AAAAAAAADTI/UMdV1Seh7R8c0GdV2RgwjuAoJLW47it1gCLcBGAsYHQ/s1600/074.jpg\"><img border=\"0\" src=\"https://1.bp.blogspot.com/-nSjfvVEYsOE/XZ6cEycVw3I/AAAAAAAADTI/UMdV1Seh7R8c0GdV2RgwjuAoJLW47it1gCLcBGAsYHQ/s200/074.jpg\" data-original-width=\"171\" width=\"151\" data-original-height=\"226\" height=\"200\"></a></div><div><span>One of the key themes of the early modern philosophers\u2019 revolt against Scholasticism was a move away from an Aristotelian hylemorphist conception of the nature of physical substance to some variation or other of the mechanical philosophy.\u00a0 The other day I was asked a very interesting question: Can transubstantiation be formulated in terms of a mechanistic conception of physical substance rather than a hylemorphic one?\u00a0 My answer was that I would not peremptorily say that it cannot be, but that the suggestion certainly raises serious philosophical and theological problems.</span></div><a name=\"more\"></a><br> <div><span>Here\u2019s why.<span>\u00a0 </span>Hylemorphism in its most straightforward version roughly agrees with common sense about which of the things of everyday experience are distinct substances, which are different parts of the same substance, and which are aggregates rather than true substances.<span>\u00a0 </span>For example, it would say that a stone, a tree, and a dog are all distinct substances from one another; that a particular dog\u2019s nose and its right front leg are different parts of the same substance rather than distinct substances; and that a pile of stones is an aggregate rather than a substance in its own right.<span>\u00a0 </span>Of course, use of the term \u201csubstance\u201d in the technical Aristotelian sense isn\u2019t part of common sense, but even untutored common sense would surely involve the supposition that a stone, a tree, and a dog are all distinct <i>things</i> or <i>objects</i>, that the nose and leg of the dog are parts of a larger thing or object rather than separate things or objects, and that a pile of stones is a bunch of things or objects rather than a single object.<span>\u00a0 </span>At least to that extent, common sense would more or less agree with what I am calling a straightforward version of hylemorphism. <span>\u00a0</span>(See chapter 3 of <i><a href=\"https://www.amazon.com/Scholastic-Metaphysics-A-Contemporary-Introduction/dp/3868385444/ref=sr_1_1?ie=UTF8&qid=1391482601&sr=8-1&keywords=scholastic+metaphysics+a+contemporary+introduction\">Scholastic Metaphysics</a></i> for exposition and defense of the hylemorphist account of substance.)</span></div><div><span><br></span></div><div><span>Now, the mechanical world picture that pushed aside the hylemorphist model tended radically to revise the common sense understanding of physical objects in one of two general ways, depending on how mechanism was spelled out.<span>\u00a0 </span>It reduced ordinary physical objects either to mere aggregates of their innumerably many component parts, or to mere modes of some larger blob of which <i>they</i>were the parts.</span></div><div><span><br></span></div><div><span>Descartes and Spinoza essentially took the latter option.<span>\u00a0 </span>Though Descartes is often described as positing a plurality of extended substances alongside the plurality of thinking substances, his considered view seemed to be that strictly speaking, there is only a single extended substance, of which the ordinary objects of our experience are merely modifications.<span>\u00a0 </span>Spinoza more famously took such a position (or rather, he took it that <i>Deus sive Natura</i>was the one substance of which the ordinary physical objects of our experience are all modes).<span>\u00a0 </span>On this view, a stone, a tree, and a dog are not really distinct substances, but merely distinct aspects of one and the same substance \u2013 in something like the way common sense regards the color, weight, and shape of a stone to be mere modes of one and the same object, the stone.</span></div><div><span><br></span></div><div><span>Atomist and corpuscularian versions of the mechanical philosophy went in the other direction.<span>\u00a0 </span>They essentially make either atoms or corpuscles the true substances, and ordinary objects mere aggregates of these purported substances.<span>\u00a0 </span>Just as a pile of rocks is not a true substance but merely a collection of substances (or as the hylemorphist would say, being a pile of rocks is a merely accidental form rather than a substantial form), so too a stone, a tree, or a dog is on this view merely a collection of particles.<span>\u00a0 </span>In effect, the particles are the true substances, and the stone, tree, or dog is like the pile \u2013 a relatively superficial arrangement of metaphysically more fundamental entities.</span></div><div><span><br></span></div><div><span>So, to come to transubstantiation, the idea, of course, is that in the Eucharist, while the accidents of bread and wine remain, the substance of bread and wine are miraculously replaced with that of Christ.<span>\u00a0 </span>Suppose, then, that we were to adopt Descartes\u2019 version of the mechanical philosophy, on which there is just one big physical substance underlying all the things ordinary perceptual experience reveals to us.<span>\u00a0 </span>That would entail that the substance that underlies the accidents of bread and wine that are about to be consecrated is the very same substance as that which underlies stones, trees, dogs, cats, human bodies, apples, oranges, the sun, the moon, water, lead, gold, and every other thing we see, hear, taste, touch, or smell.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>But in that case, when transubstantiation occurs, it is not just the substance underlying the accidents of bread and wine that is replaced, but the substance underlying all of these other things too.<span>\u00a0 </span>In other words, after transubstantiation occurs, it is really the body and blood of Christ that underlies what we perceive as stones, trees, dogs, cats, human bodies, the sun, the moon, water, etc.!<span>\u00a0 </span><i>Everything</i> in the physical world would be transubstantiated.<span>\u00a0 </span>We would be left with a kind of pantheism.<span>\u00a0 </span>Absolutely <i>every</i> physical thing would have to treated with the same reverence that the Eucharist is, because every physical thing would be the Eucharist!</span></div><div><span><br></span></div><div><span>Another bizarre implication of this is that transubstantiation could occur only once.<span>\u00a0 </span>For only at the first time it occurs is the one physical substance replaced by that of Christ.<span>\u00a0 </span>If a priest were ever to try to consecrate bread and wine again, he would fail, because there is no longer any physical substance there to <i>be</i> replaced.<span>\u00a0 </span>It is <i>already</i>the body and blood of Christ.</span></div><div><span><br></span></div><div><span>Suppose we went the other route, that of either atomism or corpuscularianism.<span>\u00a0 </span>Then, like stones, trees, and dogs, bread and wine would not be true substances but merely accidental collections of innumerably many true substances.<span>\u00a0 </span>They would be like a pile of rocks, only instead it would be fundamental particles (atoms or corpuscles, depending on your favored version of the mechanical philosophy) that would be piled up.<span>\u00a0 </span>But in that case, exactly <i>what </i>is the substance that is replaced when transubstantiation occurs?<span>\u00a0 </span>Neither the substance of the bread nor that of the wine can be what is replaced, because on this view they just <i>aren\u2019t</i>true substances in the first place.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Should we say that it is each particle that makes up the aggregate that is transubstantiated (just as Catholic theology allows that many hosts at a time may be consecrated at Mass)?<span>\u00a0\u00a0 </span>But there are several problems with that suggestion.<span>\u00a0 </span>The first is that it is hard to know how to give a principled answer to the question what the <i>boundaries</i> are between those particles that make up the aggregate and those that are not part of it \u2013 and thus between those particles that are transubstantiated, and those that are not.<span>\u00a0 </span>The reason is that the boundaries of an aggregate are much less well defined than those of a substance.<span>\u00a0 </span>Is a stone that is two millimeters away from a pile of stones itself part of the pile or not?<span>\u00a0 </span>And is a particle that falls from the host part of <i>that</i> (purported) aggregate of particles or not?<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>If we think of the host on the model of an Aristotelian <i>substance</i>, then we can say that a fallen particle is part of the host, like a body part that has been severed, as it were.<span>\u00a0 </span>But, again, if instead we think in terms of the model of a pile of stones or some other aggregate, the answer isn\u2019t as clear.</span></div><div><span><br></span></div><div><span>A second problem is that in Catholic theology, not any old matter can be used when consecrating the Eucharist.<span>\u00a0 </span>It has to be bread and wine, specifically.<span>\u00a0 </span>But on the interpretation under consideration, according to which bread and wine are not true substances, it is really the particles (either atoms or corpuscles) that are being consecrated.<span>\u00a0 </span>And the atoms or corpuscles that make up bread and wine are essentially the same as those that make up everything else (just as the stones that make up a pile can be essentially of the same type as those that are used instead to make up a wall).<span>\u00a0 </span>In that case, though, it would be hard to see why there is anything special about bread and wine.<span>\u00a0 </span>Why couldn\u2019t <i>any</i> old physical thing be consecrated, if every physical thing is essentially just the same kind of stuff in relatively superficial differences of configuration?</span></div><div><span><br></span></div><div><span>A third problem is that canon law says that a Catholic ought to receive communion at most only once (or in some special circumstances, perhaps twice) a day.<span>\u00a0 </span>But on the interpretation under consideration, one would in effect be consuming <i>millions</i> of consecrated hosts insofar as each of the millions of particles that make up what common sense regards as a single host was being independently transubstantiated.</span></div><div><span><br></span></div><div><span>Perhaps such problems could be solved, though I am doubtful.\u00a0 Anyway, the issue illustrates the unexpected implications that philosophical assumptions can have for theology.\u00a0 (And thus the caution that any Catholic ought to exercise before embracing philosophical novelties.\u00a0 The Scholastics knew what they were doing.)</span></div>"
},
"visual": {
"url": "https://cdn.vox-cdn.com/thumbor/qEtBNTmNKQvUro7McqHPXL-2OOM=/0x0:6720x4480/1310x873/cdn.vox-cdn.com/uploads/chorus_image/image/59664621/marshall_majorIII_aniconinthemaking_product_rgb_highres_2.0.jpg",
"width": 1310,
"height": 878,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 3562,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/fbdcd69b-7e27-4b6a-bfed-6584b944155d",
"label": "\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb Renamed"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572500351314
},
{
"keywords": [
"Xcode"
],
"originId": "https://nshipster.com/metrickit",
"recrawled": 1572363511019,
"updateCount": 2,
"fingerprint": "9be1d5cd",
"id": "CmHb1hXBWguYpGAhzgwJM9xvPVSYJFbt7KLqF3nqYQ0=_16df9da832d:14579:d4506071",
"updated": 1571641200000,
"author": "Mattt",
"summary": {
"direction": "ltr",
"content": "<p>At WWDC this year, Apple announced a coordinated effort between Xcode 11 and iOS 13 to bring new insights to developers about how their apps are performing in the field.</p>"
},
"alternate": [
{
"href": "http://feedproxy.google.com/~r/NSHipster/~3/o2-j6xKjBrA/",
"type": "text/html"
}
],
"canonical": [
{
"href": "https://nshipster.com/metrickit/",
"type": "text/html"
}
],
"crawled": 1571854910253,
"title": "MetricKit",
"published": 1571641200000,
"origin": {
"streamId": "feed/http://feeds.feedburner.com/NSHipster",
"htmlUrl": "https://nshipster.com/",
"title": "NSHipster"
},
"content": {
"direction": "ltr",
"content": "<p>As an undergraduate student,\nI had a radio show called\n<em>\u201cGoodbye, Blue Monday\u201d</em>\n(I was really into Vonnegut at the time).\nIt was nothing glamorous \u2014\njust a weekly, 2-hour slot at the end of the night\nbefore the station switched into automation.</p>\n<p>If you happened to be driving through the hills of Pittsburgh, Pennsylvania\nlate at night with your radio tuned to\n<a rel=\"noopener noreferrer\" href=\"http://www.wrct.org\"><abbr title=\"Radio Carnegie Tech\">WRCT</abbr> 88.3</a>,\nyou\u2019d have heard an eclectic mix of\n<a rel=\"noopener noreferrer\" href=\"https://beta.music.apple.com/us/album/acoustica/410402556\">Contemporary Classical</a>,\n<a rel=\"noopener noreferrer\" href=\"https://beta.music.apple.com/us/album/a-funk-odyssey/203132910\">Acid Jazz</a>,\n<a rel=\"noopener noreferrer\" href=\"https://beta.music.apple.com/us/album/ma-quale-idea-single/1415038751\">Italian Disco</a>, and\n<a rel=\"noopener noreferrer\" href=\"https://beta.music.apple.com/us/album/kind-of-blue/268443092\">Bebop</a>.\nThat, and the stilting, dulcet baritone of\na college kid doing his best impersonation of\n<a rel=\"noopener noreferrer\" href=\"http://old.post-gazette.com/magazine/20010404mowod4.asp\">Tony Mowod</a>.</p>\n<p>Sitting there in the booth,\nwaiting for tracks to play out before launching into an\n<abbr title=\"Federal Communications Commission\">FCC</abbr>-mandated\n<abbr title=\"Public Service Announcement\">PSA</abbr>\nor on-the-hour\n<a rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Station_identification\">station identification</a>,\nI\u2019d wonder:\n<em>Is anyone out there listening?</em>\n<em>And if they were, did they like it?</em>\nI could\u2019ve been broadcasting static the whole time and been none the wiser.</p>\n<p>The same thoughts come to mind whenever I submit a build to App Store Connect\u2026\nbut then I\u2019ll remember that, unlike radio,\nyou <em>can</em> actually know these things!\nAnd the latest improvements in Xcode 11 make it easier than ever\nto get an idea of how your apps are performing in the field.</p>\n<p>We\u2019ll cover everything you need to know in this week\u2019s NSHipster article.\nSo as they say on the radio:\n<em>\u201cDon\u2019t touch that dial (it\u2019s got jam on it)\u201d.</em></p>\n<hr>\n<p>MetricKit is a new framework in iOS 13\nfor collecting and processing battery and performance metrics.\nIt was announced at <a href=\"https://nshipster.com/wwdc-2019/\">WWDC this year</a>\nalong with XCTest Metrics and the Xcode Metrics Organizer\nas part of a coordinated effort to bring new insights to developers\nabout how their apps are performing in the field.</p>\n<figure>\n<picture>\n<source srcset=\"https://nshipster.com/assets/metrickit-diagram--dark-b7358fa1e9bdf87502044ad241ffcfe5bb904cb7d1bf948d38b0f35b3e93fc59.png\" media=\"(prefers-color-scheme: dark)\">\n<img alt=\"MetricKit Diagram\" src=\"https://nshipster.com/assets/metrickit-diagram--light-0dd5dd5af36c169873c46b2be3155f50aa5ccbfd98a8794bdd5e0d510eb9a42d.png\">\n</picture>\n<figcaption>Diagram from WWDC 2019 Session 417: <a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/videos/play/wwdc2019/417/\">&quot;Improving Battery Life and Performance&quot;</a></figcaption>\n</figure>\n<p>Apple automatically collects metrics from apps installed on the App Store.\nYou can view them in Xcode 11\nby opening the Organizer (<kbd>\u2325</kbd><kbd>\u2318</kbd><kbd>\u21e7</kbd><kbd>O</kbd>)\nand selecting the new Metrics tab.</p>\n<p>MetricKit complement Xcode Organizer Metrics by providing a programmatic way to\nreceive daily information about how your app is performing in the field.\nWith this information,\nyou can collect, aggregate, and analyze on your own in greater detail\nthan you can through Xcode.</p>\n<h2>\n<a href=\"https://nshipster.com/metrickit/#understanding-app-metrics\"></a>Understanding App Metrics</h2>\n<p>Metrics can help uncover issues you might not have seen while testing locally,\nand allow you to track changes across different versions of your app.\nFor this initial release,\nApple has focused on the two metrics that matter most to users:\n<dfn>battery usage</dfn> and <dfn>performance</dfn>.</p>\n<h3>\n<a href=\"https://nshipster.com/metrickit/#battery-usage\"></a>Battery Usage</h3>\n<picture>\n<source srcset=\"https://nshipster.com/assets/metrickit-battery-usage--dark-a04760e5bcf6bb9da1153f10b37c074d3ecee9cba5887cf1065bee0a4e545d95.png\" media=\"(prefers-color-scheme: dark)\">\n<img alt=\"MetricKit Diagram\" src=\"https://nshipster.com/assets/metrickit-battery-usage--light-999245ecb5a77e77835214efce028de4fe854da718ef7b7b86730ad8812383ca.png\">\n</picture>\n<p>Battery life depends on a lot of different factors.\nPhysical aspects like the age of the device and\nthe number of charge cycles are determinative,\nbut the way your phone is used matters, too.\nThings like CPU usage,\nthe brightness of the display and the colors on the screen,\nand how often radios are used to fetch data or get your current location \u2014\nall of these can have a big impact.\nBut the main thing to keep in mind is that\nusers care a lot about battery life.</p>\n<p>Aside from how good the camera is,\nthe amount of time between charges\nis <em>the</em> deciding factor when someone buys a new phone these days.\nSo when their new, expensive phone <em>doesn\u2019t</em> make it through the day,\nthey\u2019re going to be pretty unhappy.</p>\n<p>Until recently,\nApple\u2019s taken most of the heat on battery issues.\nBut since iOS 12 and its new\n<a rel=\"noopener noreferrer\" href=\"https://support.apple.com/en-us/HT201264\">Battery Usage screen</a> in Settings,\nusers now have a way to tell when their favorite app is to blame.\nFortunately,\nwith iOS 13 you now have everything you need to make sure\nyour app doesn\u2019t run afoul of reasonable energy usage.</p>\n<h3>\n<a href=\"https://nshipster.com/metrickit/#performance\"></a>Performance</h3>\n<p>Performance is another key factor in the overall user experience.\nNormally, we might look to stats like\nprocessor clock speed or <a href=\"https://nshipster.com/uitableviewheaderfooterview/\">frame rate</a>\nas a measure of performance.\nBut instead,\nApple\u2019s focusing on less abstract and more actionable metrics:</p>\n<dl>\n<dt>Hang Rate</dt>\n<dd>How often is the main / UI thread blocked,\nsuch that the app is unresponsive to user input?</dd>\n<dt>Launch Time</dt>\n<dd>How long does an app take to become usable after the user taps its icon?</dd>\n<dt>Peak Memory &amp; Memory at Suspension</dt>\n<dd>How much memory does the app use at its peak\nand just before entering the background?</dd>\n<dt>Disk Writes</dt>\n<dd>How often does the app write to disk,\nwhich \u2014 if you didn\u2019t already know \u2014 is a\n<a rel=\"noopener noreferrer\" href=\"https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html\">comparatively slow operation</a>\n<em>(even with the flash storage on an iPhone!)</em>\n</dd>\n</dl>\n<h2>\n<a href=\"https://nshipster.com/metrickit/#using-metrickit\"></a>Using MetricKit</h2>\n<p>From the perspective of an API consumer,\nit\u2019s hard to imagine how MetricKit could be easier to incorporate.\nAll you need is for some part of your app to serve as\na metric subscriber\n(an obvious choice is your <code>App<wbr>Delegate</code>),\nand for it to be added to the shared <code>MXMetric<wbr>Manager</code>:</p>\n<pre data-lang=\"Swift\"><code><span>import</span> <span>UIKit</span>\n <span>import</span> <span>Metric<wbr>Kit</span>\n <span>@UIApplication<wbr>Main</span>\n <span>class</span> <span>App<wbr>Delegate</span><span>:</span> <span>UIResponder</span><span>,</span> <span>UIApplication<wbr>Delegate</span> <span>{</span>\n <span>func</span> <span>application</span><span>(</span><span>_</span> <span>application</span><span>:</span> <span>UIApplication</span><span>,</span> <span>did<wbr>Finish<wbr>Launching<wbr>With<wbr>Options</span> <span>launch<wbr>Options</span><span>:</span> <span>[</span><span>UIApplication</span><span>.</span><span>Launch<wbr>Options<wbr>Key</span><span>:</span> <span>Any</span><span>]?)</span> <span>-></span> <span>Bool</span> <span>{</span>\n <span>MXMetric<wbr>Manager</span><span>.</span><span>shared</span><span>.</span><span>add</span><span>(</span><span>self</span><span>)</span>\n <span>return</span> <span>true</span>\n <span>}</span>\n <span>func</span> <span>application<wbr>Will<wbr>Terminate</span><span>(</span><span>_</span> <span>application</span><span>:</span> <span>UIApplication</span><span>)</span> <span>{</span>\n <span>MXMetric<wbr>Manager</span><span>.</span><span>shared</span><span>.</span><span>remove</span><span>(</span><span>self</span><span>)</span>\n <span>}</span>\n <span>}</span>\n <span>extension</span> <span>App<wbr>Delegate</span><span>:</span> <span>MXMetric<wbr>Manager<wbr>Subscriber</span> <span>{</span>\n <span>func</span> <span>did<wbr>Receive</span><span>(</span><span>_</span> <span>payloads</span><span>:</span> <span>[</span><span>MXMetric<wbr>Payload</span><span>])</span> <span>{</span>\n <var>...</var>\n <span>}</span>\n <span>}</span>\n </code></pre>\n<p>iOS automatically collects samples while your app is being used,\nand once per day (every 24 hours),\nit\u2019ll send an aggregated report with those metrics.</p>\n<p>To verify that your <code>MXMetric<wbr>Manager<wbr>Subscriber</code>\nis having its delegate method called as expected,\nselect Simulate MetricKit Payloads from the Debug menu\nwhile Xcode is running your app.</p>\n<aside>\n<p>The Simulate MetricKit Payloads menu item\nrequires the app to be running on an actual device\nand is disabled for Simulator builds.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/metrickit/#annotating-critical-code-sections-with-signposts\"></a>Annotating Critical Code Sections with Signposts</h3>\n<p>In addition to the baseline statistics collected for you,\nyou can use the\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/metrickit/3214364-mxsignpost\"><code>mx<wbr>Signpost</code></a> function\nto collect metrics around the most important parts of your code.\nThis <a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/os/3019241-os_signpost\">signpost</a>-backed API\ncaptures CPU time, memory, and writes to disk.</p>\n<p>For example,\nif part of your app did post-processing on audio streams,\nyou might annotate those regions with metric signposts\nto determine the energy and performance impact of that work:</p>\n<pre data-lang=\"Swift\"><code><span>let</span> <span>audio<wbr>Log<wbr>Handle</span> <span>=</span> <span>MXMetric<wbr>Manager</span><span>.</span><span>make<wbr>Log<wbr>Handle</span><span>(</span><span>category</span><span>:</span> <span>&quot;Audio&quot;</span><span>)</span>\n <span>func</span> <span>process<wbr>Audio<wbr>Stream</span><span>()</span> <span>{</span>\n <span>mx<wbr>Signpost</span><span>(</span><span>.</span><span>begin</span><span>,</span> <span>log</span><span>:</span> <span>audio<wbr>Log<wbr>Handle</span><span>,</span> <span>name</span><span>:</span> <span>&quot;Process<wbr>Audio<wbr>Stream&quot;</span><span>)</span>\n <var>...</var>\n <span>mx<wbr>Signpost</span><span>(</span><span>.</span><span>end</span><span>,</span> <span>log</span><span>:</span> <span>audio<wbr>Log<wbr>Handle</span><span>,</span> <span>name</span><span>:</span> <span>&quot;Process<wbr>Audio<wbr>Stream&quot;</span><span>)</span>\n <span>}</span>\n </code></pre>\n<h2>\n<a href=\"https://nshipster.com/metrickit/#creating-a-self-hosted-web-service-for-collecting-app-metrics\"></a>Creating a Self-Hosted Web Service for Collecting App Metrics</h2>\n<p>Now that you have this information,\nwhat do you do with it?\nHow do we fill that <code><var>...</var></code> placeholder in our implementation of <code>did<wbr>Receive(_:)</code>?</p>\n<p>You <em>could</em> pass that along to some paid analytics or crash reporting service,\n<em>but where\u2019s the fun in that</em>?\nLet\u2019s build our own web service to collect these for further analysis:</p>\n<h3>\n<a href=\"https://nshipster.com/metrickit/#storing-and-querying-metrics-with-postgresql\"></a>Storing and Querying Metrics with PostgreSQL</h3>\n<p>The <code>MXMetric<wbr>Payload</code> objects received by metrics manager subscribers\nhave a convenient\n<a rel=\"noopener noreferrer\" href=\"https://developer.apple.com/documentation/metrickit/mxmetricpayload/3131907-jsonrepresentation\"><code>json<wbr>Representation()</code></a> method\nthat generates something like this:</p>\n<details>\n\n<pre data-lang=\"JSON\"><code><span>{</span><span>\n</span><span>&quot;location<wbr>Activity<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cumulative<wbr>Best<wbr>Accuracy<wbr>For<wbr>Navigation<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;20 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Best<wbr>Accuracy<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;30 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Hundred<wbr>Meters<wbr>Accuracy<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;30 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Nearest<wbr>Ten<wbr>Meters<wbr>Accuracy<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;30 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Kilometer<wbr>Accuracy<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;20 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Three<wbr>Kilometers<wbr>Accuracy<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;20 sec&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;cellular<wbr>Condition<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cell<wbr>Condition<wbr>Time&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogram<wbr>Num<wbr>Buckets&quot;</span><span>:</span><span> </span><span>3</span><span>,</span><span>\n</span><span>&quot;histogram<wbr>Value&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;0&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>20</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;1 bars&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;1 bars&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;1&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>30</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;2 bars&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;2 bars&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;2&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>50</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;3 bars&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;3 bars&quot;</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;meta<wbr>Data&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;app<wbr>Build<wbr>Version&quot;</span><span>:</span><span> </span><span>&quot;0&quot;</span><span>,</span><span>\n</span><span>&quot;os<wbr>Version&quot;</span><span>:</span><span> </span><span>&quot;i<wbr>Phone OS 13.1.3 (17A878)&quot;</span><span>,</span><span>\n</span><span>&quot;region<wbr>Format&quot;</span><span>:</span><span> </span><span>&quot;US&quot;</span><span>,</span><span>\n</span><span>&quot;device<wbr>Type&quot;</span><span>:</span><span> </span><span>&quot;i<wbr>Phone9,2&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;gpu<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cumulative<wbr>GPUTime&quot;</span><span>:</span><span> </span><span>&quot;20 sec&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;memory<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;peak<wbr>Memory<wbr>Usage&quot;</span><span>:</span><span> </span><span>&quot;200,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;average<wbr>Suspended<wbr>Memory&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;average<wbr>Value&quot;</span><span>:</span><span> </span><span>&quot;100,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;standard<wbr>Deviation&quot;</span><span>:</span><span> </span><span>0</span><span>,</span><span>\n</span><span>&quot;sample<wbr>Count&quot;</span><span>:</span><span> </span><span>500</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;signpost<wbr>Metrics&quot;</span><span>:</span><span> </span><span>[</span><span>\n</span><span>{</span><span>\n</span><span>&quot;signpost<wbr>Interval<wbr>Data&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogrammed<wbr>Signpost<wbr>Durations&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogram<wbr>Num<wbr>Buckets&quot;</span><span>:</span><span> </span><span>3</span><span>,</span><span>\n</span><span>&quot;histogram<wbr>Value&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;0&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>50</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;0 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;100 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;1&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>60</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;100 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;400 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;2&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>30</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;400 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;700 ms&quot;</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;signpost<wbr>Cumulative<wbr>CPUTime&quot;</span><span>:</span><span> </span><span>&quot;30,000 ms&quot;</span><span>,</span><span>\n</span><span>&quot;signpost<wbr>Average<wbr>Memory&quot;</span><span>:</span><span> </span><span>&quot;100,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;signpost<wbr>Cumulative<wbr>Logical<wbr>Writes&quot;</span><span>:</span><span> </span><span>&quot;600 k<wbr>B&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;signpost<wbr>Category&quot;</span><span>:</span><span> </span><span>&quot;Test<wbr>Signpost<wbr>Category1&quot;</span><span>,</span><span>\n</span><span>&quot;signpost<wbr>Name&quot;</span><span>:</span><span> </span><span>&quot;Test<wbr>Signpost<wbr>Name1&quot;</span><span>,</span><span>\n</span><span>&quot;total<wbr>Signpost<wbr>Count&quot;</span><span>:</span><span> </span><span>30</span><span>\n</span><span>},</span><span>\n</span><span>{</span><span>\n</span><span>&quot;signpost<wbr>Interval<wbr>Data&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogrammed<wbr>Signpost<wbr>Durations&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogram<wbr>Num<wbr>Buckets&quot;</span><span>:</span><span> </span><span>3</span><span>,</span><span>\n</span><span>&quot;histogram<wbr>Value&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;0&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>60</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;0 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;200 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;1&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>70</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;201 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;300 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;2&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>80</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;301 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;500 ms&quot;</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;signpost<wbr>Cumulative<wbr>CPUTime&quot;</span><span>:</span><span> </span><span>&quot;50,000 ms&quot;</span><span>,</span><span>\n</span><span>&quot;signpost<wbr>Average<wbr>Memory&quot;</span><span>:</span><span> </span><span>&quot;60,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;signpost<wbr>Cumulative<wbr>Logical<wbr>Writes&quot;</span><span>:</span><span> </span><span>&quot;700 k<wbr>B&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;signpost<wbr>Category&quot;</span><span>:</span><span> </span><span>&quot;Test<wbr>Signpost<wbr>Category2&quot;</span><span>,</span><span>\n</span><span>&quot;signpost<wbr>Name&quot;</span><span>:</span><span> </span><span>&quot;Test<wbr>Signpost<wbr>Name2&quot;</span><span>,</span><span>\n</span><span>&quot;total<wbr>Signpost<wbr>Count&quot;</span><span>:</span><span> </span><span>40</span><span>\n</span><span>}</span><span>\n</span><span>],</span><span>\n</span><span>&quot;display<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;average<wbr>Pixel<wbr>Luminance&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;average<wbr>Value&quot;</span><span>:</span><span> </span><span>&quot;50 apl&quot;</span><span>,</span><span>\n</span><span>&quot;standard<wbr>Deviation&quot;</span><span>:</span><span> </span><span>0</span><span>,</span><span>\n</span><span>&quot;sample<wbr>Count&quot;</span><span>:</span><span> </span><span>500</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;cpu<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cumulative<wbr>CPUTime&quot;</span><span>:</span><span> </span><span>&quot;100 sec&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;network<wbr>Transfer<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cumulative<wbr>Cellular<wbr>Download&quot;</span><span>:</span><span> </span><span>&quot;80,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Wifi<wbr>Download&quot;</span><span>:</span><span> </span><span>&quot;60,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Cellular<wbr>Upload&quot;</span><span>:</span><span> </span><span>&quot;70,000 k<wbr>B&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Wifi<wbr>Upload&quot;</span><span>:</span><span> </span><span>&quot;50,000 k<wbr>B&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;disk<wbr>IOMetrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cumulative<wbr>Logical<wbr>Writes&quot;</span><span>:</span><span> </span><span>&quot;1,300 k<wbr>B&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;application<wbr>Launch<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogrammed<wbr>Time<wbr>To<wbr>First<wbr>Draw<wbr>Key&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogram<wbr>Num<wbr>Buckets&quot;</span><span>:</span><span> </span><span>3</span><span>,</span><span>\n</span><span>&quot;histogram<wbr>Value&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;0&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>50</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;1,000 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;1,010 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;1&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>60</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;2,000 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;2,010 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;2&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>30</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;3,000 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;3,010 ms&quot;</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;histogrammed<wbr>Resume<wbr>Time&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogram<wbr>Num<wbr>Buckets&quot;</span><span>:</span><span> </span><span>3</span><span>,</span><span>\n</span><span>&quot;histogram<wbr>Value&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;0&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>60</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;200 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;210 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;1&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>70</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;300 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;310 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;2&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>80</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;500 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;510 ms&quot;</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;application<wbr>Time<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;cumulative<wbr>Foreground<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;700 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Background<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;40 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Background<wbr>Audio<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;30 sec&quot;</span><span>,</span><span>\n</span><span>&quot;cumulative<wbr>Background<wbr>Location<wbr>Time&quot;</span><span>:</span><span> </span><span>&quot;30 sec&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;time<wbr>Stamp<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;2019-10-22 06:59:00 +0000&quot;</span><span>,</span><span>\n</span><span>&quot;application<wbr>Responsiveness<wbr>Metrics&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogrammed<wbr>App<wbr>Hang<wbr>Time&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;histogram<wbr>Num<wbr>Buckets&quot;</span><span>:</span><span> </span><span>3</span><span>,</span><span>\n</span><span>&quot;histogram<wbr>Value&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;0&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>50</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;0 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;100 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;1&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>60</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;100 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;400 ms&quot;</span><span>\n</span><span>},</span><span>\n</span><span>&quot;2&quot;</span><span>:</span><span> </span><span>{</span><span>\n</span><span>&quot;bucket<wbr>Count&quot;</span><span>:</span><span> </span><span>30</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>Start&quot;</span><span>:</span><span> </span><span>&quot;400 ms&quot;</span><span>,</span><span>\n</span><span>&quot;bucket<wbr>End&quot;</span><span>:</span><span> </span><span>&quot;700 ms&quot;</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>}</span><span>\n</span><span>},</span><span>\n</span><span>&quot;app<wbr>Version&quot;</span><span>:</span><span> </span><span>&quot;1.0.0&quot;</span><span>,</span><span>\n</span><span>&quot;time<wbr>Stamp<wbr>Begin&quot;</span><span>:</span><span> </span><span>&quot;2019-10-21 07:00:00 +0000&quot;</span><span>\n</span><span>}</span><span>\n</span></code></pre>\n</details>\n<p>As you can see,\nthere\u2019s a lot baked into this representation.\nDefining a schema for all of this information would be a lot of work,\nand there\u2019s no guarantee that this won\u2019t change in the future.\nSo instead,\nlet\u2019s embrace the NoSQL paradigm\n<em>(albeit responsibly, using <a rel=\"noopener noreferrer\" href=\"https://postgresapp.com\">Postgres</a>)</em>\nby storing payloads in a <a rel=\"noopener noreferrer\" href=\"https://www.postgresql.org/docs/current/datatype-json.html\"><code>JSONB</code> column</a>:</p>\n<pre data-lang=\"sql\"><code><span>CREATE</span> <span>TABLE</span> <span>IF</span> <span>NOT</span> <span>EXISTS</span> <span>metrics</span> <span>(</span>\n <span>id</span> <span>BIGINT</span> <span>GENERATED</span> <span>BY</span> <span>DEFAULT</span> <span>AS</span> <span>IDENTITY</span> <span>PRIMARY</span> <span>KEY</span><span>,</span>\n <span>payload</span> <span>JSONB</span> <span>NOT</span> <span>NULL</span>\n <span>);</span>\n </code></pre>\n<p><em>So easy!</em></p>\n<p>We can extract individual fields from payloads\nusing <a rel=\"noopener noreferrer\" href=\"https://www.postgresql.org/docs/current/functions-json.html\">JSON operators</a>\nlike so:</p>\n<pre data-lang=\"sql\"><code><span>SELECT</span> <span>(</span><span>payload</span> <span>-></span> <span>'application<wbr>Time<wbr>Metrics'</span>\n <span>->></span> <span>'cumulative<wbr>Foreground<wbr>Time'</span><span>)::</span><span>INTERVAL</span>\n <span>FROM</span> <span>metrics</span><span>;</span>\n <span>-- interval</span>\n <span>-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550</span>\n <span>-- @ 11 mins 40 secs</span>\n <span>-- (1 row)</span>\n </code></pre>\n<aside>\n<p>The JSON representation of metrics stores measurements for time and memory\nas strings with units (such as <code>&quot;100 ms&quot;</code> and <code>500 k<wbr>B</code>).\nIn Postgres, you can cast time measurements directly to the\n<a rel=\"noopener noreferrer\" href=\"https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-INTERVAL-INPUT\"><code>INTERVAL</code> type</a>,\nhowever you\u2019ll need to create a function to convert to byte counts:</p>\n<pre data-lang=\"sql\"><code><span>CREATE</span> <span>OR</span> <span>REPLACE</span> <span>FUNCTION</span> <span>parse_byte_count</span> <span>(</span><span>TEXT</span><span>)</span>\n <span>RETURNS</span> <span>BIGINT</span>\n <span>AS</span> <span>$$</span>\n <span>SELECT</span>\n <span>replace</span><span>(</span><span>split_part</span><span>(</span><span>$</span><span>1</span><span>,</span> <span>' '</span><span>,</span> <span>1</span><span>),</span><span>','</span><span>,</span><span>''</span><span>)::</span><span>BIGINT</span> <span>*</span>\n <span>CASE</span> <span>split_part</span><span>(</span><span>$</span><span>1</span><span>,</span> <span>' '</span><span>,</span> <span>2</span><span>)</span>\n <span>WHEN</span> <span>'k<wbr>B'</span> <span>THEN</span> <span>1000</span>\n <span>WHEN</span> <span>'MB'</span> <span>THEN</span> <span>1000</span> <span>*</span> <span>1000</span>\n <span>WHEN</span> <span>'GB'</span> <span>THEN</span> <span>1000</span> <span>*</span> <span>1000</span> <span>*</span> <span>1000</span>\n <span>END</span>\n <span>$$</span> <span>LANGUAGE</span> <span>'sql'</span> <span>STRICT</span> <span>IMMUTABLE</span><span>;</span>\n </code></pre>\n</aside>\n<h4>\n<a href=\"https://nshipster.com/metrickit/#advanced-creating-views\"></a>Advanced: Creating Views</h4>\n<p>JSON operators in PostgreSQL can be cumbersome to work with \u2014\nespecially for more complex queries.\nOne way to help with that is to create a view\n<em>(<a rel=\"noopener noreferrer\" href=\"https://www.postgresql.org/docs/current/rules-materializedviews.html\">materialized</a> or otherwise)</em>\nto project the most important information to you\nin the most convenient representation:</p>\n<pre data-lang=\"sql\"><code><span>CREATE</span> <span>VIEW</span> <span>key_performance_indicators</span> <span>AS</span>\n <span>SELECT</span>\n <span>id</span><span>,</span>\n <span>(</span><span>payload</span> <span>-></span> <span>'app<wbr>Version'</span><span>)</span> <span>AS</span> <span>app_version</span><span>,</span>\n <span>(</span><span>payload</span> <span>-></span> <span>'meta<wbr>Data'</span> <span>->></span> <span>'device<wbr>Type'</span><span>)</span> <span>AS</span> <span>device_type</span><span>,</span>\n <span>(</span><span>payload</span> <span>-></span> <span>'meta<wbr>Data'</span> <span>->></span> <span>'region<wbr>Format'</span><span>)</span> <span>AS</span> <span>region</span><span>,</span>\n <span>(</span><span>payload</span> <span>-></span> <span>'application<wbr>Time<wbr>Metrics'</span>\n <span>->></span> <span>'cumulative<wbr>Foreground<wbr>Time'</span>\n <span>)::</span><span>INTERVAL</span> <span>AS</span> <span>cumulative_foreground_time</span><span>,</span>\n <span>parse_byte_count</span><span>(</span>\n <span>payload</span> <span>-></span> <span>'memory<wbr>Metrics'</span>\n <span>->></span> <span>'peak<wbr>Memory<wbr>Usage'</span>\n <span>)</span> <span>AS</span> <span>peak_memory_usage_bytes</span>\n <span>FROM</span> <span>metrics</span><span>;</span>\n </code></pre>\n<p>With views,\nyou can perform\n<a rel=\"noopener noreferrer\" href=\"https://www.postgresql.org/docs/current/functions-aggregate.html\">aggregate queries</a>\nover all of your metrics JSON payloads\nwith the convenience of a schema-backed relational database:</p>\n<pre data-lang=\"sql\"><code><span>SELECT</span> <span>avg</span><span>(</span><span>cumulative_foreground_time</span><span>)</span>\n <span>FROM</span> <span>key_performance_indicators</span><span>;</span>\n <span>-- avg</span>\n <span>-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550</span>\n <span>-- @ 9 mins 41 secs</span>\n <span>SELECT</span> <span>app_version</span><span>,</span> <span>percentile_disc</span><span>(</span><span>0</span><span>.</span><span>5</span><span>)</span>\n <span>WITHIN</span> <span>GROUP</span> <span>(</span><span>ORDER</span> <span>BY</span> <span>peak_memory_usage_bytes</span><span>)</span>\n <span>AS</span> <span>median</span>\n <span>FROM</span> <span>key_performance_indicators</span>\n <span>GROUP</span> <span>BY</span> <span>app_version</span><span>;</span>\n <span>-- app_version \u2502 median</span>\n <span>-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550</span>\n <span>-- &quot;1.0.1&quot; \u2502 192500000</span>\n <span>-- &quot;1.0.0&quot; \u2502 204800000</span>\n </code></pre>\n<aside>\n<p>PostgreSQL doesn\u2019t handle camelcase well for table or column names,\nso keep that in mind when using functions like\n<a rel=\"noopener noreferrer\" href=\"https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING-TABLE\"><code>jsonb_to_record</code></a>.</p>\n</aside>\n<h3>\n<a href=\"https://nshipster.com/metrickit/#creating-a-web-service\"></a>Creating a Web Service</h3>\n<p>In this example,\nmost of the heavy lifting is delegated to Postgres,\nmaking the server-side implementation rather boring.\nFor completeness,\nhere are some reference implementations in\nRuby (Sinatra) and JavaScript (Express):</p>\n<div>\n<div>\n\n\n</div>\n<pre data-lang=\"Ruby\" tabindex=\"0\"><code><span>require</span> <span>'sinatra/base'</span>\n <span>require</span> <span>'pg'</span>\n <span>require</span> <span>'sequel'</span>\n <span>class</span> <span>App</span> <span>&lt;</span> <span>Sinatra</span><span>::</span><span>Base</span>\n <span>configure</span> <span>do</span>\n <span>DB</span> <span>=</span> <span>Sequel</span><span>.</span><span>connect</span><span>(</span><span>ENV</span><span>[</span><span>'DATABASE_URL'</span><span>])</span>\n <span>end</span>\n <span>post</span> <span>'/collect'</span> <span>do</span>\n <span>DB</span><span>[</span><span>:metrics</span><span>].</span><span>insert</span><span>(</span><span>payload: </span><span>request</span><span>.</span><span>body</span><span>.</span><span>read</span><span>)</span>\n <span>status</span> <span>204</span>\n <span>end</span>\n <span>end</span>\n </code></pre>\n<pre data-lang=\"JavaScript\" hidden=\"hidden\" tabindex=\"0\"><code><span>import</span> <span>express</span> <span>from</span> <span>'express'</span><span>;</span>\n <span>import</span> <span>{</span> <span>Pool</span> <span>}</span> <span>from</span> <span>'pg'</span><span>;</span>\n <span>const</span> <span>db</span> <span>=</span> <span>new</span> <span>Pool</span><span>(</span>\n <span>connection<wbr>String</span><span>:</span> <span>process</span><span>.</span><span>env</span><span>.</span><span>DATABASE_URL</span><span>,</span>\n <span>ssl</span><span>:</span> <span>process</span><span>.</span><span>env</span><span>.</span><span>NODE_ENV</span> <span>===</span> <span>'production'</span>\n <span>);</span>\n <span>const</span> <span>app</span> <span>=</span> <span>express</span><span>();</span>\n <span>app</span><span>.</span><span>post</span><span>(</span><span>'/collect'</span><span>,</span> <span>(</span><span>request</span><span>,</span> <span>response</span><span>)</span> <span>=></span> <span>{</span>\n <span>db</span><span>.</span><span>query</span><span>(</span><span>'INSERT INTO metrics (payload) VALUES ($1)'</span><span>,</span> <span>[</span><span>request</span><span>.</span><span>body</span><span>],</span> <span>(</span><span>error</span><span>,</span> <span>results</span><span>)</span> <span>=></span> <span>{</span>\n <span>if</span> <span>(</span><span>error</span><span>)</span> <span>{</span>\n <span>throw</span> <span>error</span><span>;</span>\n <span>}</span>\n <span>response</span><span>.</span><span>status</span><span>(</span><span>204</span><span>);</span>\n <span>})</span>\n <span>});</span>\n <span>app</span><span>.</span><span>listen</span><span>(</span><span>process</span><span>.</span><span>env</span><span>.</span><span>PORT</span> <span>||</span> <span>5000</span><span>)</span>\n </code></pre>\n</div>\n<h3>\n<a href=\"https://nshipster.com/metrickit/#sending-metrics-as-json\"></a>Sending Metrics as JSON</h3>\n<p>Now that we have everything set up,\nthe final step is to implement\nthe required <code>MXMetric<wbr>Manager<wbr>Subscriber</code> delegate method <code>did<wbr>Receive(_:)</code>\nto pass that information along to our web service:</p>\n<pre data-lang=\"Swift\"><code><span>extension</span> <span>App<wbr>Delegate</span><span>:</span> <span>MXMetric<wbr>Manager<wbr>Subscriber</span> <span>{</span>\n <span>func</span> <span>did<wbr>Receive</span><span>(</span><span>_</span> <span>payloads</span><span>:</span> <span>[</span><span>MXMetric<wbr>Payload</span><span>])</span> <span>{</span>\n <span>for</span> <span>payload</span> <span>in</span> <span>payloads</span> <span>{</span>\n <span>let</span> <span>url</span> <span>=</span> <span>URL</span><span>(</span><span>string</span><span>:</span> <span>&quot;https://example.com/collect&quot;</span><span>)</span><span>!</span>\n <span>var</span> <span>request</span> <span>=</span> <span>URLRequest</span><span>(</span><span>url</span><span>:</span> <span>url</span><span>)</span>\n <span>request</span><span>.</span><span>http<wbr>Method</span> <span>=</span> <span>&quot;POST&quot;</span>\n <span>request</span><span>.</span><span>http<wbr>Body</span> <span>=</span> <span>payload</span><span>.</span><span>json<wbr>Representation</span><span>()</span>\n <span>let</span> <span>task</span> <span>=</span> <span>URLSession</span><span>.</span><span>shared</span><span>.</span><span>data<wbr>Task</span><span>(</span><span>with</span><span>:</span> <span>request</span><span>)</span>\n <span>task</span><span>.</span><span>priority</span> <span>=</span> <span>URLSession<wbr>Task</span><span>.</span><span>low<wbr>Priority</span>\n <span>task</span><span>.</span><span>resume</span><span>()</span>\n <span>}</span>\n <span>}</span>\n <span>}</span>\n </code></pre>\n<hr>\n<p>When you create something and put it out into the world,\nyou lose your direct connection to it.\nThat\u2019s as true for apps as it is for college radio shows.\nShort of user research studies or\n<a rel=\"noopener noreferrer\" href=\"https://techcrunch.com/2019/02/06/iphone-session-replay-screenshots/\">invasive ad-tech</a>,\nthe truth is that\n<a rel=\"noopener noreferrer\" href=\"https://xkcd.com/1172/\">we rarely have any clue about how people are using our software</a>.</p>\n\n<p>Metrics offer a convenient way to at least make sure that\nthings aren\u2019t too slow or too draining.\nAnd though they provide but a glimpse in the aggregate\nof how our apps are being enjoyed,\nit\u2019s just enough to help us honor both our creation and our audience\nwith a great user experience.</p>\n\n<img width=\"1\" alt=\"\" src=\"http://feeds.feedburner.com/~r/NSHipster/~4/o2-j6xKjBrA\" height=\"1\">"
},
"visual": {
"url": "https://cdn.vox-cdn.com/thumbor/06e5FJWgUfUSmDaPJIEZoGF1XOs=/0x68:2040x1136/fit-in/1200x630/cdn.vox-cdn.com/uploads/chorus_asset/file/10378819/DSCF3031.jpg",
"width": 1200,
"height": 628,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 4744,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/e31b3fcb-27f6-4f3e-b96c-53902586e366",
"label": "Weblogs"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572500250190
},
{
"originId": "https://inessential.com/2019/10/22/netnewswire_5_0_3_for_mac_released",
"fingerprint": "2c4d6d88",
"id": "+jHfsXnBCVfCstSIW1WDumAyigT4rnsUPnI5WFxgnAU=_16df54dfcca:13322:d4506071",
"summary": {
"direction": "ltr",
"content": "<p><a href=\"https://ranchero.com/netnewswire/\"><img width=\"256\" alt=\"NetNewsWire for Mac icon: globe with a satellite in the foreground.\" src=\"https://ranchero.com/images/nnw_icon_256.png\" height=\"256\"></a></p>\n<p>The main things in this release are 1) enhanced performance and 2) importing subscriptions from NetNewsWire 3 (since it won\u2018t run on Catalina).</p>\n<p>There are also a bunch of bug fixes \u2014 including a fix for the space bar behavior on Catalina \u2014 and there\u2019s a new feature: you can type the <code>s</code> key to star and unstar an article.</p>\n<p>For more details, <a href=\"https://nnw.ranchero.com/2019/10/22/netnewswire-for-mac.html\">read the change notes</a> on the NetNewsWire blog.</p>"
},
"alternate": [
{
"href": "https://inessential.com/2019/10/22/netnewswire_5_0_3_for_mac_released",
"type": "text/html"
}
],
"crawled": 1571778591946,
"title": "NetNewsWire 5.0.3 for Mac Released",
"published": 1571775505000,
"origin": {
"streamId": "feed/http://ranchero.com/xml/rss.xml",
"htmlUrl": "https://inessential.com/",
"title": "inessential.com"
},
"visual": {
"url": "http://www.blogcdn.com/www.engadget.com/media/2013/10/nvidia-shield-console-mode.jpg",
"width": 620,
"height": 340,
"contentType": "image/jpg"
},
"unread": false,
"readTime": 5621,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572500226675
},
{
"id": "AxO6mug+YPRclcA3EJcsykvvS1qcjXH62IXONGWCBII=_16db2add61b:afd:a4acdac",
"originId": "58495.pz39s0 at https://www.imore.com",
"fingerprint": "8fe463a6",
"content": {
"content": "<div><div><div><p>An Apple Support rep apparently said, &quot;I do not know how this could of happened.&quot;</p>\n<p><a href=\"https://www.imore.com/apple-card-user-says-he-was-victim-fraud\" title=\"Apple Card user says he was the victim of fraud\"><img src=\"https://www.imore.com/sites/imore.com/files/styles/large_wm_blw/public/field/image/2019/08/apple-card-hero-05.jpeg?itok=IWclhnvc\"></a></p>\n<h2>What you need to know</h2>\n<ul><li>An Apple Card user claims he was the victim of fraud.</li>\n<li>When he contacted Apple Support, they said, &quot;I do not know how this could of happened.&quot;</li>\n<li>Apple Card touts an extra level of security with no numbers and no CVV.</li>\n</ul><p>When Apple Card debuted, one of its biggest draws was Apple's focus on security. On Apple's website, it says, &quot;It's hard to steal a credit card number when you can't see it.&quot; But that's apparently what happened to one Apple Card user who reached out to <a href=\"https://9to5mac.com/2019/10/09/apple-card-security-cloning/\">9to5Mac</a>, claiming they were the victim of fraud.</p>\n<p>The Apple Card user said they reached out to Apple Support and received this response:</p>\n<blockquote>\n<p>I do not know how this could of happened. It's very rare for your card to be in two places at one time. Since our physical cards have no number on it, it's very hard for someone to copy it.</p>\n</blockquote>\n<p>The Apple Card user confirmed the fraudulent charge after receiving an alert on his iPhone. The tricky thing is the purchase was apparently labeled as being nearby, but clicking on the map revealed it was hours away, 9to5Mac explained.</p>\n<p>On Apple's website, the company highlights the fact that the Apple Card doesn't have any numbers on it. &quot;Not even a CVV. So that's one less thing to worry about when you hand over your card at a restaurant or store.&quot; But that doesn't guarantee it can't be stolen.</p>\n<p>9to5Mac speculates that the Apple Card user may have been the victim of skimming, which can potentially affect all credit cards and debit cards. It's a reminder to be extra vigilant when swiping your card at a gas station or ATM. Better yet, use Apple Pay when possible.</p>\n<p></p><p></p>\n<div>\n<h3><a href=\"https://www.imore.com/apple-goldman-sachs-credit-card\">Apple Card</a></h3>\n<p><a href=\"https://www.imore.com/apple-goldman-sachs-credit-card\"></a><a href=\"https://www.imore.com/apple-card-user-says-he-was-victim-fraud\" title=\"Apple Card user says he was the victim of fraud\"><img src=\"https://www.imore.com/sites/imore.com/files/styles/large/public/field/image/2019/03/apple-card-iphone-xs-payment.jpg\"></a></p>\n<ul><li><a href=\"https://www.imore.com/apple-goldman-sachs-credit-card\">Apple Card: Everything you need to know</a></li>\n<li><a href=\"https://www.imore.com/amex-business-gold-card-apple-store-rewards\">Best Apple Store rewards card</a></li>\n<li><a href=\"https://www.imore.com/apple-card-missing-these-huge-signup-bonuses\">Best credit cards with sign up bonuses</a></li>\n<li><a href=\"https://www.imore.com/not-approved-apple-card-try-applying-these-cards-instead\">What to do if you're not approved for Apple Card</a></li>\n<li><a href=\"https://www.imore.com/is-apple-card-worth-getting\">Is Apple Card worth getting?</a></li>\n</ul></div>\n<p></p></div></div></div><img width=\"1\" alt=\"\" src=\"http://feeds.feedburner.com/~r/TheIphoneBlog/~4/DzBrQNf9PCU\" height=\"1\">",
"direction": "ltr"
},
"title": "Apple Card user says he was the victim of fraud",
"author": "Brandon Russell",
"summary": {
"content": "An Apple Support rep apparently said, &quot;I do not know how this could of happened.&quot;\nWhat you need to know\nAn Apple Card user claims he was the victim of fraud.\nWhen he contacted Apple Support, they said, &quot;I do not know how this could of happened.&quot;\nApple Card touts an extra level of security with no numbers and no CVV.\nWhen Apple Card debuted, one of its biggest draws was Apple's focus on security. On Apple's website, it says, &quot;It's hard to steal a credit card number when you can't see it.&quot; But that's apparently what happened to one Apple Card user who reached out to 9to5Mac, claiming they were the victim of fraud.\nThe Apple Card user said they reached out to Apple Support and received this response:\nI do not know how this could of happened. It's very rare for your card to be in two places at one time. Since our physical cards have no number on it, it's very hard for someone to copy it.\nThe Apple Card user confirmed the fraudulent charge after receiving an alert on his iPhone. ...",
"direction": "ltr"
},
"alternate": [
{
"href": "http://feeds.imore.com/~r/TheIphoneBlog/~3/DzBrQNf9PCU/apple-card-user-says-he-was-victim-fraud",
"type": "text/html"
}
],
"canonical": [
{
"href": "https://www.imore.com/apple-card-user-says-he-was-victim-fraud",
"type": "text/html"
}
],
"crawled": 1570660800027,
"published": 1570660313000,
"origin": {
"streamId": "feed/http://www.imore.com/rss.xml",
"title": "iMore - The #1 iPhone, iPad, and iPod touch blog",
"htmlUrl": "https://www.imore.com/"
},
"unread": false,
"readTime": 2216,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572500208603
},
{
"keywords": [
"Development",
"How To",
"Xcode"
],
"originId": "https://ericasadun.com/?p=6502",
"fingerprint": "878bb7e8",
"id": "eos9yhbovnwyH+gNY6NsrxoZIGI+1zv2KFTRDDBJycA=_16e0e491282:185ad:d4506071",
"author": "erica",
"summary": {
"direction": "ltr",
"content": "Most Xcode users quickly become familiar with the basics of the Find Navigator panel. With it, you can find text, regular expressions, and perform search-and-replace, whether matching or ignoring case. But that\u2019s just scratching the surface of the Find Navigator. I thought I\u2019d drop a few words today about search scopes. Controlled from the bottom [\u2026]"
},
"alternate": [
{
"href": "https://ericasadun.com/2019/10/27/fun-with-xcode-search-domains-excluding-match-text/",
"type": "text/html"
}
],
"crawled": 1572197700226,
"title": "Fun with Xcode Search Domains: Excluding match text",
"published": 1572195876000,
"origin": {
"streamId": "feed/http://ericasadun.com/feed/",
"htmlUrl": "https://ericasadun.com",
"title": "Erica Sadun"
},
"content": {
"direction": "ltr",
"content": "<p>Most Xcode users quickly become familiar with the basics of the Find Navigator panel.</p>\n<p><img data-orig-file=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.32.34-AM.png?fit=273%2C104&amp;ssl=1\" data-orig-size=\"273,104\" data-medium-file=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.32.34-AM.png?fit=273%2C104&amp;ssl=1\" data-attachment-id=\"6503\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-description=\"\" src=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.32.34-AM.png?resize=273%2C104&ssl=1\" data-permalink=\"https://ericasadun.com/2019/10/27/fun-with-xcode-search-domains-excluding-match-text/screen-shot-2019-10-27-at-10-32-34-am/\" data-large-file=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.32.34-AM.png?fit=273%2C104&amp;ssl=1\" alt=\"\" data-image-title=\"Screen Shot 2019-10-27 at 10.32.34 AM\" width=\"273\" data-comments-opened=\"1\" class=\"wp-image-6503\" data-recalc-dims=\"1\" height=\"104\"></p>\n<p>With it, you can find text, regular expressions, and perform search-and-replace, whether matching or ignoring case. But that\u2019s just scratching the surface of the Find Navigator.</p>\n<p>I thought I\u2019d drop a few words today about search scopes. Controlled from the bottom left, \u00a0under the search field, you can create narrowed searches. This enables you to, for example, search only in Swift files or exclude files containing the word Test.</p>\n<p>To get started, click the icon (two lines with three squares on a line between them) and then New Scope (the plus icon). Here, you can name the scope, limit the search extent, and add criteria for exactly which files should be included or not.</p>\n<p><img data-orig-file=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?fit=863%2C223&amp;ssl=1\" data-orig-size=\"863,223\" data-medium-file=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?fit=300%2C78&amp;ssl=1\" data-attachment-id=\"6504\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-description=\"\" src=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?resize=863%2C223&ssl=1\" data-permalink=\"https://ericasadun.com/2019/10/27/fun-with-xcode-search-domains-excluding-match-text/screen-shot-2019-10-27-at-10-37-57-am/\" data-large-file=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?fit=863%2C223&amp;ssl=1\" alt=\"\" data-image-title=\"Screen Shot 2019-10-27 at 10.37.57 AM\" srcset=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?w=863&amp;ssl=1 863w, https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?resize=300%2C78&amp;ssl=1 300w, https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?resize=768%2C198&amp;ssl=1 768w, https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.37.57-AM.png?resize=535%2C138&amp;ssl=1 535w\" sizes=\"(max-width: 863px) 100vw, 863px\" width=\"863\" data-comments-opened=\"1\" class=\"wp-image-6504\" data-recalc-dims=\"1\" height=\"223\"></p>\n<p>The logic is straightforward. You choose where to look (the project, a folder, or through the entire SDK), and whether to include all conditions or some conditions:</p>\n<p><img data-orig-file=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.49-AM.png?fit=310%2C105&amp;ssl=1\" data-orig-size=\"310,105\" data-medium-file=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.49-AM.png?fit=300%2C102&amp;ssl=1\" data-attachment-id=\"6505\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-description=\"\" src=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.49-AM.png?resize=310%2C105&ssl=1\" data-permalink=\"https://ericasadun.com/2019/10/27/fun-with-xcode-search-domains-excluding-match-text/screen-shot-2019-10-27-at-10-39-49-am/\" data-large-file=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.49-AM.png?fit=310%2C105&amp;ssl=1\" alt=\"\" data-image-title=\"Screen Shot 2019-10-27 at 10.39.49 AM\" srcset=\"https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.49-AM.png?w=310&amp;ssl=1 310w, https://i2.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.49-AM.png?resize=300%2C102&amp;ssl=1 300w\" sizes=\"(max-width: 310px) 100vw, 310px\" width=\"310\" data-comments-opened=\"1\" class=\"wp-image-6505\" data-recalc-dims=\"1\" height=\"105\"></p>\n<p>Each condition is based on the file name, path, extension, UTI (the kind of file, like image which is useful for finding vector assets), Workspace location (namely groups), or source control status (handy for finding newly applied changes.)</p>\n<p>Most of my conditions are file-name-based. And for those, you get the following matching conditions. The \u201cends with\u201d is an obvious win for extensions (although you can also use UTIs for that), and \u201cstarts with\u201d can help for projects organized in hierarchical ways.</p>\n<p><img data-orig-file=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.44-AM.png?fit=484%2C113&amp;ssl=1\" data-orig-size=\"484,113\" data-medium-file=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.44-AM.png?fit=300%2C70&amp;ssl=1\" data-attachment-id=\"6506\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-description=\"\" src=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.44-AM.png?resize=484%2C113&ssl=1\" data-permalink=\"https://ericasadun.com/2019/10/27/fun-with-xcode-search-domains-excluding-match-text/screen-shot-2019-10-27-at-10-39-44-am/\" data-large-file=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.44-AM.png?fit=484%2C113&amp;ssl=1\" alt=\"\" data-image-title=\"Screen Shot 2019-10-27 at 10.39.44 AM\" srcset=\"https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.44-AM.png?w=484&amp;ssl=1 484w, https://i0.wp.com/ericasadun.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-27-at-10.39.44-AM.png?resize=300%2C70&amp;ssl=1 300w\" sizes=\"(max-width: 484px) 100vw, 484px\" width=\"484\" data-comments-opened=\"1\" class=\"wp-image-6506\" data-recalc-dims=\"1\" height=\"113\"></p>\n<p>Now, interestingly enough, this list fails to offer \u201cdoes not contain\u201d but that\u2019s fairly easy to work around. Since Xcode supports regex matching, you can easily replicate \u201cdoes not contain\u201d with an <a href=\"https://www.regextester.com/15\">appropriate regex</a>:</p>\n<p><a href=\"https://ericasadun.com/wp-content/uploads/2019/10/AntiMatch.tiff\"><img data-orig-file=\"https://ericasadun.com/wp-content/uploads/2019/10/AntiMatch.tiff\" data-orig-size=\"\" data-medium-file=\"https://ericasadun.com/wp-content/uploads/2019/10/AntiMatch.tiff\" data-attachment-id=\"6507\" data-image-meta=\"[]\" data-image-description=\"\" src=\"https://ericasadun.com/wp-content/uploads/2019/10/AntiMatch.tiff\" data-permalink=\"https://ericasadun.com/2019/10/27/fun-with-xcode-search-domains-excluding-match-text/antimatch/\" data-large-file=\"https://ericasadun.com/wp-content/uploads/2019/10/AntiMatch.tiff\" alt=\"\" data-image-title=\"AntiMatch\" data-comments-opened=\"1\" class=\"wp-image-6507\"></a></p>\n<p>Change the file name to a path to exclude source file directories.</p>\n<p>You can create as many search domains as you like. At least, I haven\u2019t found an upper bound yet. I haven\u2019t found a way to reorder the find scopes, although if you\u2019re really controlling about this, you can pop into \u00a0your workspace (<code>ProjectName.xcodeproj/project.xcworkspace/xcuserdata/username.xcuserdatad</code>), convert your <code>UserInterfaceState.xcuserstate</code> to xml (<code>plutil -convert xml1</code>), and hand-edit it the way you need.</p>\n<p>There are lots of wonderful little Xcode tweaks like these throughout this monster of an IDE. What are some of your faves? If I have time this week, I\u2019ll share some of mine, such as the four-square \u2014 another of my favorite tools \u2014 and a few great ways to connect your editor to the navigator.</p>"
},
"unread": false,
"readTime": 3406,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
}
],
"actionTimestamp": 1572499929438
},
{
"keywords": [
"Apple"
],
"originId": "https://9to5mac.com/?p=617536",
"recrawled": 1572455791719,
"updateCount": 1,
"fingerprint": "77224d8",
"id": "BmoAzSEWHFzR01wyxBZAhNEo11Vy8oDR1qKDe+tKVEQ=_16e1d065ad9:1c0f1:d4506071",
"author": "Michael Potuck",
"summary": {
"direction": "ltr",
"content": "<div><img src=\"https://9to5mac.com/wp-content/uploads/sites/6/2019/10/sonos-discount-program-trade-in.jpeg?quality=82&strip=all&w=1600\"></div>\n<p>Sonos has announced a new initiative today that makes it easy for existing customers to trade in older Sonos products for a nice discount on new ones. For Apple customers, the <a href=\"http://www.anrdoezrs.net/links/9173227/type/dlg/https://www.sonos.com/en-us/tradeup\">Trade Up program</a> is a neat opportunity to bring <a href=\"http://www.anrdoezrs.net/links/9173227/type/dlg/https://www.sonos.com/en-us/products/wireless-speakers\">Sonos\u2019 AirPlay 2 compatible speakers</a> into your home.</p>\n<p> <a href=\"https://9to5mac.com/2019/10/30/sonos-trade-in-program-airplay-2/#more-617536\">more\u2026</a></p>\n<p>The post <a rel=\"nofollow\" href=\"https://9to5mac.com/2019/10/30/sonos-trade-in-program-airplay-2/\">Sonos pushing AirPlay 2 speaker lineup with new Trade Up program</a> appeared first on <a rel=\"nofollow\" href=\"https://9to5mac.com\">9to5Mac</a>.</p>"
},
"alternate": [
{
"href": "https://9to5mac.com/2019/10/30/sonos-trade-in-program-airplay-2/",
"type": "text/html"
}
],
"crawled": 1572444986073,
"title": "Sonos pushing AirPlay 2 speaker lineup with new Trade Up program",
"published": 1572442686000,
"origin": {
"streamId": "feed/http://9to5mac.com/feed/",
"htmlUrl": "https://9to5mac.com",
"title": "9to5Mac"
},
"visual": {
"url": "https://cdn.vox-cdn.com/thumbor/06e5FJWgUfUSmDaPJIEZoGF1XOs=/0x68:2040x1136/fit-in/1200x630/cdn.vox-cdn.com/uploads/chorus_asset/file/10378819/DSCF3031.jpg",
"width": 1200,
"height": 628,
"contentType": "image/jpeg"
},
"unread": false,
"readTime": 4493,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815",
"label": "Macintosh"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572499889443
},
{
"originId": "tag:blogger.com,1999:blog-8954608646904080796.post-4991449931465752891",
"fingerprint": "7d99be14",
"thumbnail": [
{
"url": "https://1.bp.blogspot.com/-rGjQOQb89a8/XbS25YYbgeI/AAAAAAAADUI/s8Q4e0pTtX4qSTP3wrkt13VGV53Q8J0tQCLcBGAsYHQ/s72-c/092.jpg",
"width": 72,
"height": 72
}
],
"id": "v0v+7Ya8tssIZvd3/pcnFRr3HwvY/5YK3FGc2t65c0Y=_16e0a232509:17e32:d4506071",
"updated": 1572124724480,
"author": "Edward Feser",
"alternate": [
{
"href": "http://edwardfeser.blogspot.com/2019/10/john-paul-ii-in-defense-of-nation-and.html",
"type": "text/html"
}
],
"crawled": 1572128105737,
"title": "John Paul II in defense of the nation and patriotism",
"published": 1572124680000,
"origin": {
"streamId": "feed/http://edwardfeser.blogspot.com/feeds/posts/default",
"htmlUrl": "http://edwardfeser.blogspot.com/",
"title": "Edward Feser"
},
"content": {
"direction": "ltr",
"content": "<br><div><a href=\"https://1.bp.blogspot.com/-rGjQOQb89a8/XbS25YYbgeI/AAAAAAAADUI/s8Q4e0pTtX4qSTP3wrkt13VGV53Q8J0tQCLcBGAsYHQ/s1600/092.jpg\"><img border=\"0\" data-original-height=\"180\" src=\"https://1.bp.blogspot.com/-rGjQOQb89a8/XbS25YYbgeI/AAAAAAAADUI/s8Q4e0pTtX4qSTP3wrkt13VGV53Q8J0tQCLcBGAsYHQ/s1600/092.jpg\" data-original-width=\"144\"></a></div><div><span>In chapters 11-15 of his last book <span><i><a href=\"https://www.amazon.com/Memory-Identity-Conversations-Dawn-Millennium/dp/0847827615/ref=sr_1_1?keywords=john+paul+II+memory+and+identity&qid=1572031154&sr=8-1\">Memory and Identity</a></i></span>, Pope St. John Paul II provides a lucid exposition of the idea of the nation as a natural social institution and of the virtue of patriotism, as these have been understood in traditional natural law theory and Catholic moral theology.\u00a0 The relevance to current controversies will be obvious.</span></div><div><span><br></span></div><div><span>What is the nation, and what is patriotism?<span>\u00a0 </span>John Paul begins by noting the connection between the nation and the family, where the former is in a sense an extension of the latter:</span></div><a name=\"more\"></a><br> <div><i><span>The Latin word </span></i><span>patria<i> is associated with the idea and the reality of \u201cfather\u201d (</i>pater<i>).<span>\u00a0 </span>The native land (or fatherland) can in some ways be identified with patrimony \u2013 that is, the totality of goods bequeathed to us by our forefathers\u2026 Our native land is thus our heritage and it is also the whole patrimony derived from that heritage.<span>\u00a0 </span>It refers to the land, the territory, but more importantly, the concept of patria includes the values and spiritual content that make up the culture of a given nation</i>. (p. 60)</span></div><div><span><br></span></div><div><span>As that last remark makes clear, the ties of blood are less important than those of culture.<span>\u00a0 </span>Indeed, multiple ethnicities can make up a nation.<span>\u00a0 </span>Referring to his native Poland, the pope notes that \u201cin ethnic terms, perhaps the most significant event for the foundation of the nation was the union of two great tribes,\u201d and yet other peoples too eventually went on together to comprise \u201cthe Polish nation\u201d (p. 77).<span>\u00a0 </span>It is shared culture, and especially a shared religion, that formed these diverse ethnicities into a nation:</span></div><div><span><br></span></div><div><i><span>When we speak of Poland\u2019s baptism, we are not simply referring to the sacrament of Christian initiation received by the first historical sovereign of Poland, but also to the event which was decisive for the birth of the nation and the formation of its Christian identity.<span>\u00a0 </span>In this sense, the date of Poland\u2019s baptism marks a turning point.<span>\u00a0 </span>Poland as a nation emerges from its prehistory at that moment and begins to exist in history</span></i><span>.<span>\u00a0 </span>(p. 77)</span></div><div><span><br></span></div><div><span>That a shared culture is the key to understanding the nation is a theme John Paul emphasizes repeatedly throughout the book.<span>\u00a0 </span>He says that \u201cevery nation draws life from the works of its own culture\u201d (p. 83), and that:</span></div><div><span><br></span></div><div><i><span>The nation is, in fact, the great community of men who are united by various ties, but above all, precisely by culture.<span>\u00a0 </span>The nation exists\u00a0<span>\u2018through\u2019 culture and \u2018for\u2019 culture\u00a0</span>and it is therefore the great educator of men in order that they may \u2018be more\u2019 in the community\u2026</span></i></div><div><i><span><br></span></i></div><div><i><span>I am the son of a nation which\u2026 has kept its identity, and it has kept, in spite of partitions and foreign occupations, its national sovereignty, not by relying on the resources of physical power but solely\u00a0<span>by relying on its culture. </span><span>\u00a0</span>This culture turned out, under the circumstances, to be more powerful than all other forces.<span>\u00a0 </span>What I say here concerning the right of the nation to the foundation of its culture and its future is not, therefore, the echo of any \u2018nationalism\u2019, but it is always a question of a stable element of human experience and of the\u00a0<span>humanistic perspective of man's development.<span>\u00a0 </span></span>There exists a fundamental sovereignty of society, which is manifested in the culture of the nation</span></i><span>. (p. 85)</span></div><div><span><br></span></div><div><span>In addition to shared values and religion, John Paul identifies shared history as another crucial aspect of a nation\u2019s identifying culture:</span></div><div><span><br></span></div><div><i><span>Like individuals, then, nations are endowed with historical memory\u2026 And the histories of nations, objectified and recorded in writing, are among the essential elements of culture \u2013 the element which determines the nation\u2019s identity in the temporal dimension</span></i><span>.<span>\u00a0 </span>(pp. 73-74)</span></div><div><span><br></span></div><div><span>The pope notes that citizens of modern Western European countries often have \u201creservations\u201d about the notion of \u201cnational identity as expressed through culture,\u201d and have even \u201carrived at a stage which could be defined as \u2018post-identity\u2019\u201d (p. 86).<span>\u00a0 </span>There is \u201ca widespread tendency to move toward supranational structures, even internationalism\u201d with \u201csmall nations\u2026 allow[ing] themselves to be absorbed into larger political structures\u201d (p. 66).<span>\u00a0 </span>However, the disappearance of the nation would be contrary to the natural order of things:</span></div><div><span><br></span></div><div><i><span>Yet it still seems that nation and native land, like the family, are permanent realities.<span>\u00a0 </span>In this regard, Catholic social doctrine speaks of \u201cnatural\u201d societies, indicating that both the family and the nation have a particular bond with human nature, which has a social dimension.<span>\u00a0 </span>Every society\u2019s formation takes place in and through the family: of this there can be no doubt.<span>\u00a0 </span>Yet something similar could also be said about the nation</span></i><span>. (p. 67)</span></div><div><span><br></span></div><div><span>And again:</span></div><div><span><br></span></div><div><i><span>The term \u201cnation\u201d designates a community based in a given territory and distinguished from other nations by its culture.<span>\u00a0 </span>Catholic social doctrine holds that the family and the nation are both natural societies, not the product of mere convention.<span>\u00a0 </span>Therefore, in human history they cannot be replaced by anything else.<span>\u00a0 </span>For example, the nation cannot be replaced by the State, even though the nation tends naturally to establish itself as a State\u2026 Still less is it possible to identify the nation with so-called democratic society, since here it is a case of two distinct, albeit interconnected orders.<span>\u00a0 </span>Democratic society is closer to the State than is the nation.<span>\u00a0 </span>Yet the nation is the ground on which the State is born</span></i><span>. (pp. 69-70)</span></div><div><span><br></span></div><div><span>As this last point about the state and democracy indicates, a nation cannot be defined in terms of, or replaced by, either governmental institutions and their laws and policies on the one hand, or the aggregate of the attitudes of individual citizens on the other.<span>\u00a0 </span>It is something deeper than, and presupposed by, both of these things.<span>\u00a0 </span>It is only insofar as a nation, defined by its culture, is already in place that a polity can come into being.<span>\u00a0 </span>Hence it is a mistake to think that, if the common cultural bonds that define a nation disappear, the nation can still be held together by virtue of governmental policy either imposed from above or arrived at my majority vote.<span>\u00a0 </span>For a people have to be united by common bonds of culture before they can all see either governmental policy or the will of the majority as legitimate.<span>\u00a0 </span>(Readers familiar with the work of Roger Scruton will note the parallels, and how deeply conservative John Paul II\u2019s understanding of the nation is.)<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Now, as a natural institution, the nation, like the family, is necessary for our well-being.<span>\u00a0 </span>And as with the family, this entails a <i>moral duty</i> to be loyal to and to defend one\u2019s nation \u2013 and for precisely the same sorts of reasons one has a duty of loyalty to and defense of one\u2019s family:</span></div><div><span><br></span></div><div><i><span>If we ask where patriotism appears in the Decalogue, the reply comes without hesitation: it is covered by the fourth commandment, which obliges us to honor our father and mother.<span>\u00a0 </span>It is included under the umbrella of the Latin word </span></i><span>pietas<i>, which underlines the religious dimension of the respect and veneration due to parents\u2026</i></span></div><div><span><i><br></i></span></div><div><i><span>Patriotism is a love for everything to do with our native land: its history, its traditions, its language, its natural features.<span>\u00a0 </span>It is a love which extends also to the works of our compatriots and the fruits of their genius.<span>\u00a0 </span>Every danger that threatens the overall good of our native land becomes an occasion to demonstrate this love</span></i><span>. (pp. 65-66)</span></div><div><span><br></span></div><div><span>Among the dangers to the nation are the opposite extreme economic errors of egalitarian statism and liberal individualism, which threaten to destroy the common culture that defines the nation \u2013 in the one case from the top down and in the other from the bottom up.<span>\u00a0 </span>The pope writes:</span></div><div><span><br></span></div><div><i><span>[W]e must ask how best to respect the proper relationship between economics and culture without destroying this greater human good for the sake of profit, in deference to the overwhelming power of one-sided market forces.<span>\u00a0 </span>It matters little, in fact, whether this kind of tyranny is imposed by Marxist totalitarianism or by Western liberalism</span></i><span>. (pp. 83-84)</span></div><div><span><br></span></div><div><span>If liberal individualism is an error that pays insufficient respect to the nation, there is of course an opposite extreme error which involves giving excessive esteem to the nation \u2013 namely, nationalism.<span>\u00a0 </span>Patriotism, rightly understood, is the middle ground between these extremes:</span></div><div><span><br></span></div><div><i><span>Whereas nationalism involves recognizing and pursuing the good of one\u2019s own nation alone, without regard for the rights of others, patriotism, on the other hand, is a love for one\u2019s native land that accords rights to all other nations equal to those claimed for one\u2019s own</span></i><span>. (p. 67)</span></div><div><span><br></span></div><div><span>John Paul II was clear that the remedy for nationalism was not to go to the opposite extreme (whether in the name of individualism, internationalism, or whatever), but rather precisely to insist on the sober middle ground:</span></div><div><span><br></span></div><div><i><span>How can we be delivered from such a danger?<span>\u00a0 </span>I think the right way is through patriotism\u2026 Patriotism, in other words, leads to a properly ordered social love</span></i><span>. (p. 67)</span></div><div><span><br></span></div><div><span>Now, let\u2019s note a number of things about these remarks and their implications.<span>\u00a0 </span>First, as I have said, what the late pope was giving expression to here is not merely his personal opinion, but traditional natural law political philosophy and Catholic moral teaching \u2013 the kind of thing that would have been well known to someone formed in Thomistic philosophy and theology in the early twentieth century, as John Paul II was.</span></div><div><span><br></span></div><div><span>Second, John Paul\u2019s teaching implies that those who seek to preserve their nation\u2019s common culture, and for that reason are concerned about trends that might radically alter its religious makeup or undermine its common language and reverence for its history, are simply following a natural and healthy human impulse and indeed following out the implications of the fourth commandment.<span>\u00a0 </span>There is no necessary connection between this attitude and racism, hatred for immigrants, religious bigotry, or the like.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Of course, a person who seeks to preserve his nation\u2019s culture <i>might</i> also be a racist or xenophobe or bigot.<span>\u00a0 </span>The point, however, is that he <i>need not</i> be, and indeed that it is wrong even to <i>presume</i> that he is, because a special love for one\u2019s own nation and desire to preserve its culture is a natural human tendency, and thus likely to be found even in people who have no racist or xenophobic or bigoted attitudes at all.<span>\u00a0 </span>Indeed, it is, again, even morally virtuous.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Needless to say, there is <i>also</i> a moral need to balance this patriotism with a welcoming attitude toward immigrants, with respect for the rights of religious minorities, and so forth.<span>\u00a0 </span>The point, however, is that <i>all </i>of these things need to be balanced. <span>\u00a0</span>Too many contemporary Catholics, including some churchmen, have a tendency to emphasize only the latter while ignoring the former.<span>\u00a0 </span>They have a tendency to buy into the leftist narrative according to which the current wave of populist and patriotic sentiment in the United States and Western Europe is merely an expression of racism and xenophobia.<span>\u00a0 </span>This is deeply unjust, contrary to Catholic teaching, and politically dangerous.<span>\u00a0 </span>It is unjust and contrary to Catholic teaching because, again, both natural law and traditional moral theology affirm that a desire to preserve one\u2019s nation and its culture are natural human sentiments and morally praiseworthy.<span>\u00a0 </span>It is dangerous because, when governing authorities fail to respect and take account of these natural and decent human sentiments, they are <i>inviting</i> rather than preventing a nationalist overreaction. </span></div><div><span><br></span></div><div><span>(President Trump has famously called himself a \u201cnationalist,\u201d which is unfortunate given the connotations of that term.<span>\u00a0 </span>However, from <span><a href=\"https://www.nbcnews.com/politics/donald-trump/future-does-not-belong-globalists-trump-pushes-nationalism-u-n-n1058171\">his 2019 address to the United Nations</a></span> it seems clear that what he means by this is just the defense of the institution of the nation against those who would dissolve it in the name of globalism, open borders, etc.<span>\u00a0 </span>Moreover, he explicitly affirmed the right of <i>every</i> nation to preserve itself and its sovereignty, and the right of <i>every</i>human being to have a special patriotic love and preference for his own country.<span>\u00a0 </span>He also has repeatedly called for the United States to refrain from intervening in the affairs of other nations.<span>\u00a0 </span>So it is evident that it is really just <i>patriotism</i> in the sense described above, rather than some sort of American nationalism, that he intends to promote.)</span></div><div><span><br></span></div><div><span>The current controversy over illegal immigration must be understood in light of these principles.<span>\u00a0 </span>In <span><a href=\"http://w2.vatican.va/content/john-paul-ii/en/messages/migration/documents/hf_jp-ii_mes_25071995_undocumented_migrants.html\">a 1996 message on World Migration Day</a></span>, John Paul II emphasized the need to welcome migrants, to take account of the dangerous circumstances they are sometimes fleeing, to avoid all racist and xenophobic attitudes, and so on.<span>\u00a0 </span>At the same time, he acknowledged that \u201cmigration is assuming the features of a social emergency, above all because of the increase in\u00a0<i>illegal migrants\u201d</i><span> (emphasis in the original), and that the problem is</span> \u201cdelicate and complex.\u201d<span>\u00a0 </span>He affirmed that \u201cillegal immigration should be prevented\u201d and that one reason it is problematic is that \u201cthe supply of foreign labour is becoming excessive in comparison to the needs of the economy, which already has difficulty in absorbing its domestic workers.\u201d<span>\u00a0 </span>And he stated that in some cases, it may be necessary to advise migrants \u201cto seek acceptance in other countries, or to return to their own country.\u201d</span></div><div><span><br></span></div><div><span>The Catechism promulgated by Pope John Paul II <span><a href=\"http://www.vatican.va/archive/ccc_css/archive/catechism/p3s2c2a4.htm\">teaches that</a></span>:</span></div><div><span><br></span></div><div><i><span>The more prosperous nations are obliged, <b>to the extent they are able,</b>to welcome the\u00a0<span>foreigner\u00a0</span>in search of the security and the means of livelihood which he cannot find in his country of origin. Public authorities should see to it that the natural right is respected that places a guest under the protection of those who receive him.</span></i></div><div><i><span><br></span></i></div><div><b><i><span>Political authorities, for the sake of the common good for which they are responsible,</span></i></b><i><span> <b>may make the exercise of the right to immigrate subject to various juridical conditions,</b> especially with regard to the immigrants' duties toward their country of adoption. <b>Immigrants are obliged to respect with gratitude the material and spiritual heritage of the country that receives them, to obey its laws and to assist in carrying civic burdens</b></span></i><b><span>.</span></b><span><span>\u00a0 </span>(Emphasis added)</span></div><div><span><br></span></div><div><span>End quote.<span>\u00a0 </span>Note that the Catechism teaches that immigrants have a <i>duty</i> to respect the laws and \u201cspiritual heritage\u201d of the nation they seek to enter, and that political authorities may restrict immigration so as to uphold the \u201ccommon good\u201d of the nation they govern.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>Hence, there is no foundation in Catholic teaching for an open borders position, or for the position that those who seek to uphold the common culture and economic interests of their nation ought to be dismissed as racists and xenophobes.<span>\u00a0 </span>On the contrary, Catholic teaching <i>explicitly rules out</i> those positions.<span>\u00a0 </span></span></div><div><span><span><br></span></span></div><div><span>There is a further implication of John Paul II\u2019s teaching.<span>\u00a0 </span>It isn\u2019t merely that having a special love for one\u2019s nation and its culture is natural and virtuous.<span>\u00a0 </span>It is that a <i>failure </i>to have it is <i>vicious</i> \u2013 a violation of the fourth commandment.</span></div><div><span><br></span></div><div><span>Of course, every nation has its faults, and aspects of its history of which one ought to be ashamed.<span>\u00a0 </span>For example, Germans are right to repudiate the Nazi period of their history, and Americans are right to repudiate slavery and segregation.<span>\u00a0 </span>But there is a mentality prevalent in the modern West that goes well beyond that \u2013 that insists on seeing nothing but evil in one\u2019s own nation and its culture and history.<span>\u00a0 </span>This is the mentality <span><a href=\"https://quillette.com/2019/10/07/oikophobia-our-western-self-hatred/\">sometimes called <i>oikophobia</i></a></span> \u2013 the hatred of one\u2019s own \u201chousehold\u201d (<i>oikos</i>), in the sense of one\u2019s own nation.<span>\u00a0 </span>One sees this mentality in Westerners who shrilly and constantly denounce their civilization as irredeemably racist, colonialist, etc., downplaying or denying its virtues, and comparing it unfavorably to other cultures \u2013 as if Western culture is somehow <i>more</i> prone to such failings than other cultures are, and as if it hasn\u2019t contributed enormously to the good of the world (both of which are absurd suppositions).</span></div><div><span><br></span></div><div><span>Oikophobia is <i>evil</i>.<span>\u00a0 </span>It is a spiritual poison that damages both those prone to it (insofar as it makes them bitter, ungrateful, etc.) and the social order of which they are parts (insofar as it undermines the love and loyalty citizens need to have for their nation if it is to survive).<span>\u00a0 </span>It is analogous to the evil of hating and undermining one\u2019s own family.<span>\u00a0 </span>It is a violation of the fourth commandment.</span></div><div><span><br></span></div><div><span>The oikophobe sees his position as a remedy for nationalism, but in fact he is simply guilty of falling into an error that is the opposite extreme from that of the nationalist.<span>\u00a0 </span>Moreover, he is inadvertently <i>promoting</i> nationalism, because human beings have a tendency to overreact to one extreme by going too far in the other direction.<span>\u00a0 </span>Nationalism is bound to arise precisely as an overreaction against oikophobia.<span>\u00a0 </span>Those who are currently reacting to what they perceive as a resurgent nationalism by doubling down on oikophobia \u2013 pushing for open borders, indiscriminately denouncing their opponents as racists and xenophobes, etc. \u2013 are making a true nationalist backlash <i>more </i>likely, not less likely.<span>\u00a0 </span>The only true remedy for the evils of nationalism and oikophobia is, as John Paul II taught, the sober middle ground of patriotism.</span></div><div><span><br></span></div><div><span>It is no accident that those prone to oikophobia tend to be precisely the same people as those who want to push further the sexual revolution, feminism, and the destruction of the traditional family and traditional sex roles that these entail.<span>\u00a0 </span>The same liberal individualist poison is at the core of all of these attitudes.<span>\u00a0 </span>As St. John Paul II said, \u201c<i>patria </i>is associated with the idea and the reality of \u2018father\u2019 (<i>pater</i>).\u201d<span>\u00a0 </span>Hatred of masculinity and of the paternal authority and responsibilities that are its fulfilment, hatred of the traditional family and of the sexual morality that safeguards it, and hatred of one\u2019s fatherland, are ultimately of a piece.<span>\u00a0 </span>And lurking beneath them all is a deeper hatred for another, heavenly Father.</span></div><div><span><br></span></div><div><span>Further reading:</span></div><div><span><br></span></div><div><span><span><a href=\"https://edwardfeser.blogspot.com/2017/10/liberty-equality-fraternity.html\">Liberty, equality, fraternity?</a></span></span><span></span></div><div><span><br></span></div><div><span><span><a href=\"http://edwardfeser.blogspot.com/2019/06/continetti-on-post-liberal-conservatism_2.html\">Continetti on post-liberal conservatism</a></span></span><span></span></div><div><span><br></span></div><div><span><span><a href=\"https://www.claremont.org/crb/article/hayeks-tragic-capitalism/\">Hayek\u2019s Tragic Capitalism</a></span></span></div>"
},
"visual": {
"url": "none"
},
"unread": true,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/fbdcd69b-7e27-4b6a-bfed-6584b944155d",
"label": "\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb\ud83e\udd1e\ud83c\udffb Renamed"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572499824479
},
{
"originId": "https://www.raywenderlich.com/5436806-modern-collection-views-with-compositional-layouts",
"fingerprint": "16268498",
"id": "RFlzskW4NhJjlZfijOSI8IXqM9+zz6V9qnDVl1gxaJs=_16e1cddfaa1:1c015:d4506071",
"updated": 1572440368000,
"summary": {
"direction": "ltr",
"content": "In this tutorial, you\u2019ll learn how to build beautiful, modern UICollectionView layouts using iOS 13\u2019s new declarative UICollectionViewCompositionalLayout API."
},
"alternate": [
{
"href": "https://www.raywenderlich.com/5436806-modern-collection-views-with-compositional-layouts",
"type": "text/html"
}
],
"crawled": 1572442340001,
"title": "Modern Collection Views with Compositional Layouts [FREE]",
"published": 1572440368000,
"origin": {
"streamId": "feed/http://www.raywenderlich.com/feed",
"htmlUrl": "http://www.raywenderlich.com/feed",
"title": "Ray Wenderlich | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more"
},
"unread": false,
"readTime": 3593,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/885f2e01-d314-4e63-abac-17dcb063f5b5",
"label": "Programming"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572499811331
},
{
"originId": "https://inessential.com/2019/10/30/etas_follow_up",
"fingerprint": "d48dc2d2",
"id": "+jHfsXnBCVfCstSIW1WDumAyigT4rnsUPnI5WFxgnAU=_16e1e5e8e9e:1ca95:d4506071",
"summary": {
"direction": "ltr",
"content": "<p>Some people took my post <a href=\"https://inessential.com/2019/10/28/no_etas\">No ETAs</a> as if I were arguing against doing software estimates of any kind, ever.</p>\n<p>I didn\u2019t actually mean that. If your boss, project manager, or person you\u2019re contracting with asks for an estimate, do your best to come up with something accurate. If you\u2019re writing enterprise software, you may even be contractually bound to provide estimates for when features will ship.</p>\n<p>There are ways to get pretty good at this. Pay attention to history and avoid wishful thinking. Don\u2019t assume perfect productivity. Allow for the unexpected, because there\u2019s always something.</p>\n<p>What I\u2019m talking about is the case where you\u2019re writing a consumer-facing app \u2014\u00a0something that would get published on an app store, for instance \u2014\u00a0and customers or potential customers ask about an ETA for a given feature. Don\u2019t do it! (For the reasons stated in the article.)</p>"
},
"alternate": [
{
"href": "https://inessential.com/2019/10/30/etas_follow_up",
"type": "text/html"
}
],
"crawled": 1572467543710,
"title": "ETAs: Follow-Up",
"published": 1572466202000,
"origin": {
"streamId": "feed/http://ranchero.com/xml/rss.xml",
"htmlUrl": "https://inessential.com/",
"title": "inessential.com"
},
"unread": false,
"readTime": 6552,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/66132046-6f14-488d-b590-8e93422723c8",
"label": "The number Three 333"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572499788300
},
{
"keywords": [
"Apple"
],
"originId": "https://9to5mac.com/?p=617593",
"fingerprint": "a1dafaae",
"id": "BmoAzSEWHFzR01wyxBZAhNEo11Vy8oDR1qKDe+tKVEQ=_16e1de23321:1c6e3:d4506071",
"author": "Guilherme Rambo",
"summary": {
"direction": "ltr",
"content": "<div><img src=\"https://9to5mac.com/wp-content/uploads/sites/6/2019/10/16-inch-macbook-pro-touch-bar-keyboard.jpg?quality=82&strip=all&w=1600\"></div>\n<p>Rumors about a new 16-inch MacBook Pro are not exactly new, with recent icon evidence found in macOS Catalina betas suggesting the redesign mentioned in some reports is not going to happen as we thought.</p>\n<p> <a href=\"https://9to5mac.com/2019/10/30/exclusive-16-inch-macbook-pro-touch-bar-and-touch-id-layout-confirmed/#more-617593\">more\u2026</a></p>\n<p>The post <a rel=\"nofollow\" href=\"https://9to5mac.com/2019/10/30/exclusive-16-inch-macbook-pro-touch-bar-and-touch-id-layout-confirmed/\">Exclusive: 16-inch MacBook Pro Touch Bar and Touch ID layout confirmed</a> appeared first on <a rel=\"nofollow\" href=\"https://9to5mac.com\">9to5Mac</a>.</p>"
},
"alternate": [
{
"href": "https://9to5mac.com/2019/10/30/exclusive-16-inch-macbook-pro-touch-bar-and-touch-id-layout-confirmed/",
"type": "text/html"
}
],
"crawled": 1572459393825,
"title": "Exclusive: 16-inch MacBook Pro Touch Bar and Touch ID layout confirmed",
"published": 1572456327000,
"origin": {
"streamId": "feed/http://9to5mac.com/feed/",
"htmlUrl": "https://9to5mac.com",
"title": "9to5Mac"
},
"unread": false,
"readTime": 3947,
"categories": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815",
"label": "Macintosh"
}
],
"tags": [
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.read",
"label": ""
},
{
"id": "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/tag/global.saved",
"label": "Saved For Later"
}
],
"actionTimestamp": 1572499186128
}
]
}