Traveling Abroad with the iPhone

Recently, I visited London and Cardiff on vacation and took my iPhone with me. I knew ahead of time I would like to get the most use out of it, without incurring ridiculous roaming fees, so I planned ahead. This article discusses a number of different solutions and the benefits and limitations of each.

My Goal: Use maps with GPS tracking while traveling abroad

Although the native Google Maps application will not function on the streets of London without an Internet connection, there are applications that you can download ahead of time that will. One application that I liked in particular was OffMaps for the iPhone. It allows you to download maps of any city or region ahead of time, as well as select city guides. The map download is extremely customizable, including selecting the map’s level of precision. The only downside was that these maps/guides have to be downloaded directly by the iPhone (WiFi or 3G) and can take hours to retrieve. I would have preferred an option that let you download the maps from iTunes, utilizing a wired Ethernet connection. Also, you must download maps for all areas you intend to visit ahead of time, as even WiFi connections can be costly and limited abroad.

While I did try other, often city-specific applications, but I wasn’t as impressed with them as OffMaps. Plus, I was able to configure the same application for multiple cities prior to my trip.

After downloading an offline map application, my second goal was to enable GPS. This as it turns out, is trickier than I thought.

Solution 1: Leave the iPhone at home

I considered leaving it at home, but it’s really hard to organize a car service on your return trip if they have no way to reach you. Also, it’s useful to check the time and recent e-mail since my cell phone has replaced my watch as my mechanism for keeping time. Finally, the iPhone is nice for watching TV and movies on the plane as well as listening to music while traveling.

Solution 2: Put the iPhone in Airplane Mode for the entire trip

Most blogs I visited prior to departure recommended putting my iPhone in Airplane Mode for the length of my trip, as it allows you to use WiFi without any possibility of incurring roaming fees. The problem, though, is that it also disables the phone’s GPS, so that you cannot track your current location. Goal failed.

Solution 3: Disable Cellular Data and Roaming

One obvious solution is to go into the General > Network settings and disable cellular data and roaming. There’s a few problems with this though. First, you’re trusting your cell phone not to accidentally charge you for usage. Based on some of the stories floating around the net about being charged thousands of dollars for roaming, that’s just a leap of faith I’m not personally able to make. Second, your battery life is going to be severely limited, because the iPhone will be searching for a signal during the entire trip. Finally, there’s no guarantee some data features won’t continue to process, such as voice mail. With Apple’s Visual Voicemail, the iPhone downloads audio files automatically every time someone leaves you a message. Think of it as a charge anytime someone leaves you a message.

There are steps you can take to disable voice mail while traveling, but I do not recommend them. AT&T has to actually switch your data plan while you’re away, there’s no option to simply disable it. For those with no-longer-available unlimited data plans, switching our data plan can make us a little edgy. Also, there’s no guarantee GPS will work in this environment, although it probably should.

Solution 4: Replace the SIM card

Those absolutely needing international access can buy a SIM from a local carrier. Given that I’m using a US iPhone, and AT&T has severely restricted non-AT&T usage, I wasn’t convinced this would work without jail-breaking the iPhone. Also, there are some security risks from letting your passwords/access transfer over a network you may not be familiar with. Ultimately, I decided this option wouldn’t be worth the headache. If I had a more open, European iPhone, though, I may have felt differently, since in those markets the phone and the SIM are not extremely interconnected.

Solution 5: Lock the SIM card

One excellent recommendation was to install a 4-digit PIN code on the SIM which requires entry every time the iPhone is started and disables all cellular/data communication if not present. The advantage to this is that GPS continues to work in this environment. The only down side is that you have make sure not to forget your PIN code. Also, I had to do a bit of searching to find the ‘default’ pin code that programmed into my SIM card.

Solution 6: Remove the SIM card

Similar to Solution #5, I realized I could just pull out the SIM card. No special tools required, just a paper clip and a plastic bag to put it in (the new Micro SIMs are tiny and easy to lose). Unlike some of the other solutions which rely on software features, this completely prevents data roaming but still allows WiFi usage and GPS support, so it’s the solution I went with. I just left the SIM in a hotel safe and carried the phone around all day. I was successful with my original goal of simulating Google Maps with tracking, as the offline maps and GPS functioned as expected. The only thing I noticed is that true GPS requires much clearer line of site with a satellite. In other words, GPS only functioned when I was out in the open, and sometimes took a while to acquire an initial signal. This is to be expected with GPS technology, but having the iPhone’s data network fix a location faster than traditional GPS has spoiled me over the last few years.

Reflections

