<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ios8 on A&#43; programming moments</title>
    <link>https://aplus.rs/tags/ios8/</link>
    <description>Recent content in Ios8 on A&#43; programming moments</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 29 Dec 2014 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://aplus.rs/tags/ios8/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>How to properly share / export GPX files on iOS</title>
      <link>https://aplus.rs/2014/how-to-properly-share-slash-export-gpx-files-on-ios/</link>
      <pubDate>Mon, 29 Dec 2014 00:00:00 +0000</pubDate>
      
      <guid>https://aplus.rs/2014/how-to-properly-share-slash-export-gpx-files-on-ios/</guid>
      <description>&lt;p&gt;In upcoming version 4.1 of my &lt;a href=&#34;http://radianttap.com/run-5k/&#34;&gt;Run 5k&lt;/a&gt; app, I’m adding support for exporting data out of the app. I strongly believe that data liberation should exist in all applications and services despite the fact it can require significant amount of time to do properly. In 4.1, you will be able to export complete GPX file for each run you did with Run 5k.&lt;/p&gt;
&lt;h3 id=&#34;what-is-gpx&#34;&gt;What is GPX&lt;/h3&gt;
&lt;p&gt;GPX is de-facto standard for exchanging GPS tracks, waypoints, and similar GPS related data between applications and services. It stands for &lt;a href=&#34;https://en.wikipedia.org/wiki/GPS_Exchange_Format&#34;&gt;GPS Exchange Format&lt;/a&gt; and was created by &lt;a href=&#34;http://www.topografix.com&#34;&gt;Topografix&lt;/a&gt;. Current version of the specification is &lt;a href=&#34;http://www.topografix.com/GPX/1/1/&#34;&gt;1.1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Over time, companies like Garmin have added Extensions to the original specification – thus you can include things like heart rate to it. Which all later lead them to create an expanded format called &lt;a href=&#34;https://en.wikipedia.org/wiki/Training_Center_XML&#34;&gt;TCX&lt;/a&gt; which allows you to transfer many fitness-related bits of information.&lt;/p&gt;
&lt;h3 id=&#34;how-to-do-it-on-ios&#34;&gt;How to do it on iOS&lt;/h3&gt;
&lt;p&gt;The hardest part of the work is already done by Watanabe Toshinori, who created and open-soured &lt;a href=&#34;https://github.com/FLCLjp/iOS-GPX-Framework&#34;&gt;GPX framework&lt;/a&gt; for creating and parsing GPX formats, plus also a separate &lt;a href=&#34;https://github.com/FLCLjp/GPX-Logger&#34;&gt;Logger&lt;/a&gt; and &lt;a href=&#34;https://github.com/FLCLjp/GPX-Viewer&#34;&gt;Viewer&lt;/a&gt;. If you look at the &lt;a href=&#34;https://github.com/FLCLjp?tab=repositories&#34;&gt;GitHub profile&lt;/a&gt;, you’ll find the same for Google’s KML as well. &lt;em&gt;Truly an amazing contribution to the iOS community and people like Watanabe inspire me to share my knowledge and code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sadly, the last Watanabe’s update was 3 years ago and &lt;a href=&#34;https://github.com/FLCLjp/iOS-GPX-Framework/network&#34;&gt;many other developers&lt;/a&gt; have taken the mantle and continued to improve the library. Simply pick the one you want, even the original still works just fine on iOS 8.&lt;/p&gt;
&lt;p&gt;Once you include the framework in your own app, it’s pretty straightforward to instantiate the whole hierarchy and convert your &lt;code&gt;CLLocation&lt;/code&gt; stuff into &lt;code&gt;GPX&lt;/code&gt; objects.&lt;/p&gt;
&lt;h3 id=&#34;how-to-add-gpx-support-to-ios-system-wide&#34;&gt;How to add GPX support to iOS, system-wide&lt;/h3&gt;
&lt;p&gt;With that out of the way, the &lt;em&gt;troubling&lt;/em&gt; part is how to actually share the file on iOS. &lt;br&gt;
Why troubling?&lt;br&gt;
All file exchanging in iOS is dependent on the OS knowing about the file format in the first place. This is done through &lt;a href=&#34;https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_intro/understand_utis_intro.html&#34;&gt;Uniform Type Identifier&lt;/a&gt; system, or UTI. Read Apple docs or this old &lt;a href=&#34;http://www.cocoanetics.com/2012/09/fun-with-uti/&#34;&gt;Cocoanetics blog post&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;p&gt;For now, it’s enough to know that in order to attach a particular file to — say Mail message, iOS must have its UTI record.
Ideally, you would already have another
app that acts as GPX viewer and or editor. Thus the UTI declaration for GPX would already be available to iOS runtime.&lt;/p&gt;
&lt;p&gt;By default, iOS installation does not have GPX record and thus you can’t depend on it being there. Hence to successfully  export GPX file, you need to add Imported UTI Declaration to your app’s Info.plist file; “imported” means that you are declaring someone else’s file format, in this case Topografix’s GPX. (If your app defines your own custom file format, you would use Exported UTI Declaration.)&lt;/p&gt;
&lt;p&gt;This is what you need to add to the end of the Info.plist file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;key&amp;gt;UTImportedTypeDeclarations&amp;lt;/key&amp;gt;
&amp;lt;array&amp;gt;
	&amp;lt;dict&amp;gt;
		&amp;lt;key&amp;gt;UTTypeIdentifier&amp;lt;/key&amp;gt;
		&amp;lt;string&amp;gt;com.topografix.gpx&amp;lt;/string&amp;gt;
		&amp;lt;key&amp;gt;UTTypeReferenceURL&amp;lt;/key&amp;gt;
		&amp;lt;string&amp;gt;http://www.topografix.com/GPX/1/1&amp;lt;/string&amp;gt;
		&amp;lt;key&amp;gt;UTTypeDescription&amp;lt;/key&amp;gt;
		&amp;lt;string&amp;gt;GPS Exchange Format (GPX)&amp;lt;/string&amp;gt;
		&amp;lt;key&amp;gt;UTTypeConformsTo&amp;lt;/key&amp;gt;
		&amp;lt;array&amp;gt;
			&amp;lt;string&amp;gt;public.xml&amp;lt;/string&amp;gt;
		&amp;lt;/array&amp;gt;
		&amp;lt;key&amp;gt;UTTypeTagSpecification&amp;lt;/key&amp;gt;
		&amp;lt;dict&amp;gt;
			&amp;lt;key&amp;gt;public.filename-extension&amp;lt;/key&amp;gt;
			&amp;lt;array&amp;gt;
				&amp;lt;string&amp;gt;gpx&amp;lt;/string&amp;gt;
			&amp;lt;/array&amp;gt;
			&amp;lt;key&amp;gt;public.mime-type&amp;lt;/key&amp;gt;
			&amp;lt;string&amp;gt;application/gpx+xml&amp;lt;/string&amp;gt;
		&amp;lt;/dict&amp;gt;
	&amp;lt;/dict&amp;gt;	
