Jekyll2018-07-10T16:18:26+00:00https://stevemoser.org/Steve MoserSteve Moser is a Senior Consultant at Levvel.
RichTexture2018-05-04T09:41:00+00:002018-05-04T09:41:00+00:00https://stevemoser.org/posts/apple-dev/richtexture<p>Today I’m <a href="https://itunes.apple.com/app/richtexture/id1376116077">releasing</a> and <a href="https://github.com/stevemoser/richtexture">open sourcing RichTexture</a>, a rich text editor for iOS. I started this project after discovering Louis D’hauwe’s open source plain text editor for iOS, <a href="https://github.com/louisdh/textor">Textor</a>. I forked his editor and replaced plain text editing with rich text editing. RichTexture is the first open source iOS rich text editor that supports saving and opening files through the system documents browser. This is important because even though Apple’s Pages app supports opening rich text (.rtf and .rtfd) files, it only allows for saving files in the Pages (.pages) file format.</p>
<p>RichTexture is a few system APIs glued together:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RichTexture = Textor (UIDocument + UIDocumentBrowserViewController + UITextView) + NSAttributedString (storing rich text for UITextView) + NSFileWrapper (converting NSAttributedString to an .rtf file)
</code></pre></div></div>
<p>RichTexture is available on the <a href="https://itunes.apple.com/app/richtexture/id1376116077">App Store</a>.</p>Today I’m releasing and open sourcing RichTexture, a rich text editor for iOS. I started this project after discovering Louis D’hauwe’s open source plain text editor for iOS, Textor. I forked his editor and replaced plain text editing with rich text editing. RichTexture is the first open source iOS rich text editor that supports saving and opening files through the system documents browser. This is important because even though Apple’s Pages app supports opening rich text (.rtf and .rtfd) files, it only allows for saving files in the Pages (.pages) file format.Permalinks2018-03-08T00:00:00+00:002018-03-08T00:00:00+00:00https://stevemoser.org/posts/web-dev/permalinks<p><em>This post is inspired by <a href="https://mattgemmell.com/permalinks/">Matt Gemmell’s post</a>.</em></p>
<ul>
<li>Even though most sites are hosted on Linux machines that are case-sensitive a static site should bake correctly on a machine that isn’t. Thus as a bare minimum URLs should be case-insensitive and in my opinion case-preserving as well.</li>
<li>I agree that URLs should minimize noise and thus remove dates in most cases</li>
<li>Pretty URLs are fine but I don’t like them for simple html content since navigating a downloaded version of the site leads to a lot of /index.html files. Thus having a ‘.html’ suffix is better than the /index.html noise. It is Natural URL Structure.</li>
<li>Computers serve humans so that in the case where it is simple URLs after the host should be mixed case for improved readability.</li>
<li>One exception is for paths that could become part of the host. For instance an organization name in GitHub is used for the subdomain for its GitHub pages URL.</li>
<li>My blog posts are under /posts/ because jekyll</li>
</ul>This post is inspired by Matt Gemmell’s post.Designing and Developing for iPhone X2017-12-13T09:41:00+00:002017-12-13T09:41:00+00:00https://stevemoser.org/posts/apple-dev/designing-and-developing-for-iphone-x<p><img src="https://cdn.levvel.io/blog_content/Designing%20and%20Developing%20for%20iPhone%20X/Designing%20and%20Developing%20for%20iPhone%20X-c5SzfSJ4vf4uNKJjvDl2mhyK1fMlYpKu.jpeg" alt="Levvel Branded iPhone" /></p>
<p><em>Note: this post originally appeared on <a href="https://www.levvel.io/our-ideas/Designing-and-Developing-for-iPhone-X">Levvel’s blog</a></em></p>
<p>The iPhone X is a large departure from previous forms of iPhone devices—one that will be a disruptive force in the digital device marketplace in the months to come. In order to keep up with the changing space, developers and designers creating 3rd-party applications for the iPhone X must be able to adapt their applications to the new version’s APIs while still supporting older devices. One of the best ways to prepare for this is to become well acquainted with the X, including the changes in its screen, gestures, and buttons, and with the updated <a href="http://help.apple.com/iphone/11/#/">iPhone User Guide</a> to find out where functionality has moved in the new version.</p>
<p>App creators should also check out how Apple’s native apps and leading 3rd-party apps have been updated for the new version. The following section offers some highlights on the new changes in the iPhone X, and what designers and developers should keep in mind as they create applications for this device.</p>
<h2 id="screen">Screen</h2>
<p><img src="https://cdn.levvel.io/blog_content/Designing%20and%20Developing%20for%20iPhone%20X/Designing%20and%20Developing%20for%20iPhone%20X-tTBb1vc4Zb7aBaOrm8ZmdBwZkgCcxHRo.png" alt="iPhone X Corner" /></p>
<p>The new edge-to-edge screen is the headlining feature of iPhone X. You should get acquainted with the resulting safe areas because of the new rounded corners and the sensor housing. You should also become familiar with the new aspect ratio, OLED pixels, and true 3x resolution.</p>
<h2 id="safe-areas">Safe Areas</h2>
<p>The all new Super Retina display doesn’t have a single right angle on it, including around the notch at the top, which Apple refers to as the sensor housing. The hardware seems to melt into the software, especially at the bottom where the curve of the phone’s corners, display corners, dock corners, and app corners all match.</p>
<p>To extend this rich aesthetic to your app, Apple recommends a 16pt radius to match the main corners. Also, use the safe area and layout margins provided by UIKit to make sure content and controls are not occluded by the corners or the sensor housing. When your background content does reach the corners you don’t have to worry about pixelated edges since Apple handles the anti-aliasing for you. The safe area layout guide also provides backward compatibility for your apps running on older devices by reducing their size to zero (since older devices have no unsafe areas to avoid).</p>
<p>If your app already uses UIKit controls and bars along the top and bottom, you will have a much easier time updating your app for iPhone X. In fact, if you are using storyboards, it can be as easy as checking the ‘Enable Safe Area Layout Guide’ checkbox to perform an automatic migration of your constraints to use the safe area layout guide. Be sure to fix any constraints to use the superview instead of the safe area layout guide or vice versa. Typically if a view has edge-to-edge background content without controls, like a header parallax image, then you will want to use a superview in a constraint. Otherwise, it is best to stick with the safe area layout guide. Of course, any top or bottom layout defined in code will have to be updated, as no automatic code migration is provided for the safe area layout guide. For more information about the safe area layout guide checkout <a href="https://useyourloaf.com/blog/safe-area-layout-guide/">Use Your Loaf’s post</a>.</p>
<h2 id="keyboard">Keyboard</h2>
<p>The new screen also changes the keyboard height. With the edge-to-edge display, the keyboard was made much taller in order to keep the keys in an ergonomic position, so be on the lookout for code that assumes the height of the keyboard. Even if your code doesn’t make assumptions about the height of the keyboard you will probably have to update your UITextField and UITextField’s inputAccessoryView so that content appears within the safe area. You’ll also have to update it so that your bar doesn’t run into the indicator when an external keyboard is connected, since in that case it would be at the bottom of the screen. If you’re using the popular IQKeyboardManager library you’ll want to update to the latest version, as it fixes many of these issues.</p>
<p><img src="https://cdn.levvel.io/blog_content/Designing%20and%20Developing%20for%20iPhone%20X/Designing%20and%20Developing%20for%20iPhone%20X-ueHdDpIkfUf1rAdOpYgLYDAHgJQppYjC.png" alt="iPhone X keyboard bar error" /></p>
<h2 id="aspect-ratio">Aspect Ratio</h2>
<p>The new display also brings a new aspect ratio (19.5:9) to iOS devices (this also means there is no Display Zoom support because Display Zoom requires taking advantage of developers supporting the same aspect ratio on smaller devices and there is no smaller 19.5:9 device).</p>
<p>The new aspect ratio shouldn’t matter too much if you’re correctly resizing your app for every screen size. However, it might impact you if you are making assumptions about the aspect ratio for scrolling content or have a full-screen image that is relying on a certain aspect ratio. For example, with iOS 10 only iPhone devices with 16:9 displays were supported.</p>
<p>I came across one app that changed the translucency of the navigation bar over a header image based on what percentage of the screen was scrolled. With the new ratio of iPhone X, that calculation has to incorporate the aspect ratio of the screen as well.</p>
<p>Also, be sure that either an aspect fill of your existing image doesn’t cut off any important content, or provide a new asset. The latter is prefered since iPhone X has the first true 3x display of any iOS device. The plus-size phones render a 3x Retina image scaled down by 1.15. In any case any non full-screen 3x assets used for the plus-size devices will work on iPhone X.</p>
<h2 id="oled">OLED</h2>
<p>If your app provides a dark theme with a dark gray background, consider adding another dark theme with true black. True black looks much better on the OLED Super Retina display because the contrast is much higher for this color theme. Also consider a true white background if your app has an off-white tint theme. This is because users that opt to use the new Smart Invert feature will see true black if they have that feature enabled.</p>
<h2 id="smart-invert">Smart Invert</h2>
<p>Smart Invert inverts the colors on all views except those marked by a developer or UIKit as “not needing inversion”. For example, a UISwitch would turn from green to purple with Classic Invert, but with Smart Invert it stays green, which ends up looking like the Clock app. Also, with Smart Invert, if a screen is dark by default like the Clock app or the movies tab in the iTunes app, developers can make it stay dark.To support Smart Invert, developers should check out the <a href="https://developer.apple.com/documentation/uikit/uiview/2865843-accessibilityignoresinvertcolors">accessibilityIgnoresInvertColors property on UIView</a>.</p>
<h2 id="top-notch">Top Notch</h2>
<p>One word on the ‘Embrace the Notch’ debate. I agree with Apple that the notch should be embraced for two reasons. First, because it reduces the wear and burn-in on the Super Retina display and second because the rest of iOS embraces the notch. Any 3rd-party app that doesn’t embrace the notch will look out of place, as it gives the device a non-symmetrical look that isn’t seen anywhere else in iOS.</p>
<p><img src="https://cdn.levvel.io/blog_content/Designing%20and%20Developing%20for%20iPhone%20X/Designing%20and%20Developing%20for%20iPhone%20X-eoU4aDJEhXNYf3JO9Y9D5EbU34HW73pX.jpeg" alt="From Apple’s ‘Designing for iPhone X’ video" /></p>
<p>From Apple’s ‘Designing for iPhone X’ video</p>
<h2 id="gestures-and-buttons">Gestures and Buttons</h2>
<p>In the iPhone X, the Home button is gone and its duties have been divided between what Apple calls the indicator (the long pill shape at the bottom of the screen) and the renamed side button. Previously Apple called this side button the Wake/Lock button. It seems likely that they are taking a cue from the Apple Watch since image push notifications and a double click of the side button to confirm Apply Pay eventually made their way to iPhone.</p>
<p>In any case, designers and developers will have to be mindful of the indicator at the bottom of the screen. Although Apple allows developers to hide it for viewing full-screen content like photos and videos, the indicator should rarely be hidden for at least two reasons.</p>
<p>First, it is a buffer and a reminder for designers and developers to not fill the bottom of the screen with controls since the area around the indicator can we used to swipe left and right for multitasking. Second, it shows the orientation of the device, which is especially important if no text is on screen to hint at the orientation. The orientation is important because swiping from the bottom of the current orientation of the screen is the only way to go to the Home screen.</p>
<p>In <a href="https://youtu.be/-7dTzc8kTOY?t=2m21s">Casey Neistat’s review of iPhone X</a> he stated that the DJI app froze on him and because iPhone X has no hardware Home button he wasn’t able to exit the app. I believe what happened is that the DJI app hid the indicator while in landscape mode. When Casey was swiping from the bottom of the phone instead of the bottom of the screen orientation (which is the left side of the screen here) the indicator became unhidden on the left side of the screen (which you can see below). Swiping from the left or right edge of the device according to the screen orientation does nothing and thus Casey thought that app was frozen and couldn’t get to the Home screen. I verified that blocking the main thread doesn’t prevent the swipe-up-to-go-Home gesture from working by creating a test app.</p>
<p><img src="https://cdn.levvel.io/blog_content/Designing%20and%20Developing%20for%20iPhone%20X/Designing%20and%20Developing%20for%20iPhone%20X-jLEBAmtSSLZ7uBcYwpbskg2vkO0cVK7i.png" alt="Casey Neistat’s review of iPhone X" /></p>
<h2 id="face-id">Face ID</h2>
<p>Finally, three quick notes about Face ID. First, if you are linking on iOS 11 or later, you will have to add the <code class="highlighter-rouge">NSFaceIDUsageDescription</code> usage description key with a description to your Info.plist if you want to use Face ID. This is used in place of Touch ID’s localizedReason string.</p>
<p>The text that goes with it says, “Do you want to allow ‘App Name’ to use Face ID?”. This alert isn’t so much for privacy’s sake, like access to your photo library, as it is for user preference, like the notifications permission dialog. Second, you’ll want to test when the user declines or enables this through the Settings app under the Face ID & Passcode section.</p>
<p>Keep in mind that you’ll have to test this on an actual device as this setting isn’t available on the simulator. Third, Face ID behaves a little differently than Touch ID. For whatever reason when Face ID scans a user’s face your app briefly enters the background and <code class="highlighter-rouge">applicationDidEnterBackground</code> is called. When this finishes, your app becomes active and <code class="highlighter-rouge">applicationDidBecomeActive</code> is called. This can lead to an authentication dialog loop as seen in the Barclay app if an app brings up a biometric authentication dialog during <code class="highlighter-rouge">applicationDidBecomeActive</code>.</p>
<h2 id="in-conclusion">In Conclusion</h2>
<p>These are a handful of tips for developing and designing for iPhone X. For more information check out Apple’s updated <a href="https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/">Human Interface Guidelines section for iPhone X</a> and <a href="https://developer.apple.com/videos/play/fall2017/801/">Designing for iPhone X video</a>.</p>Is your App at Risk of Getting Kicked out of the App Store?2016-11-02T12:00:00+00:002016-11-02T12:00:00+00:00https://stevemoser.org/posts/apple-dev/is-your-app-at-risk-of-getting-kicked-out-of-the-app-store<p><em>Note: this post originally appeared on <a href="https://www.levvel.io/our-ideas/is-your-ios-app-at-risk">Levvel’s Blog</a></em></p>
<p>While developers are thinking about Swift 3, Xcode 8, and support for iOS 10, app owners are considering whether it is the time to update their years-old iOS apps. Apple has just given app owners a great reason to consider updating their apps, <a href="https://developer.apple.com/support/app-store-improvements/">announcing</a> that it is “cleaning up” the App Store by removing old apps that haven’t been updated in some time and will thus fail to pass the new app review process. If your app becomes non-compliant, Apple is giving you 30 days to update it. This process has the potential to affect a large number of apps, as <a href="https://david-smith.org/blog/2016/09/03/a-sizeable-cleanup/">roughly half</a> of the apps in the App Store have not been updated in the last year. This post will walk you through the main points to consider when updating your app for iOS 10.</p>
<p><img src="https://cdn.levvel.io/blog_content/iOS10-Update-Blog-Post/ipad-and-iphone.jpeg" alt="ipad and iphone" /></p>
<h2 id="swift-update">Swift Update</h2>
<p>When you first open your app in Xcode 8, you’ll be prompted to update the version of Swift your app uses. For the first time, you have two options: you can either make a smaller update to Swift 2.3 or leap all the way forward to Swift 3.0. By updating to Swift 3.0, you’ll not only be more prepared for the next version of Swift but you’ll also have access to Xcode 8’s new <a href="https://developer.apple.com/videos/play/wwdc2016/412/">thread sanitizer</a> and <a href="https://developer.apple.com/videos/play/wwdc2016/410/">visual memory debugger</a>. The thread sanitizer helps surface difficult to find concurrency issues. The visual memory debugger graphs object ownership in your app, which can help you detect memory leaks. However, updating to Swift 3.0 is a more difficult update than moving to 2.0 for many reasons, one of them being the pervasive syntax changes. You’ll also have to update your dependencies for Swift 3.0. Hopefully, the Swift version migrator runs flawlessly but, if it doesn’t, you can rerun the migrator. For a sufficiently large Swift project, however, you’ll probably have to manually update your code, which is beyond the scope of this post.</p>
<h2 id="objective-c-update">Objective-C Update</h2>
<p>Since Objective-C hasn’t had any major changes in the past couple of years, you should be able to build and run your app in Xcode 8 without any errors, for the most part. However, you’ll probably see new warnings about nullability annotations and lightweight generics. <a href="https://developer.apple.com/swift/blog/?id=25">Nullability annotations</a> let the compiler and other developers know which pointers may or may not be null. This also allows your swift code to use optionals for pointer types defined in your Objective-C code that are annotated as nullable. Lightweight generics allows you to specify the type of objects inside of a collection. Adopting both of these changes can be tedious but they should be a priority—not only because they allow your Swift code to better interoperate with your Objective-C code—but because they will also make your code more explicit and safer.</p>
<h2 id="update-deployment-target">Update Deployment Target</h2>
<p>Your next decision when upgrading your app is which minimum iOS version you want to target. This is different from the base SDK, which should be set to ‘Latest’ and, consequently, will be iOS 10 in Xcode 8. Because iOS users update their devices so quickly, the general consensus and Apple’s recommendation is to target the last minor version of the previous major release. Since iOS 10.1 is out, that means your app’s deployment target should be 9.3. With the new deployment target set, be sure to remove code that references previous iOS versions through system version checks. While we’re on the subject of system version checks, make sure your code doesn’t check for the system version like this:</p>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><code class="hljs undefined">
#define IsIOS7 ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=7)
</code>
</pre>
<p>This will return false for iOS 9 but true for iOS 10, because it only compares the first character of the returned system version. This is apparently as <a href="https://github.com/search?q=%255B%255B%255BUIDevice+currentDevice%255D+systemVersion%255D+substringToIndex%253A1%255D&type=Code&utf8=">widespread</a> as the <a href="http://www.pcworld.com/article/2690724/why-windows-10-isnt-named-9-windows-95-legacy-code.html">Windows system version check</a> looking for Windows 95 or 98.</p>
<h2 id="find-and-fix-new-warnings">Find and Fix New Warnings</h2>
<p>When you compile and run your app, you’ll most likely see some new warnings about deprecated methods, but hopefully your app runs the first time. If it exits on launch, check the console for a line similar to this:</p>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><code class="hljs undefined">
The app's Info.plist must contain an NSPhotoLibraryUsageDescription key.
</code>
</pre>
<p>Usage description keys have been around awhile but, starting with iOS 10, Apple requires all systems prompts for access to the user’s data to include a usage description. If your app doesn’t include the corresponding description for a system prompt, it will exit on launch. Simply add a usage description key for each framework that accesses user data to your app’s info.plist file. If you already included usage description keys in the past, then be sure to also check out the <a href="https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html">new required usage description keys</a>. Note that your app might not exit on launch if a dependency in your library links against one of these frameworks, but you still need to include a usage description; otherwise, your app will not pass validation when uploading to iTunes Connect.</p>
<p>On the topic of dependencies, now would be a good time to update those as well. If you are using CocoaPods, update your Podfile with your deployment target and then run ‘pod update’ to fetch updates for your pods.</p>
<p>Before you start working your way down the list of new warnings, first update to the recommended Xcode project settings by selecting ‘project’ in the sidebar, then in the menu select Editor → Validate Settings…, then Perform Changes. Among other things, this will turn on new compiler checks that will generate new warnings. After you have fixed the resulting warnings, go ahead and run the static analyzer on your project, since it includes new checks in Xcode 8.</p>
<p>In addition to fixing deprecated methods, I ran into some other warnings when updating my iOS 7 app to iOS 10, such as a crash when presenting UIActivityViewController on iPad. If you try to present a UIActivityViewController without specifying a popover presentation controller source view in iOS 8 or newer, your app will crash and produce the following log within the console:</p>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;"><code class="hljs undefined">
Your application has presented a UIActivityViewController (<UIActivityViewController: 0x7ffd88c6c730>). In its current trait environment, the modalPresentationStyle of a UIActivityViewController with this style is UIModalPresentationPopover. You must provide location information for this popover through the view controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the view controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.
</code>
</pre>
<p>Fixing this is usually as simple as what the log suggests. In my case, I set my UIActivityViewController popoverPresentationController’s sourceView to the button that calls up the Activity View Controller.</p>
<p>Another issue I encountered related to launch storyboard requirements. iOS 8 introduced launch storyboards, which allow you to specify how your launch image displays across all supported iOS device sizes with a single adaptive storyboard. This will save time in the long run as Apple introduces new device sizes, but if you are not ready to make that investment you can opt out of it on iPad-only apps with the ‘UIRequiresFullScreen’ info.plist key.</p>
<p>Once you’ve updated your deployment target, updated your dependencies, and fixed your warnings, you’re ready to upload your app to iTunes Connect. I would suggest, however, that you take the time to go beyond SDK compatibility and strive for taking advantage of the updated SDK.</p>
<h2 id="ios-8-sdk">iOS 8 SDK</h2>
<p>The biggest change that the iOS 8 SDK brings to the table is adaptivity. Adaptivity allows developers to specify how their app should best fill a certain screen size through AutoLayout and new adaptivity APIs handle the rest. Developers no longer have to maintain different files for iPhone and iPad layout. While the new adaptivity APIs are powerful, they can take a significant amount of time to adopt—especially if your app doesn’t use AutoLayout yet. Before iOS 8, the only screen size change introduced to iOS came as a result of the extra height of the iPhone 5 and iPhone 5s devices. These were relatively simple to support since most content on iOS scrolls vertically. When the iPhone 6 and 6 Plus devices arrived, they changed not only the height but also the width of the screen. Now developers have to consider how their layout and especially their text layout expands and truncates with the different sizes. Designers also have to get involved by cutting new 3x assets for iPhone devices with 5.5-inch Retina HD Displays. Note that Apple still accepts iPhone 5-only sized apps in the App Store.</p>
<p>If you’re not ready to take on this change, your app will simply expand to fill the screen. However, users will notice that you are not taking full advantage of their screen size especially when they try to type on the blown up keyboard they are unaccustomed to seeing in other appropriately sized apps. Also, no one knows how much longer Apple will allow updates for iPhone 5 only sized apps in the App Store.</p>
<h2 id="ios-9-sdk">iOS 9 SDK</h2>
<p>The iOS 9 SDK continued with the theme of adaptivity from the iOS 8 SDK by bringing support to iPad. Since iOS 9 allows iPad users to use apps in split screen and slide-over modes, developers must allow their app to gracefully fill these new sizes. Like before, Apple will still accept apps that don’t support these new modes, but no one knows for how long.</p>
<p>3D Touch was another enhancement that Apple introduced with iOS 9. It allows for new peek and pop pressure sensitive options. Thankfully, these are relatively easy to support for vanilla UIKit applications.</p>
<h2 id="ios-10-sdk">iOS 10 SDK</h2>
<p>This year’s iOS 10 SDK is relatively easy to support, especially since no new device screen sizes were introduced with it, though you do have to contend with App Transport Security (ATS) starting in the new year. ATS is a security measure by Apple to ensure that your app communicates securely with its back end. In order to meet its security requirements, your app must use HTTPS and TLS version 1.2 with forward security. ATS was easily ignored when it was introduced in iOS 9 by setting the NSAllowsArbitraryLoads key to YES under the NSAppTransportSecurity dictionary key. This prevents the alert below from popping up. However, starting January 1, 2017, all apps submitted to the App Store are required to use ATS. If you foresee this being an issue for your app, you’ll want to get your app update out before this requirement hits.</p>
<p><img src="https://cdn.levvel.io/blog_content/iOS10-Update-Blog-Post/iOS10-blog-error.png" alt="error message" /></p>
<h2 id="itunes-connect">iTunes Connect</h2>
<p>Before you submit your update to the App Store via iTunes Connect, you might need to guard against roadblocks, such as code signing. If it has been a year since your last update, then your app signing setup is probably expired. Thankfully, Apple has further improved its ‘Fix Issue’ button by adding Automatic Code Signing with Xcode8. Previously, this button might overwrite a previous provisioning profile that was correctly set up on a coworker’s machine and thus render the coworker’s code signing setup useless. This brought on so much frustration that a developer made an Xcode plugin to disable this button entirely in order to prevent wasted afternoons of resetting of provisioning profiles. With Xcode 8, Automatic Code Signing instead uses a dedicated profile managed by Xcode, which means you can turn on Automatic Code Signing without worrying about messing up your coworker’s signing setup after checking in your project settings file. Just go to your project’s target and tick on the Automatic Code Signing checkbox shown below and then click ‘Enable Automatic’ to accept the changes.</p>
<p><img src="https://cdn.levvel.io/blog_content/iOS10-Update-Blog-Post/iOS10-blog-manage.png" alt="manage" /></p>
<p><img src="https://cdn.levvel.io/blog_content/iOS10-Update-Blog-Post/iOS10-blog-reset.png" alt="reset" /></p>
<p>With code signing fixed, you can now create a new version of your app in iTunes Connect, build an archive, and upload your app. If everything went okay, then you’ll be ready to submit your app for review. If your app uploaded to iTunes Connect but you don’t see the build, be patient. If you still don’t see your build after 30 minutes, check the developer email address associated with your app. When I tried this with my app, I discovered that one of my dependencies had linked against a framework that requires a usage description key for privacy purposes. If you run into issues like this, you’ll need to increase your app’s build number (not its version number) after you fix the issue and upload it again in order for iTunes Connect to see the new version of your app.</p>
<p>Even now, just as you’re ready to hit the ‘Submit for Review’ button, you might hit one or two more snags. In recent years, Apple has reduced the number of allowed special characters in your app description. Simply remove those restricted characters and move on to the screenshots, if this applies. If you’re submitting an iPad compatible application, iTunes Connect needs an iPad Pro screenshot. This shouldn’t take long to do well, but if you’re in a real hurry, Apple will accept blown up versions of your existing iPad screenshots.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Getting your app up and running with the iOS 10 SDK might take a little more time and require extra attention, but it’s worth it. Not only will you get to keep your app in the App Store, but users will appreciate the speed and reliability that comes with building your app against the latest SDK.</p>Note: this post originally appeared on Levvel’s BlogREADME2015-07-29T12:00:00+00:002015-07-29T12:00:00+00:00https://stevemoser.org/posts/README<p>Welcome to my blog/wiki/bliki/memex. It is currently formatted in <a href="http://daringfireball.net/projects/markdown/">Markdown</a>, generated by <a href="http://jekyllrb.com/">Jekyll</a>, built by and hosted on <a href="https://www.netlify.com">Netlify</a>. You can also <a href="https://github.com/stevemoser/jekyll-netlify-cms">view it on GitHub</a>. If you see room for improvement (even just a typo) please use the edit button above and submit a pull request.</p>
<h4 id="history">History</h4>
<p>Brief rundown of my blogging past:</p>
<ol>
<li><strong>Geocities</strong> - My first page</li>
<li><strong>Twitter</strong> - Microblogging!</li>
<li><strong>Tumbler</strong> - So simple, yet little control</li>
<li><strong>Wordpress</strong> - More control and complexity</li>
<li><strong>Jekyll</strong> - Simplicity and control but a little bare</li>
<li><strong>Octopress</strong> - That looks nice… like every other hacker blog</li>
<li><strong>Jekyll generated and hosted on Github Pages</strong> - Editing on Github works but is a pain on mobile and no support for unsafe plugins</li>
<li><strong>Jekyll generated by Travis CI and hosted on Github Pages</strong> - More control but complicated and no HTTPS with custom domains</li>
<li><strong>Jekyll on Gitlab</strong> - It even includes its own CI! Sadly as of this writing custom domains are disabled due to a bug</li>
<li><strong>Jekyll on Netlify</strong> - Simple and one click HTTPS with a custom domain. Plus with Netlify CMS I can edit on mobile.</li>
</ol>
<p>In the future you can find a step by step guide for setting up a blog/wiki like mine.</p>
<!---
#### Starting Point
Here are a few good starting points for exploring content here:
* [Why be findable?](sociology/why-be-findable.md)
* [Syndicated Memex](syndicated-memex.md)
#### Categories
* [Apple Development](apple-dev/README.md)
* [Computing](computing/README.md)
* [Sociology](sociology/README.md)
* [Programming](programming/README.md)
#### Stubs
There may be links to posts with little or no content and that is okay. This allows me to write about things as deep or broad as I want to go and come back and flesh out the in-between pages later. Normally this would lead to a mess with a normal blog but hopefully most people don't consume this site like a normal blog.
# TODO: create PR post and link -->
<!--- # TODO: create blog background post and link -->
<!--- # TODO: List tags -->Welcome to my blog/wiki/bliki/memex. It is currently formatted in Markdown, generated by Jekyll, built by and hosted on Netlify. You can also view it on GitHub. If you see room for improvement (even just a typo) please use the edit button above and submit a pull request.Falsehoods Programmers Believe About Systems of Measurement2013-08-07T10:15:00+00:002013-08-07T10:15:00+00:00https://stevemoser.org/posts/dev/falsehoods-programmers-believe-about-systems-of-measurement<p>When starting <a href="https://github.com/stevemoser/UnitsKit">UnitsKit</a> I had many false assumptions about how irregular systems of measurement could be. Even after studying the subject and other existing libraries I was surprised by how many more irregularities I found. Inspired by Patrick McKenzie’s post about <a href="http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/">‘Falsehoods Programmers Believe About Names’</a> I have set out to form a non-complete list of irregulars when working with systems of measurement and converting between them.</p>
<ol>
<li>There is more than one variant of the metric system. (MKS vs CGS)</li>
<li>All base SI units are prefix-less. (The kilogram is the base unit of mass)</li>
<li>All derived metric units are derived of base SI units. (The liter is based off of decimeters)</li>
<li>Heterogenous units are of no practical use. (Radar beam height formula uses a constant expressed in nautical miles per foot)</li>
<li>Fractional dimensions are of no practical use. (Radar beam height formula uses a constant expressed in <a href="http://www.boost.org/doc/libs/1_37_0/doc/html/boost_units/Units.html">nautical miles per foot^(1/2)</a>)</li>
<li>Non-metric systems have base units as well.</li>
<li>Just as liters has decimeters so that it doesn’t need a numerical proportionality constant, pints has <code class="highlighter-rouge">yardsInOneDimensionOfAPint</code>. (I made up my own unit for this, a little more than 11 of them fit in a yard).</li>
<li>A gallon is treated much like a liter in their respective systems of measure. (Liter is not an official SI unit but a gallon is an official Imperial unit).</li>
<li>All base units are made of base dimensions. (The gallon ‘base’ unit is made of the derived volume dimension)</li>
<li>A gallon is a gallon is a gallon. (Did you mean a liquid or dry gallon, US, Imperial, or a ten-gallon hat?)</li>
<li>Written out unit names are not case-sensitive (Calorie vs. calorie)</li>
<li>Base units always reduce to the same derived units. (Did you mean a Joule or a Newton meter? You might know but then you have to keep track of plane and solid angle units.)</li>
<li>Written out base units should always be presented in the same order (Are capital symbols, units with positive exponents, or length dimension units first?)</li>
<li>There is no need to differentiate between absolute and relative measurements. (Kelvin and Fahrenheit)</li>
<li>Derived unit symbols are represented the same way across systems of measure (mph vs km/h)</li>
<li>All units accepted for use with the SI are base ten (the hour and minute are base 60, Sexagesimal, blame the moon)</li>
<li>You will never have any namespace issues. (Is that h an hour or the Planck constant?</li>
</ol>When starting UnitsKit I had many false assumptions about how irregular systems of measurement could be. Even after studying the subject and other existing libraries I was surprised by how many more irregularities I found. Inspired by Patrick McKenzie’s post about ‘Falsehoods Programmers Believe About Names’ I have set out to form a non-complete list of irregulars when working with systems of measurement and converting between them.How to Create a Shared iAd banner in a Tabbed Application with Storyboards2013-04-24T20:45:00+00:002013-04-24T20:45:00+00:00https://stevemoser.org/posts/apple-dev/how-to-create-a-shared-iad-banner-in-a-tabbed-application-with-storyboards<p>While looking at Apple’s iAd Suite sample code I noticed that the TabbedBanner example was the perfect use case for iOS 6’s new <em>Container View</em> Storyboard object. It allows a view controller to be placed inside another view controller which is exactly how we want our banner view controllers setup. No code. Actually it gets better, to get Apple’s example to work with container views we mostly remove code! Check out my example <a href="https://github.com/stevemoser/TabbedBanner">GitHub project</a> or follow below to see how.</p>
<p>To get started it’s easiest to start a new project based on Xcode’s <em>Tabbed Application</em> template while making sure that the <em>Use Storyboards</em> option is checked. Then download <a href="http://developer.apple.com/library/ios/#samplecode/iAdSuite/Introduction/Intro.html">Apple’s iAd Suite sample code</a> and copy the BannerViewController .h and .m files into your project (for extra fun you copy the TextViewController classes as well to show off the timer reacting to ads appearing).</p>
<p>Next open up the main storyboard and remove the relationship segue to the first and second view controller and move them to the right to make room for the container view controllers. Then drag out two view controllers and two container view and place each container view inside their respective view controllers. Open the Identity Inspector and select each new view controller and change the class to BannerViewController. The Banner View Controllers now need to be connected to the tab bar so ctrl drag from the Tab Bar Controller scene to each Banner View Controller and select a <em>relationship</em> segue.</p>
<p>Now we need to make sure that the container view is the root view of each Banner View Controller. Unless someone knows an easier way I’ve found it best to drag the container view above the default view in Interface Builder’s Document Outline. Finally we can connect each Banner View Controller’s container view to their respective first and second view controllers from the original template by ctrl dragging from each container view to each first or second view controller and selecting the <em>embed</em> segue. We are all done with storyboard though you can add a long text view to each first and second view controller so that you can test the banner view controller to make sure it doesn’t occlude it’s child view controller.</p>
<p>Open up BannerViewController.h and remove the old init method. We don’t need this anymore since we are creating the banner view controllers in the storyboard.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">-</span> <span class="p">(</span><span class="n">instancetype</span><span class="p">)</span><span class="nf">initWithContentViewController</span><span class="p">:(</span><span class="n">UIViewController</span> <span class="o">*</span><span class="p">)</span><span class="nv">contentController</span><span class="p">;</span>
</code></pre></div></div>
<p>Move on to BannerViewController.m and remove the implementation of the previous method. We are almost done but we still how to set the <code class="highlighter-rouge">_contentController</code> instance variable and add the banner view controller to the BannerViewManager’s shared instance since we are not overriding the init method anymore. Instead of implementing a custom init method we have to wait for the storyboard to setup the view controller and then let us finish the initialization by overriding <code class="highlighter-rouge">initWithCoder:</code> and adding the banner view controller to the BannerViewManager’s shared instance.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">-</span> <span class="p">(</span><span class="n">id</span><span class="p">)</span><span class="nf">initWithCoder</span><span class="p">:(</span><span class="n">NSCoder</span> <span class="o">*</span><span class="p">)</span><span class="nv">aDecoder</span>
<span class="p">{</span>
<span class="n">self</span> <span class="o">=</span> <span class="p">[</span><span class="n">super</span> <span class="nf">initWithCoder</span><span class="p">:</span><span class="n">aDecoder</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="p">{</span>
<span class="p">[[</span><span class="n">BannerViewManager</span> <span class="nf">sharedInstance</span><span class="p">]</span> <span class="nf">addBannerViewController</span><span class="p">:</span><span class="n">self</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">self</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>But what about the <code class="highlighter-rouge">_contentController</code> you may ask. At this point we haven’t loaded BannerViewController’s view and it’s subviews thus the container view isn’t loaded. Normally if we were creating this view controller programmatically we could create the view like in <code class="highlighter-rouge">loadView</code> but since it is created in the storyboard we can remove this method as well. After BannerViewController’s view is loaded it is still missing the contents of it’s container view so it invokes <code class="highlighter-rouge">prepareForSegue:</code> to retrieve the child view controllers from the storyboard. It is at this point we can set our <code class="highlighter-rouge">_contentController</code> to the segue’s destination view controller.</p>
<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">prepareForSegue</span><span class="p">:(</span><span class="n">UIStoryboardSegue</span> <span class="o">*</span><span class="p">)</span><span class="nv">segue</span> <span class="nf">sender</span><span class="p">:(</span><span class="n">id</span><span class="p">)</span><span class="nv">sender</span>
<span class="p">{</span>
<span class="n">_contentController</span> <span class="o">=</span> <span class="n">segue</span><span class="p">.</span><span class="n">destinationViewController</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>And we’re done! Build and run to see that the banner view controller doesn’t occlude it’s child view controller when the ad pops up and the same ad is show across the view controllers. Now you can easily incorporate iAds into your Tabbed Application that uses Storyboards.</p>While looking at Apple’s iAd Suite sample code I noticed that the TabbedBanner example was the perfect use case for iOS 6’s new Container View Storyboard object. It allows a view controller to be placed inside another view controller which is exactly how we want our banner view controllers setup. No code. Actually it gets better, to get Apple’s example to work with container views we mostly remove code! Check out my example GitHub project or follow below to see how.How to Pick an Apple Friendly TLD2013-04-21T16:35:00+00:002013-04-21T16:35:00+00:00https://stevemoser.org/posts/web-dev/how-to-pick-an-apple-friendly-tld<p>Can’t find the .com or .net <a href="http://en.wikipedia.org/wiki/Top-level_domain">top-level domain</a> (TLD) for your website? Thinking about a country code TLD for your site like .io or possibly a domain hack? Great, there are plenty of short URL’s available for other TLD’s besides the traditional .com’s and .net’s. You can filter by price or how it looks with your particular URL but you should also consider <em>data detectors</em>.</p>
<p>Apple’s data detector <a href="https://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSDataDetector_Class/Reference/Reference.html">NSDataDetector</a> combs user text views such as notes and emails looking for anything from mailing addresses, to email addresses and even tracking numbers for packages. But most importantly for your website it looks for URL’s. Now normally it will pick just about any TLD as long as it is prepended with <code class="highlighter-rouge">www.</code> such as <code class="highlighter-rouge">www.github.io</code>. However it doesn’t pick up all non-prepended TLD’s. For example, if you email someone with the text <code class="highlighter-rouge">github.io</code>, it will not turn that nice shade of blue indicating that it is a tappable link. So which non-prepended TLD’s does it pick up? I asked <a href="http://stackoverflow.com/q/16088329/142358">stackoverflow</a> but no one seemed interested so I ran the names myself with this <a href="http://data.iana.org/TLD/tlds-alpha-by-domain.txt">text file from ICANN</a>.</p>
<h3 id="uppercase">Uppercase</h3>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>example.COM
example.EDU
example.EU
example.GOV
example.LY
example.NET
example.ORG
</code></pre></div></div>
<h3 id="lowercase">Lowercase</h3>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>example.ar
example.at
example.au
example.be
example.br
example.ca
example.ch
example.cn
example.de
example.dk
example.edu
example.es
example.eu
example.fi
example.fr
example.gov
example.gr
example.hk
example.hu
example.il
example.is
example.it
example.jp
example.kr
example.lu
example.ly
example.ma
example.mx
example.net
example.nl
example.no
example.nz
example.org
example.pt
example.ru
example.se
example.sg
example.th
example.tn
example.tr
example.tw
example.ua
example.uk
example.us
</code></pre></div></div>
<p>Interestingly enough the data detector is case sensitive. So it looks like if you can’t find a traditional TLD you should try to go with <code class="highlighter-rouge">.ly</code> (the country code TLD for Libya) since NSDataDetector picks up both uppercase and lowercase URL’s. One more thing to consider is the TLD keyboard shortcut on iOS. A user can hold down the .com button to quickly fill in .net, .edu, .org, .us, or .com of course. Also remember that all this was tested on the US locale and YMMV on a different locale.</p>Can’t find the .com or .net top-level domain (TLD) for your website? Thinking about a country code TLD for your site like .io or possibly a domain hack? Great, there are plenty of short URL’s available for other TLD’s besides the traditional .com’s and .net’s. You can filter by price or how it looks with your particular URL but you should also consider data detectors.