Ultimately, downloading the offline maps was the single best step I took prior to my departure. Removing the SIM card was also quite easy to do and gave me peace of mind that the software wasn’t going to ‘accidentally’ allow data connections while traveling. Also, the battery was significantly better with no SIM card, and the iPhone could go for days without charging. I guess the data network usage really does chew up the battery.

Ultimately, GPS was only partially useful, as I was able to figure out where I was on the map pretty quickly based on landmarks. However, had I been traveling in a more difficult-to-navigate city or had a worse sense of direction, I would have probably used GPS more frequently.

Memo: Avoid Functions in Database Queries

The most common type of questions in the JavaRanch JDBC forum tends to be about improving performance in a database (that, and “Where can I download a JDBC Driver?”). While remote trouble-shooting performance issues can be tricky, we often spot issues with the presented queries and offer alternatives to improve performance. One issue I see from time to time is the use of database built-in functions in database queries. In general, these should be avoided at all costs for commonly-executed queries, especially ones that could trigger the function to be applied to every record in a table. This article will address this issue of using functions in database queries in more detail and provide explanations and tips for avoiding them in the future.

1. Throwing away indexes

By default, databases search an entire table for records. The purpose of indexes, created automatically by some DBMS systems, is to allow records to be retrieved faster. Using Big O notation, a sorted set of records can find an item within a range in O(log(n)) while an unsorted set would have to search the entire table, or O(n). For hash searches on a specific key, the search time is near O(constant) for properly balanced data structures.

Developers can create indexes on multiple columns in a table, but they have no direct control over how and when they are used. It is the job of the DBMS query optimizer to apply what it thinks are the best indexes at the time the query is requested. Queries that apply a function to a column in a database will likely throw away any index that the query optimizer could take advantage of to search the table, resulting in a full-table scan every time the table is queried. If you are lucky and your table only contains a few dozen records, this issue might not be noticeable, but for the rest of us, this could pose a serious problem. While there are some DBMSs, Oracle being one of them, that support function-based indexes, but they are far from standard practice.

2. Goodbye Portability

My biggest issue with functions, like any database-specific feature, is the fact that they are database specific features! Once you write a query that takes advantage of a specific function, porting your application to a different database system becomes much more difficult. Oftentimes, functions are used because there is a muddling of the data, application, and presentation layer. I have seen developers use database-specific functions to format data (most commonly, dates) from SELECT queries that are transmitted from JDBC directly to the user. If you have a strong mid-tier platform like Java, it is better to leverage the formatting functions within the language, not database-specific ones, to present data to the user.

Porting an application to a different database is non-trivial at best, but the use of database-specific functions will make the job much more difficult. And to those developers out there who often comment that switching databases never happens, it does. I’ve done it. And it’s not for the faint of heart.

3. Slow if used incorrectly

There are correct ways to use functions in database queries that are often overlooked when writing the query. For example, compare the following two MySQL-based queries, both of which search for orders placed on February 15, 2010 and use built-in functions:

SELECT * FROM Widgets WHERE DATE_FORMAT(orderDate,"%Y-%m-%d") = '2010-02-15';
SELECT * FROM Widgets WHERE orderDate = (CAST '2010-02-15' as DATETIME);

First, question is, are they equivalent? The answer is no, but let’s skip that for now and discuss performance. Which is likely to perform better on a database that contains a tree-based index on Widgets.orderDate?

Give up? The second query, of course! The second query applies a function to a constant, and most database query analyzers are intelligent enough to only apply this function once. It then uses the range index to find the records in Log(n) time. On the other hand, the first query performs a function call on every record in the table and therefore ignores the index – resulting in a slow table scan.

As for accuracy, if orderDate is a DATETIME, the second query will return all the results placed only at midnight on February 2nd (2010-02-15 00:00:00) while the second query will return all results placed during the entire day. No worries – there is an easy fix that still uses the index on orderDate for optimal performance:

SELECT * FROM Widgets WHERE orderDate >= (CAST '2010-02-15' as DATETIME)
     AND orderDate < (CAST '2010-02-16' as DATETIME);

Even though this adds a second parameter to the search, the sorted index can be applied to both.

Final Thoughts

Like many things in the world, database functions are necessary evil that are required to solve certain problems. The goal shouldn’t be to never use them, but to keep using them to a minimum. One common solution, if the function is being applied to a column repeatedly, is to denormalize the data and add a new column containing the value of the original column with the function applied to it. This is equivalent to how a function-based index works, for databases that do not have this feature built-in. The only overhead is the cost of maintaining the value in the new column each time the original value is updated, although since reads are more common than writes, this is often easy in practice. I am aware some developers have issues with denormalized data, but it is often necessary on large tables with queries that can run for minutes or even hours.