&amp;lt;/array&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This above is the minimum required. I got to this through trial and error, adding one key at the time to see what’s enough. Note that some apps are stricter than others and I found that out of all the system apps Mail is the most strict. For example, you could share – using standard share system in iOS 8 – .gpx file without the &lt;code&gt;public.mime-type&lt;/code&gt; key present through iMessage but Mail would simply ignore it. Add that one and sharing to Mail will work (your file will appear as attachment).&lt;/p&gt;
&lt;h3 id=&#34;last-piece-of-the-puzzle-how-to-share-the-file-in-ios-8&#34;&gt;Last piece of the puzzle: how to share the file in iOS 8&lt;/h3&gt;
&lt;p&gt;I like the sharing mechanism that Apple is building with iOS 8 through &lt;code&gt;UIActivity*&lt;/code&gt; APIs and I’m adding support for it in all my apps, as appropriate for each one.&lt;/p&gt;
&lt;p&gt;GPX file is perfect candidate for lazy-creation share mechanism, since it can take a while to be created. If you do it before the share sheet is even shown, you could potentially stall your UI for seconds.&lt;/p&gt;
&lt;p&gt;Thus you need to subclass &lt;code&gt;UIActivityItemProvider&lt;/code&gt; and implement just these two methods as minimum:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-objectivec&#34; data-lang=&#34;objectivec&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;NSString&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filePath&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;activity&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;saveToFileGPXString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;activity&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;getGPXString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filePath&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;NSError&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;NSData&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fileData&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NSData&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;dataWithContentsOfFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filePath&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NSDataReadingMapped&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;n&#34;&gt;NSLog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;@&amp;#34;Error reading GPX file:&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;%@&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fileData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NSString&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;activityViewController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIActivityViewController&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;activityViewController&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;dataTypeIdentifierForActivityType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NSString&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;activityType&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@&amp;#34;com.topografix.gpx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First method generates GPX file and saves it to some folder and then streams it using &lt;code&gt;dataWithContentsOfFile:options:error&lt;/code&gt;. (You can also send &lt;code&gt;NSData&lt;/code&gt; from the memory, bypassing the file system.)&lt;/p&gt;
&lt;p&gt;Second method is key: you must tell the sharing mechanism what kind of file is it, using UTI you declared in your &lt;code&gt;Info.plist&lt;/code&gt; file. If you don’t, Mail will again ignore the file (while Messages will still attach it).&lt;/p&gt;
&lt;p&gt;The only part I could not figure out is how to name the file - both Mail and Messages ignore the file name and display &lt;code&gt;Attachment-1.gpx&lt;/code&gt;. (blah)&lt;/p&gt;
&lt;p&gt;So, there you have it. Nice thing to do is to also include &lt;code&gt;(NSString *)activityViewController:(UIActivityViewController *)activityViewController subjectForActivityType:(NSString *)activityType&lt;/code&gt; and return nice, informative subject, which Mail app will read out and save your customers some typing.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Real-time inter-app communication</title>
      <link>https://aplus.rs/2014/real-time-inter-app-communication/</link>
      <pubDate>Mon, 20 Oct 2014 00:00:00 +0000</pubDate>
      
      <guid>https://aplus.rs/2014/real-time-inter-app-communication/</guid>
      <description>&lt;p&gt;Or more like “real-time”, (near)real-time or whatever modifier you prefer.&lt;/p&gt;
