<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0EDQ3s_fSp7ImA9WxFVFkg.&quot;"><id>tag:blogger.com,1999:blog-7094379308761251815</id><updated>2010-06-15T18:27:52.545-07:00</updated><title>Chris Yunker's weblog</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.chrisyunker.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.chrisyunker.com/" /><author><name>Chris Yunker</name><uri>http://www.blogger.com/profile/11418739167012430451</uri><email>chris@chrisyunker.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ChrisYunkersWeblog" /><feedburner:info uri="chrisyunkersweblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D0IHRXkzfSp7ImA9WxJQFkw.&quot;"><id>tag:blogger.com,1999:blog-7094379308761251815.post-8324643031502296188</id><published>2009-05-29T09:44:00.000-07:00</published><updated>2009-05-29T09:45:34.785-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-29T09:45:34.785-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mac drm hdcp itunes" /><title>HDCP In Action</title><content type="html">I’m a big fan of Breaking Bad and missed this week’s episode. I don’t have a DVR, but still have a working VCR and use it on occasion to record a must see show. Since Breaking Bad is on AMC, I assumed I could watch the missed episode on Hulu since Mad Men, another AMC show, was carried on Hulu. But to my surprise, they don’t have it.&lt;br /&gt;
&lt;br /&gt;
So I had to turn to iTunes to get the missed episode. For $2.99 you can download an HD version of the show. A few hours later (after waiting for 1.5 GB to download) I was ready to watch the episode. I hit play and this is what I saw.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_l98vmZmxCEo/SiAQWoUEtwI/AAAAAAAAAh0/-abM6Vo9p2M/s1600-h/Picture+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_l98vmZmxCEo/SiAQWoUEtwI/AAAAAAAAAh0/-abM6Vo9p2M/s320/Picture+1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
My Mac home setup is my MacBook attached to an external VGA monitor. This gives me a dual screen setup, with the VGA as the primary screen since it’s the largest. When I got this message the iTunes player was located on the VGA screen.&lt;br /&gt;
&lt;br /&gt;
HDCP (&lt;a href="http://en.wikipedia.org/wiki/High-bandwidth_Digital_Content_Protection"&gt;http://en.wikipedia.org/wiki/High-bandwidth_Digital_Content_Protection&lt;/a&gt;) is basically a DRM for HD video. It only allows the video to be displayed on devices that support HDCP to prevent unauthorized copies. Interestingly enough, when I dragged the iTunes player back to the MacBook screen, it played the video OK.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7094379308761251815-8324643031502296188?l=blog.chrisyunker.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/723GH9u2IFvadbyt5WVEGaHVEq0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/723GH9u2IFvadbyt5WVEGaHVEq0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/723GH9u2IFvadbyt5WVEGaHVEq0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/723GH9u2IFvadbyt5WVEGaHVEq0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisYunkersWeblog/~4/Thy8vczvsQI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.chrisyunker.com/feeds/8324643031502296188/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=7094379308761251815&amp;postID=8324643031502296188" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/8324643031502296188?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/8324643031502296188?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisYunkersWeblog/~3/Thy8vczvsQI/hdcp-in-action.html" title="HDCP In Action" /><author><name>Chris Yunker</name><uri>http://www.blogger.com/profile/11418739167012430451</uri><email>chris@chrisyunker.com</email><gd:extendedProperty name="OpenSocialUserId" value="02663009264953845519" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_l98vmZmxCEo/SiAQWoUEtwI/AAAAAAAAAh0/-abM6Vo9p2M/s72-c/Picture+1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.chrisyunker.com/2009/05/hdcp-in-action.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMBRnc9eyp7ImA9WxJSEk0.&quot;"><id>tag:blogger.com,1999:blog-7094379308761251815.post-1637790459259498487</id><published>2009-05-01T11:35:00.000-07:00</published><updated>2009-05-01T11:44:17.963-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-01T11:44:17.963-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="firefox" /><category scheme="http://www.blogger.com/atom/ns#" term="useragent" /><category scheme="http://www.blogger.com/atom/ns#" term="iphone" /><title>Nice Firefox Add-On for Mobile Website Testing</title><content type="html">I'm working on a website which will render differently depending on whether or not it's being accessed from an iPhone web broswer. I came across this Firefox Add-On which is perfect for some of my testing.&lt;br /&gt;&lt;br /&gt;It's called &lt;b&gt;User Agent Switcher&lt;/b&gt; and it's written by Chris Pederick.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://chrispederick.com/work/user-agent-switcher/"&gt;http://chrispederick.com/work/user-agent-switcher/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This add-on allows you to change the User Agent field in your browser HTTP requests. In the case of the Firefox browser I'm currently using on my macbook, here is the User Agent field:&lt;br /&gt;&lt;pre class="code"&gt;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.10) Gecko/2009042315 Firefox/3.0.10 GTB5&lt;/pre&gt;For my testing, I want to change this field to what it would be if I was browsing from my iPhone. This is the User Agent field my iPhone is currently using:&lt;br /&gt;&lt;pre class="code"&gt;Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/3.1.1 Mobile/7A300g Safari/525.20&lt;/pre&gt;The User Agent Switcher allows you to create new User Agent profiles and adds a pull-down button on Firefox so you can easily switch back and forth between browser types.&lt;br /&gt;&lt;br /&gt;Once you've added your profile and enabled it, an easy test is to simply go to google.com since it should render a simple page for mobile devices.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7094379308761251815-1637790459259498487?l=blog.chrisyunker.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MwC8y6xzq_Y4baMABcZbVcJc5AU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MwC8y6xzq_Y4baMABcZbVcJc5AU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MwC8y6xzq_Y4baMABcZbVcJc5AU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MwC8y6xzq_Y4baMABcZbVcJc5AU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisYunkersWeblog/~4/chEoPzK_d5E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.chrisyunker.com/feeds/1637790459259498487/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=7094379308761251815&amp;postID=1637790459259498487" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/1637790459259498487?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/1637790459259498487?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisYunkersWeblog/~3/chEoPzK_d5E/nice-firefox-add-on-for-mobile-website.html" title="Nice Firefox Add-On for Mobile Website Testing" /><author><name>Chris Yunker</name><uri>http://www.blogger.com/profile/11418739167012430451</uri><email>chris@chrisyunker.com</email><gd:extendedProperty name="OpenSocialUserId" value="02663009264953845519" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.chrisyunker.com/2009/05/nice-firefox-add-on-for-mobile-website.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUEQHs-eip7ImA9WxJTFU4.&quot;"><id>tag:blogger.com,1999:blog-7094379308761251815.post-8369150391926501757</id><published>2009-04-23T17:43:00.000-07:00</published><updated>2009-04-23T17:50:01.552-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-23T17:50:01.552-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="simulator" /><category scheme="http://www.blogger.com/atom/ns#" term="lowmemory" /><category scheme="http://www.blogger.com/atom/ns#" term="memory" /><category scheme="http://www.blogger.com/atom/ns#" term="iphone" /><title>Writing iPhone applications to handle Low Memory Situations</title><content type="html">Part of writing a robust iPhone application is making sure it can recover from low memory situations. These can be not uncommon if you use memory hungry components such as the UIImagePickerController or UIWebView. When a low memory situation happens, the OS will try to free up memory from your application. If enough memory can’t be freed up, the OS will terminate your application.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Low Memory Events&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
In low memory situations, the OS will invoke the didReceiveMemoryWarning method on all of your view controller objects. You should override this method in your view controllers if there is an opportunity to free up any memory. I always override this method with at least a warning log message for testing purposes. If the view controller is not currently being displayed, the OS might release its view object.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Note:&lt;/b&gt; The documentation seems to suggest it will always do this, but in testing I’ve noticed this is not the case. It seems for less critical situations it will only call the didReceiveMemoryWarning method, and for more critical situations it will call didReceiveMemoryWarning and release the view object if not currently displayed.&lt;br /&gt;
&lt;br /&gt;
Consequently, your view controllers must be designed such that they can recover in the case that its view object is released. This means that it must be written such that the view object can be unexpectedly released and then initialized again without leaking memory or putting the view in an unexpected or corrupted state.&lt;br /&gt;
&lt;br /&gt;
When the view controller releases its view object, it calls the method setView:(UIView *)view with view set to nil. You can override this method to add code that will help to cleanly release the view and all the objects it contains.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Example&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
In the following example, the view contains an imageview object which is a member variable of the view controller. In order to release the imageview when the view gets released the setView method needs to be overridden to explicitly release the imageview (only for the condition of view == nil).&lt;br /&gt;
&lt;br /&gt;
(Note that this example is for a non-NIB initialized view controller)&lt;br /&gt;
&lt;pre class="code"&gt;@interface MyViewController : UIViewController
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; UIImageView *imageView;
}
@end