In the previous example, if searching on specific single dates is extremely common, the developer could add an orderDateSTR column that contains strings such as ‘2010-02-15’. A hash index could then be built on the column which would allow searches for single dates to be accomplished in near constant time. Granted, this is not useful for range queries, but would be useful in situations where single date searching needed to be fast on large data sets.

Flex – Event Handlers and Weak References

Did you know defining an event handler on an object in Flex can prevent it or other objects from being garbage collected even after all explicit references to the objects have been removed? If not, then keep reading.

Introduction

Previously, I discussed techniques for freeing up memory on video and images in Flex, but I neglected to include a discussion of event handlers. With the release of ActionScript 3, Adobe added the notion of strong references and weak references. Strong references are those references that, if present, will prevent the object from being garbage collected. The presence of only weak references, on the other hand, will allow an object to be garbage collected. When most developers consider garbage collection, they often consider only strong references, those references they explicitly know about. The age-old wisdom, that if you remove all active (strong) references to an object, it will become eligible for garbage collection, overlooks the fact that the object may have strong references from other objects, created via event handler registration.

Event Handlers are Strong References (by default)

Somewhat surprisingly, and perhaps in a move to preserve older source code, the commonly used method addEventListener() creates a strong reference to the event handler by default. That means even after removing all explicit references to an object, it may never be eligible for garbage collection because other objects have subscribed as listeners to the object. If you have a process that repeatedly creates such objects, you have an uncontrolled memory leak that will eventually crash your program. As an example, consider a screen saver application that displays a new Image or Video on the screen every 30 seconds by creating new display objects and discarding the existing ones. Without considering the event handlers on this application, the memory usage could grow without bound, even if you take proper steps to discard the display objects.

From the Adobe Flex 3 documentation:

One important consequence of this parameter involves working with display objects’ events. Normally, you might expect a display object to be removed from memory when it is removed from the display list. However, if other objects have subscribed as listeners to that display object, with the useWeakReference parameter set to false (the default), the display object will continue to exist in Flash Player’s or AIR’s memory even though it no longer appears on the screen.

Solution #1: Proper deconstructor

The most obvious solution to prevent event handlers from holding objects in memory is to call removeEventListener() on the original object for each event handler on it. The problem is Flex does not provide a listAllEventListeners() method nor a removeAllEventListeners() method in the Event Dispatcher API [Feature Request!], so unless you remembered to save a reference to the event handler when you created it, you’re not going to have much luck removing it. This solution requires you to manage a list of event handlers and their associated types, so each can be discarded at a later time. Also, remember to remove the reference to the event handler in the list, such that the act of maintaining a list of references does not prevent garbage collection.

Solution #2: Declare a weak reference

Maintaining a list of event handlers for every object is a bit cumbersome, so luckily Adobe has added a better solution: declare the reference weak when the event is added to the object. In ActionScript 3, Adobe added an overloaded version of addEventListener() that takes 5 parameters. By setting the 5th parameter (useWeakReference) to be true, the event handler and its associated objects will become eligible for garbage collection if the weak reference event handlers are the only ones left.

For example, let’s say you defined a timer to run for 10 seconds and then stop:

var myTimer:Timer = new Timer(10,0);
myTimer.addEventListener(TimerEvent.TIMER,myTimerHandler);

As the code is written, objects referenced by myTimerHandler cannot be garbage collected, even if the timer was never started. Alternatively, if you add the overloaded parameters to the method ,false,0,true, objects referenced by myTimerHandler can be garbage collected:

var myTimer:Timer = new Timer(10,0);
myTimer.addEventListener(TimerEvent.TIMER,myTimerHandler,false,0,true);

Keep in mind, there are situations when it makes sense to define event handlers using strong references even on temporary objects. Just remember to explicitly remove the event handler if you want to reclaim the allocated memory.

Some developers, though, have made cases that Solution #1 is the only correct solution, and that using weak references is not sufficient for proper memory management.

Conclusion: Refactor your code with overloaded parameters

My suggestion to the reader is search through their code for all occurrences of addEventListener. For each occurrence, decide whether the event handler should live for the life of the application and never be garbage collected, or can be removed before the application completes. If it is the former, and the event handler should live indefinitely for the application, then do nothing. If it is the latter, and the event handler may be discarded at some point, add the parameters ,false,0,true to the event handler creation. This will preserve the existing functionality but allow it to be garbage collected. Keep in mind, though, that the event handler will not be garbage collected if you maintain strong or explicit references to it elsewhere. In the previous example, if you defined myTimerHandler to be a class-level member function, then the event handler would not be eligible for garbage collection with or without the change to the event handler registration.