&lt;p&gt;App Extensions are the new shiny in iOS 8 and one that interest me the most, especially in the fitness area. Here’s why: I use my iPhone as the core device of my entire business hence I have lots of sensitive personal and business data on it. Thus it’s natural that I have all possible security features turned on. Passcode is set, TouchID is on, instant lock with no grace period etc.&lt;/p&gt;
&lt;p&gt;This presents an issue when I go out to run with my iPhone. I don’t usually run with an armband (only in races) thus the iPhone is usually in my pocket. From time to time tough, I would like to check the parameters - heart rate, distance, pace etc. In reality, this means that I should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dug it out from the pocket&lt;/li&gt;
&lt;li&gt;unlock – Touch ID is not always reliable with sweaty fingers (at least on 5s), so it means type out the passcode&lt;/li&gt;
&lt;li&gt;back into the pocket&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Step no. 2 is what bugs me and where extensions come into play. If I have to slide to the left for the passcode screen, then I might as well slide from the top and get the info I need from the Today widget.&lt;/p&gt;
&lt;p&gt;That’s the thought process that ended with: iOS 8 version of &lt;a href=&#34;http://radianttap.com/run-5k/&#34;&gt;Run 5k&lt;/a&gt; will have Today widget that’s (more or less) a replica of its running view.&lt;/p&gt;
&lt;p&gt;The only problem to solve is - how to communicate app status between the main app and the widget, in real time?&lt;/p&gt;
&lt;h3 id=&#34;idea-1&#34;&gt;Idea 1&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;NSExtensionContext&lt;/code&gt;&lt;/em&gt; seems like a proper place to give us means to shuttle data and state back and forth, but it’s a non-starter. It’s simple and very limited class and there’s nothing in it to allow real-time communication.&lt;/p&gt;
&lt;p&gt;Maybe in iOS 9.&lt;/p&gt;
&lt;h3 id=&#34;idea-2&#34;&gt;Idea 2&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;File-based, on disk.&lt;/em&gt; Main app would write data into it, widget would read from it. However, widget might also need to write some data, for example to alter running state: I may want to temporarily pause the run.&lt;/p&gt;
&lt;p&gt;Thus you need to carefully coordinate reads/writes and to resolve the potential lock-ups. Given this and also the fact that it’s a file I/O, the real-time &lt;em&gt;may&lt;/em&gt; become far less real then I would prefer and it could actually lead to widget lagging behind actual app state.&lt;/p&gt;
&lt;p&gt;I may be wrong and it could turn out to be performant enough. Would &lt;a href=&#34;http://x.com/radiantav&#34;&gt;love to hear&lt;/a&gt; about it, if you have experiences.&lt;/p&gt;
&lt;h3 id=&#34;idea-3&#34;&gt;Idea 3&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;App-specific &lt;code&gt;UIPasteboard&lt;/code&gt;.&lt;/em&gt; It’s all in memory, so no slow I/O to speak of. Idea is that I would write my items into the pasteboard from the app, widget will read them. There is no limit what you can place in the pasteboard, but just be careful it’s not a lot of data - memory warnings are not far off in the 1GB RAM devices we still work with.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is what I chose to go with.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My first approach was whenever the app writes into the pasteboard, &lt;code&gt;UIPasteboardChangedNotification&lt;/code&gt; is fired and I’m using that to trigger widget layout/display. However, even with this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[[NSNotificationCenter defaultCenter] addObserver:self
										 selector:@selector(handleNotification:)
											 name:UIPasteboardChangedNotification
										   object:nil];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Widget’s handler is never called. And that’s really annoying, as I had to resort to polling the UIPasteboard repeatedly. Still testing it out, but I don’t like it, it seems wasteful.&lt;/p&gt;