@implementation MyViewController

- (void)setView:(UIView *)aView
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (aView == nil)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [imageView release];
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; [super setView:aView];
}

- (void)loadView
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; ...

&amp;nbsp;&amp;nbsp;&amp;nbsp; imageView = [[UIImageView alloc] initWithImage:myImage];

&amp;nbsp;&amp;nbsp;&amp;nbsp; ...
}

@end
&lt;/pre&gt;Note that if the imageview was not a view controller member variable and was autoreleased into the view, then it would automatically be released when the view was released and this wouldn’t be necessary.&lt;br /&gt;
&lt;br /&gt;
You can obviously choose not to release the objects in a view during low memory situations. If they are small objects, it’s probably safe to do so. However, the code for creating the view needs to check for the existence of previously created objects so they are not overwritten causing memory leaks and possibly putting the objects in corrupt or unexpected states:&lt;br /&gt;
&lt;pre class="code"&gt;- (void)loadView
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!imageView)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; imageView = [[UIImageView alloc] initWithImage:myImage];
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Testing&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Simulating low memory events should be an integral part of your testing. You can do this with the iPhone simulator by selecting the menu option: iPhone Simulator -&amp;gt; Hardware -&amp;gt; Simulate Memory Warning. If you did like me and put log statements inside the didReceiveMemoryWarning methods, you will see these messages in the console window. Also be sure to run the simulator with the Instruments tool in Leaks mode to check for memory leaks.&lt;br /&gt;
&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7094379308761251815-8369150391926501757?l=blog.chrisyunker.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kcJdryp0gvCJSjJbTCaSrvFmmSQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kcJdryp0gvCJSjJbTCaSrvFmmSQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kcJdryp0gvCJSjJbTCaSrvFmmSQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kcJdryp0gvCJSjJbTCaSrvFmmSQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisYunkersWeblog/~4/hBEnPm0LqPI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.chrisyunker.com/feeds/8369150391926501757/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=7094379308761251815&amp;postID=8369150391926501757" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/8369150391926501757?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/8369150391926501757?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisYunkersWeblog/~3/hBEnPm0LqPI/writing-iphone-applications-to-handle.html" title="Writing iPhone applications to handle Low Memory Situations" /><author><name>Chris Yunker</name><uri>http://www.blogger.com/profile/11418739167012430451</uri><email>chris@chrisyunker.com</email><gd:extendedProperty name="OpenSocialUserId" value="02663009264953845519" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.chrisyunker.com/2009/04/writing-iphone-applications-to-handle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8FQncycSp7ImA9WxVUE08.&quot;"><id>tag:blogger.com,1999:blog-7094379308761251815.post-5919394449113216840</id><published>2009-03-17T14:37:00.000-07:00</published><updated>2009-03-17T14:53:33.999-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-17T14:53:33.999-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="map" /><category scheme="http://www.blogger.com/atom/ns#" term="yahoo maps" /><category scheme="http://www.blogger.com/atom/ns#" term="cloudmade" /><category scheme="http://www.blogger.com/atom/ns#" term="openstreetmap" /><category scheme="http://www.blogger.com/atom/ns#" term="microsoft virtual earth" /><category scheme="http://www.blogger.com/atom/ns#" term="iphone" /><category scheme="http://www.blogger.com/atom/ns#" term="google maps" /><title>Mapping Services for iPhone Applications</title><content type="html">For my next iPhone project, I'm considering an application that uses geolocation to render a map of the user's current location. I therefore need to find a mapping service that I can use free of charge since I won’t be charging for the application.&lt;br /&gt;&lt;br /&gt;Listed below are some of the services I've considered. I don't plan to do anything more than to render the user's current location and allow him or her to adjust it slightly if it's not accurate. No need for routing or other extra features. So most mapping services should work, the only issue is the terms and conditions that will allow me to use it free of charge.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1) Google Maps&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/apis/maps/"&gt;http://code.google.com/apis/maps/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is my first choice based on my experience using it as the Maps application on the iPhone. I have also played around with Google Maps on my web site and have found the API very easy to use.&lt;br /&gt;&lt;br /&gt;The terms of service might be a problem.&lt;br /&gt;&lt;br /&gt;ToS: &lt;a href="http://code.google.com/apis/maps/signup.html"&gt;http://code.google.com/apis/maps/signup.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;9.1 Free, Public Accessibility to Your Maps API Implementation. Your Maps&lt;br /&gt;API Implementation must be generally accessible to users without charge. You&lt;br /&gt;may require users to log in to your Maps API Implementation if you do not&lt;br /&gt;require users to pay a fee. Unless you have entered into a separate written&lt;br /&gt;agreement with Google or obtained Google's written permission, your Maps&lt;br /&gt;API Implementation must not:&lt;br /&gt;&lt;br /&gt;(a) require a fee-based subscription or other fee-based restricted access; or&lt;br /&gt;(b) operate only behind a firewall or only on an internal network (except&lt;br /&gt;during the development and testing phase).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Since I'm not charging, this should be OK.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;10. License Restrictions. Except as expressly permitted under the Terms, or&lt;br /&gt;unless you have received prior written authorization from Google (or, as&lt;br /&gt;applicable, from the provider of particular Content), Google's licenses above&lt;br /&gt;are subject to your adherence to all of the restrictions below. Except as&lt;br /&gt;explicitly permitted in Section 7, you must not (nor may you permit anyone&lt;br /&gt;else to):&lt;br /&gt;&lt;br /&gt;10.8 use the Static Maps API other than in an implementation in a web&lt;br /&gt;browser;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However, this does not look OK. Since my plan is to use the map in the UIWebView object, I think this might violate the ToS. After doing some searching, I came across this thread:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://groups.google.com/group/Google-Maps-API/browse_thread/thread/2f42bc5e4c3368d8/fbdc4ecdc3b96096?pli=1"&gt;http://groups.google.com/group/Google-Maps-API/browse_thread/thread/2f42bc5e4c3368d8/fbdc4ecdc3b96096?pli=1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A Google employee weighed in and said basically that if the application were accessing a web site that could be viewed separate from the application, than the UIWebView use case should be OK.&lt;br /&gt;&lt;br /&gt;I have seen applications that use Google Maps which can’t be used in a separately in a browser. One example is iBus, a free Portland mass transit application:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://zhenwang.yao.googlepages.com/ibus-portland"&gt;http://zhenwang.yao.googlepages.com/ibus-portland&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So it appears the way I’d use Google Maps falls into the gray area of the ToS.&lt;br /&gt;&lt;br /&gt;I should also point out that there is a nice, BSD licensed library that can help to integrate the Google Maps API into an iPhone project. This helps to make a simple API even easier to use.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/iphone-google-maps-component/"&gt;http://code.google.com/p/iphone-google-maps-component/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2) Yahoo Maps&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.yahoo.com/maps/"&gt;http://developer.yahoo.com/maps/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I’ve used Yahoo Maps with Flickr geotagging and the maps look just as good as Google’s. I have not, however, seen any iPhone applications that use this service.&lt;br /&gt;&lt;br /&gt;ToS: &lt;a href="http://info.yahoo.com/legal/us/yahoo/maps/mapsapi/mapsapi-2141.html"&gt;http://info.yahoo.com/legal/us/yahoo/maps/mapsapi/mapsapi-2141.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One big issue with the ToS is the attribution part:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.yahoo.com/attribution/"&gt;http://developer.yahoo.com/attribution/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yahoo Maps require displaying an attribution badge or label that is not overlaid on the map. It’s placed below the map. This will take away from valuable screen real estate, and for me is enough of a reason to not use Yahoo Maps. Perhaps this is why I haven’t seen it used in any iPhone applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3) Microsoft Virtual Earth&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.microsoft.com/virtualearth/"&gt;http://www.microsoft.com/virtualearth/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I’ve used Microsoft’s Virtual Earth from a browser and have been really impressed. I’ve also seen it used with the Loopt iPhone application.&lt;br /&gt;&lt;br /&gt;ToS: &lt;a href="http://www.microsoft.com/virtualearth/product/terms.html"&gt;http://www.microsoft.com/virtualearth/product/terms.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The ToS looks OK for Non-Commercial use. That is, of course, if deploying a free iPhone application is considered Non-Commerical use.&lt;br /&gt;&lt;br /&gt;There’s a good write-up about using Virtual Earth with the iPhone here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.geo2web.com/2008/11/13/developing-virtual-earth-iphone-applications-with-objective-c/"&gt;http://www.geo2web.com/2008/11/13/developing-virtual-earth-iphone-applications-with-objective-c/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From reading this, it seems use of the Virtual Earth API is non-trivial. Apparently, it requires the use of SOAP requests instead of JavaScript (which Google Maps uses). Also, the returned tile images have to be programmatically assembled into a nice iPhone image. The blog post directs you to a 3rd party framework library (BSD license) that can ease implementation:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://consonancesw.com/developers/virtualearthkit/"&gt;http://consonancesw.com/developers/virtualearthkit/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4) CloudMade&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cloudmade.com/"&gt;http://cloudmade.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;CloudMade uses the maps from OpenStreetMap (http://www.openstreetmap.org/). I’ve seem OpenStreetMap used with the iPhone application MotionX-GPS, however, I’m not sure if it’s used through the CloudMade API.&lt;br /&gt;&lt;br /&gt;According to the following link, they place no restrictions on the API.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developers.cloudmade.com/projects/show/iphone-api"&gt;http://developers.cloudmade.com/projects/show/iphone-api&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;Just like our other APIs, we don't want to restrict the uses of this API - you are&lt;br /&gt;free to create applications that use our maps in any way you like, as long as&lt;br /&gt;they comply with the terms of the iPhone SDK agreement.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To implement, the user needs to download the API code and integrate with the iPhone application. CloudMade provides some iPhone application examples to learn from.&lt;br /&gt;&lt;br /&gt;CloudMade looks like a viable solution. And I’d prefer to use an open source solution, given that Google/Yahoo/Microsoft all seem to have vague terms of service agreements that allow them to cut off service for a variety of reasons.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So which one have I chosen? I think I’ll go with Google Maps. The ToS does give me some pause, however, my application is free and just for my own experience. If they shut it down, I’ll just switch to another mapping API.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7094379308761251815-5919394449113216840?l=blog.chrisyunker.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ITtafZhqTQjAo3QcbsF5NCCnQGI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ITtafZhqTQjAo3QcbsF5NCCnQGI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ITtafZhqTQjAo3QcbsF5NCCnQGI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ITtafZhqTQjAo3QcbsF5NCCnQGI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisYunkersWeblog/~4/Xx_qT3eMyko" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.chrisyunker.com/feeds/5919394449113216840/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=7094379308761251815&amp;postID=5919394449113216840" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/5919394449113216840?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/5919394449113216840?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisYunkersWeblog/~3/Xx_qT3eMyko/mapping-services-for-iphone.html" title="Mapping Services for iPhone Applications" /><author><name>Chris Yunker</name><uri>http://www.blogger.com/profile/11418739167012430451</uri><email>chris@chrisyunker.com</email><gd:extendedProperty name="OpenSocialUserId" value="02663009264953845519" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.chrisyunker.com/2009/03/mapping-services-for-iphone.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YERno9eyp7ImA9WxVUFUo.&quot;"><id>tag:blogger.com,1999:blog-7094379308761251815.post-728410032613938059</id><published>2009-03-13T09:17:00.000-07:00</published><updated>2009-03-20T11:51:47.463-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-20T11:51:47.463-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="mysql" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><category scheme="http://www.blogger.com/atom/ns#" term="apache" /><title>Ruby/Rails With Apache/MySQL on Mac OS (Leopard)</title><content type="html">I'm a new Mac user after many years of working on both Linux and Microsoft systems. This last week I went through the process of setting up my system for web development using the Ruby/Rails/Apache/MySQL platform. I was a little surprised to find out it was not as straightforward as working on Linux, given the Mac OS has a BSD core and is the development platform of a lot of high profile programmers.&lt;br /&gt;&lt;br /&gt;I'm writing this blog post primarily for my own reference. However, if it can help any others, all the better. Plus I welcome any feedback that may improve my setup.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Terminal Application&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All command line actions should be done through the Terminal application. This can be found at Application/Utilities/Terminal.app.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MacPorts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;MacPorts is a faculty similar to Aptitude in Ubuntu/Debian for installing software packages from the command line.&lt;br /&gt;&lt;br /&gt;MacPorts software is installed in a separate location under &lt;span style="font-weight: bold;"&gt;/opt/local/&lt;/span&gt;. Therefore, you can always determine whether or not an executable is part of MacPorts by running a &lt;span style="font-weight: bold;"&gt;which [command]&lt;/span&gt; and seeing if it's located under this directory.&lt;br /&gt;&lt;br /&gt;The current Leopard .dmg installer is version &lt;span style="font-weight: bold;"&gt;1.7.0&lt;/span&gt; and can be downloaded here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.macports.org/install.php"&gt;http://www.macports.org/install.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Once installed, open up a Terminal window and run the following command to make sure MacPorts is up to date&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ sudo port selfupdate&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The Terminal PATH should have the MacPorts directories (/opt/local/bin, /opt/local/sbin) preceding the standard directories. The MacPorts installer set this for me automatically. If this is not the case for you, be sure to change this in the /etc/profile file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ echo $PATH&lt;br /&gt;/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ruby&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Install Ruby and RubyGems via MacPorts.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ sudo port install ruby&lt;br /&gt;$ sudo port install rb-rubygems&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The Leopard Mac OS includes older versions of both of these programs which we do not want to use. Check to make sure that the MacPorts version is the version called from the command line:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ which ruby&lt;br /&gt;/opt/local/bin/ruby&lt;br /&gt;&lt;br /&gt;$ which gem&lt;br /&gt;/opt/local/bin/gem&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;These are the current versions&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ ruby &amp;#8208;v&lt;br /&gt;ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9]&lt;br /&gt;&lt;br /&gt;$ gem &amp;#8208;v&lt;br /&gt;1.3.1&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Rails Framework&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Install Rails framework files via RubyGems package manager.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ sudo gem install rake&lt;br /&gt;$ sudo gem install rails&lt;br /&gt;$ sudo gem install capistrano&lt;br /&gt;$ sudo gem install mongrel&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will install these packages with all dependencies. The following files should be installed&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ gem list&lt;br /&gt;&lt;br /&gt;*** LOCAL GEMS ***&lt;br /&gt;&lt;br /&gt;actionmailer (2.3.2)&lt;br /&gt;actionpack (2.3.2)&lt;br /&gt;activerecord (2.3.2)&lt;br /&gt;activeresource (2.3.2)&lt;br /&gt;activesupport (2.3.2)&lt;br /&gt;capistrano (2.5.5)&lt;br /&gt;cgi_multipart_eof_fix (2.5.0)&lt;br /&gt;daemons (1.0.10)&lt;br /&gt;fastthread (1.0.1)&lt;br /&gt;gem_plugin (0.2.3)&lt;br /&gt;highline (1.5.0)&lt;br /&gt;mongrel (1.1.5)&lt;br /&gt;net-scp (1.0.2)&lt;br /&gt;net-sftp (2.0.2)&lt;br /&gt;net-ssh (2.0.11)&lt;br /&gt;net-ssh-gateway (1.0.1)&lt;br /&gt;rails (2.3.2)&lt;br /&gt;rake (0.8.4)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MySQL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;MySQL can be installed through MacPorts or through a dmg installer. Since it’s not that important to me to have the latest version, I chose the dmg installer for simplicity.&lt;br /&gt;&lt;br /&gt;The installer can be downloaded here. The current version is &lt;span style="font-weight: bold;"&gt;5.1.32&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dev.mysql.com/downloads/mysql/5.1.html#macosx-dmg"&gt;http://dev.mysql.com/downloads/mysql/5.1.html#macosx-dmg&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The installer includes three parts:&lt;br /&gt;&lt;br /&gt;Database:        mysql-5.1.32-osx10.5-x86.pkg&lt;br /&gt;Preference Pane: MySQL.prefPane&lt;br /&gt;Launch Manager:  MySQLStartupItem.pkg&lt;br /&gt;&lt;br /&gt;I installed all three parts.&lt;br /&gt;&lt;br /&gt;Now install the Ruby MySQL interface package:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Add the MySQL bin folder to the PATH variable for command line use. Append the following line to the local profile file (~/.profile).&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;# MySQL Command Line&lt;br /&gt;export PATH=$PATH:/usr/local/mysql/bin&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Apache&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For Apache, I used the version included with the Mac OS.&lt;br /&gt;&lt;br /&gt;The Passenger gem package integrates Apache with the Rails framework. Install using the following commands.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$ sudo gem install passenger&lt;br /&gt;$ sudo passenger-install-apache2-module&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output of the last command should list some config settings to add to the Apache configuration. I added a separate file to put these in.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:100%;"  &gt;/etc/apache2/other/Passenger.conf&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;LoadModule passenger_module \&lt;br /&gt;/opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so&lt;br /&gt;PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6&lt;br /&gt;PassengerRuby /opt/local/bin/ruby&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I create a config file for each separate Rails project. The following example is for a project called ‘project1’.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:100%;"  &gt;/etc/apache2/other/project1.conf&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;&lt;br /&gt;  ServerName www.project1.com&lt;br /&gt;  ServerAdmin admin@project1.com&lt;br /&gt;  DocumentRoot /Users/username/Work/web/project1/public&lt;br /&gt;  ServerSignature On&lt;br /&gt;&lt;br /&gt;  CustomLog /var/log/apache2/project1_access.log combined&lt;br /&gt;  ErrorLog /var/log/apache2/project1_error.log&lt;br /&gt;  LogLevel info&lt;br /&gt;&lt;br /&gt;  &amp;lt;Directory /&amp;gt;&lt;br /&gt;    Options FollowSymLinks&lt;br /&gt;    AllowOverride None&lt;br /&gt;  &amp;lt;/Directory&amp;gt;&lt;br /&gt;  &amp;lt;Directory /Users/username/Work/project1/public/&amp;gt;&lt;br /&gt;    Options Indexes FollowSymLinks MultiViews&lt;br /&gt;    AllowOverride None&lt;br /&gt;    Order allow,deny&lt;br /&gt;    Allow from all&lt;br /&gt;  &amp;lt;/Directory&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to view my web site in a local browser, I need to add a setting in the hosts file to redirect to the local host. See the last line of the following file. Of course, you need to make sure to remove this once you deploy your web site to a real server.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:100%;"  &gt;/etc/hosts&lt;/span&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;#&lt;br /&gt;# Host Database&lt;br /&gt;#&lt;br /&gt;# localhost is used to configure the loopback interface&lt;br /&gt;# when the system is booting.  Do not change this entry.&lt;br /&gt;##&lt;br /&gt;127.0.0.1       localhost&lt;br /&gt;255.255.255.255 broadcasthost&lt;br /&gt;::1             localhost&lt;br /&gt;fe80::1%lo0     localhost&lt;br /&gt;&lt;br /&gt;127.0.0.1       www.project1.com project1.com&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7094379308761251815-728410032613938059?l=blog.chrisyunker.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/J4o2CjlMlwepqTqqA4CzyFA6ZiU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J4o2CjlMlwepqTqqA4CzyFA6ZiU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/J4o2CjlMlwepqTqqA4CzyFA6ZiU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J4o2CjlMlwepqTqqA4CzyFA6ZiU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisYunkersWeblog/~4/qJx0wt-ydvU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.chrisyunker.com/feeds/728410032613938059/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=7094379308761251815&amp;postID=728410032613938059" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/728410032613938059?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7094379308761251815/posts/default/728410032613938059?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisYunkersWeblog/~3/qJx0wt-ydvU/rubyrails-with-apachemysql-on-mac-os.html" title="Ruby/Rails With Apache/MySQL on Mac OS (Leopard)" /><author><name>Chris Yunker</name><uri>http://www.blogger.com/profile/11418739167012430451</uri><email>chris@chrisyunker.com</email><gd:extendedProperty name="OpenSocialUserId" value="02663009264953845519" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.chrisyunker.com/2009/03/rubyrails-with-apachemysql-on-mac-os.html</feedburner:origLink></entry></feed>