&lt;p&gt;Maybe I’m doing something wrong, still working on it.&lt;/p&gt;
&lt;h3 id=&#34;idea-4&#34;&gt;Idea 4&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Local socket communication..?&lt;/em&gt; I have almost non-existent experience with these, so can’t properly investigate. No idea what’s possible to do, will iOS even allow direct communication between two apps of which one is in background. There are a lot of *ix words and terms here that I’m out to become familiar with at some point.&lt;/p&gt;
&lt;h3 id=&#34;idea-5&#34;&gt;Idea 5&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Local web server and client.&lt;/em&gt; This is basically a specific implementation of the previous idea, but something that’s known to work in practice, people have these done in their apps.&lt;/p&gt;
&lt;p&gt;If the pasteboard becomes non-usable for my use case, I’ll probably try this next.&lt;/p&gt;
&lt;h3 id=&#34;call-for-action&#34;&gt;Call for action&lt;/h3&gt;
&lt;p&gt;I believe that as iOS matures, &lt;em&gt;direct&lt;/em&gt; inter-app communication will become a real need. Apple is making baby steps in that direction, with &lt;code&gt;NSExtensionContext&lt;/code&gt; and App Groups.&lt;/p&gt;
&lt;p&gt;The need is here and now it’s the time to formulate the requirements and hit &lt;a href=&#34;bugreport.apple.com&#34;&gt;bugreport.apple.com&lt;/a&gt; in order to have anything added to the SDK in reasonable time-frame. Just remember the open-source-born &lt;a href=&#34;http://audiob.us&#34;&gt;Audiobus&lt;/a&gt; which even Apple used &lt;a href=&#34;http://www.macrumors.com/2013/03/20/garageband-for-ios-updated-with-audiobus-support-and-other-enhancements/&#34;&gt;in their own apps&lt;/a&gt; - it’s possible :).&lt;/p&gt;
&lt;p&gt;For my use case, a simple key-value storage (&lt;code&gt;NSMutableDictionary&lt;/code&gt;) in &lt;code&gt;NSExtensionContext&lt;/code&gt; would suffice. Thus my first Radar will be to add at least &lt;code&gt;userInfo&lt;/code&gt; property to it, the way &lt;code&gt;NSNotification&lt;/code&gt; has one.&lt;/p&gt;
&lt;h3 id=&#34;update-winning-idea-6&#34;&gt;Update, (winning) Idea 6&lt;/h3&gt;
&lt;p&gt;I can&amp;rsquo;t believe I completely missed what turned out to be the winning idea: use shared &lt;code&gt;NSUserDefaults&lt;/code&gt; through App Groups. It&amp;rsquo;s the recommended way to communicate settings between the extension and app and it&amp;rsquo;s good enough to shuttle back and forth small bits of data.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UIPasteboard&lt;/code&gt;-based solution actually did work, until you lock the screen; locking puts impenetrable barrier and your extension becomes empty. NSUserDefaults works great even when locked, with passcode and all.&lt;/p&gt;
&lt;p&gt;Any comments and discussion, please contact me as &lt;a href=&#34;http://x.com/radiantav&#34;&gt;@radiantav&lt;/a&gt; on Twitter.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to remove UINavigationBar&#39;s bottom border / shadow in iOS 7</title>
      <link>https://aplus.rs/2014/how-to-remove-uinavigationbars-bottom-border-slash-shadow-in-ios-7/</link>
      <pubDate>Fri, 29 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>https://aplus.rs/2014/how-to-remove-uinavigationbars-bottom-border-slash-shadow-in-ios-7/</guid>
      <description>&lt;p&gt;One of the most annoying visual things Apple introduced in iOS 7 is inability to  remove the navigation bar shadow image. iOS 7 UI is perfect to create seamless transition between the content and the top of the screen.&lt;/p&gt;
&lt;p&gt;The only issue is that darn line at the bottom. There is no property on &lt;code&gt;UINavigationBar&lt;/code&gt; to hide it. There is &lt;code&gt;shadowImage&lt;/code&gt; which allows you to change it, but can&amp;rsquo;t remove it – &lt;code&gt;shadowImage = nil&lt;/code&gt; is the default which shows their default image. Even changing the &lt;code&gt;shadowImage&lt;/code&gt; to 100% transparent image is not enough:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For a custom shadow image to be shown, a custom background image must also be set with the &lt;code&gt;setBackgroundImage:forBarMetrics:&lt;/code&gt; method. If the default background image is used, then the default shadow image will be used regardless of the value of this property.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Brilliant. 😕 You can remove the shadow only if you also kill the blur, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-objectivec&#34; data-lang=&#34;objectivec&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;navigationController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;navigationBar&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;setBackgroundImage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIImage&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nl&#34;&gt;forBarMetrics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIBarMetricsDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;navigationController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;navigationBar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shadowImage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIImage&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Can&amp;rsquo;t help to think this was not properly thought through, but given the hectic schedule Apple engineers had for iOS 7, something had to give.
Anw, with no other avenue left, it&amp;rsquo;s subview walkthrough time.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;UINavigationBar: 0xb486860; baseClass = UINavigationBar; frame = (-160 0; 320 1); opaque = NO; autoresize = W; gestureRecognizers = &amp;lt;NSArray: 0xb4887e0&amp;gt;; layer = &amp;lt;CALayer: 0xb4869c0&amp;gt;&amp;gt;
| &amp;lt;_UINavigationBarBackground: 0xb487090; frame = (0 0; 320 1); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = &amp;lt;CALayer: 0xb4871c0&amp;gt;&amp;gt;
|    | &amp;lt;_UIBackdropView: 0xb48fb20; frame = (0 0; 320 1); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = &amp;lt;_UIBackdropViewLayer: 0xc6aec50&amp;gt;&amp;gt;
|    |    | &amp;lt;_UIBackdropEffectView: 0xc6af6e0; frame = (0 0; 320 1); clipsToBounds = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = &amp;lt;CABackdropLayer: 0xc6af9a0&amp;gt;&amp;gt;
|    |    | &amp;lt;UIView: 0xc6b0150; frame = (0 0; 320 1); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = &amp;lt;CALayer: 0xc6b02b0&amp;gt;&amp;gt;
|    | &amp;lt;UIImageView: 0xb4873d0; frame = (0 1; 320 0.5); userInteractionEnabled = NO; layer = &amp;lt;CALayer: 0xb4874a0&amp;gt;&amp;gt;
| &amp;lt;UINavigationItemView: 0xb488da0; frame = (160 -16.5; 0 0); opaque = NO; userInteractionEnabled = NO; layer = &amp;lt;CALayer: 0xb48c630&amp;gt;&amp;gt;
|    | &amp;lt;UILabel: 0xb48c9e0; frame = (0 33; 0 0); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = &amp;lt;CALayer: 0xb48cae0&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That &lt;code&gt;0.5pt&lt;/code&gt; tall &lt;code&gt;UIImageView&lt;/code&gt; is the target.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-objectivec&#34; data-lang=&#34;objectivec&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subviews&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;enumerateObjectsUsingBlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIView&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NSUInteger&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;idx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;BOOL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NSStringFromClass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;rangeOfString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;@&amp;#34;BarBackground&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NSNotFound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subviews&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;enumerateObjectsUsingBlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;^&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIView&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NSUInteger&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;idx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;BOOL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;isKindOfClass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UIImageView&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CGRectGetHeight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bounds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;					&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;removeFromSuperview&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;					&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;p&#34;&gt;}];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I coded this as defensively as possible, to not crush in case something changes in the future. Get the &lt;a href=&#34;https://github.com/radianttap/RTCleanNavigationBar&#34;&gt;RTCleanNavigationBar subclass on GitHub&lt;/a&gt; and use it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-objectivec&#34; data-lang=&#34;objectivec&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UIViewController&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UINavigationController&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UINavigationController&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nl&#34;&gt;initWithNavigationBarClass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RTCleanNavigationBar&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nl&#34;&gt;toolbarClass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nc&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;setViewControllers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;@[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vc&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works perfectly, does not trigger any issues with app review.  Hopefully it stays like that for the foreseeable time and Apple gives us a proper way to do this.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>