<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>appSTUDIO Israel</title>
	<atom:link href="http://www.appstudio.co.il/feed" rel="self" type="application/rss+xml" />
	<link>http://www.appstudio.co.il</link>
	<description></description>
	<lastBuildDate>Mon, 07 May 2012 04:33:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Converting an int to a Hebrew String</title>
		<link>http://www.appstudio.co.il/blog/converting-an-int-to-a-hebrew-string</link>
		<comments>http://www.appstudio.co.il/blog/converting-an-int-to-a-hebrew-string#comments</comments>
		<pubDate>Tue, 24 Apr 2012 11:09:46 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[iOS Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2704</guid>
		<description><![CDATA[For Open Talmud I need a way to convert a page number into a Hebrew numerals which is more familiar to those who study talmud. There is nothing great about the code. Just thought it would be a nice thing to share. -(NSString*) HebrewStringForInt:(int) number{ if (number ==15) { return @"טו"; } if (number==16) { [...]]]></description>
			<content:encoded><![CDATA[<p>For Open Talmud I need a way to convert a page number into a <a href="http://en.wikipedia.org/wiki/Hebrew_numerals">Hebrew numerals</a> which is more familiar to those who study talmud.  </p>
<p>There is nothing great about the code. Just thought it would be a nice thing to share.</p>
<pre class="brush: objc;">
-(NSString*) HebrewStringForInt:(int) number{
    if (number ==15) {
        return @"טו";
    }
    if (number==16) {
        return @"טז";
    }

    NSMutableString* toReturn=[NSMutableString string];
    while (number &gt; 400) {
        number-=400;
        [toReturn appendString:@"ת"];
    }

    if (number &gt;= 300) {
        [toReturn appendString:@"ש"];
        number-=300;
    }else if (number &gt;= 200) {
        [toReturn appendString:@"ר"];
        number-=200;
    }else if (number &gt;= 100) {
        [toReturn appendString:@"ק"];
        number-=100;
    }

    if (number &gt;= 90) {
        [toReturn appendString:@"צ"];
    }else if (number &gt;= 80) {
        [toReturn appendString:@"פ"];
    }else if (number &gt;= 70) {
        [toReturn appendString:@"ע"];
    }else if (number &gt;= 60) {
        [toReturn appendString:@"ס"];
    }else if (number &gt;= 50) {
        [toReturn appendString:@"נ"];
    }else if (number &gt;= 40) {
        [toReturn appendString:@"מ"];
    }else if (number &gt;= 30) {
        [toReturn appendString:@"ל"];
    }else if (number &gt;= 20) {
        [toReturn appendString:@"כ"];
    }else if (number &gt;= 10) {
        [toReturn appendString:@"י"];
    }

    if (number %10 ==9) {
        [toReturn appendString:@"ט"];
    }else if (number %10 ==8) {
        [toReturn appendString:@"ח"];
    }else if (number %10 ==7) {
        [toReturn appendString:@"ז"];
    }else if (number %10 ==6) {
        [toReturn appendString:@"ו"];
    }else if (number %10 ==5) {
        [toReturn appendString:@"ה"];
    }else if (number %10 ==4) {
        [toReturn appendString:@"ד"];
    }else if (number %10 ==3) {
        [toReturn appendString:@"ג"];
    }else if (number %10 ==2) {
        [toReturn appendString:@"ב"];
    }else if (number %10 ==1) {
        [toReturn appendString:@"א"];
    }

    return toReturn;
}
</pre>
<p>If you are using this for Hebrew Years keep in mind that the millennium is usually omitted and that some years have special rules which rearrange the the letters.  For example the year 742 should be ‫תשמ״ד‬ but that would spell a word that means "you will be destroyed", so instead the custom is to mix around the letters and write ‫תשד״מ‬.</p>
<p>Also keep in mind that the Hebrew numeral number system starts to look weird after 800 (with two ת's at the beginning of the number), and is completely worthless for large numbers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/converting-an-int-to-a-hebrew-string/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Documentation Errors</title>
		<link>http://www.appstudio.co.il/blog/ios-developer-tips/iphone-documentation-errors</link>
		<comments>http://www.appstudio.co.il/blog/ios-developer-tips/iphone-documentation-errors#comments</comments>
		<pubDate>Sun, 22 Apr 2012 12:27:17 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[iOS Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2542</guid>
		<description><![CDATA[For any iPhone or iPad developer the official Apple documentation is a fundamental tool in development. While the documentation is not very easy for beginners to use (it rarely has examples) it is thorough and precise. Because of how much developers rely on the documentation it is very important that they get it right. So [...]]]></description>
			<content:encoded><![CDATA[<p>For any iPhone or iPad developer the official Apple documentation is a fundamental tool in development.  While the documentation is not very easy for beginners to use (it rarely has examples) it is thorough and precise. Because of how much developers rely on the documentation it is very important that they get it right. So it really bothers me when there are mistakes.  I reported them to app using the <a href="https://bugreport.apple.com">Apple bug reporter</a>, and the three I submitted in January have already been fix.  One more I submitted in February is still unfixed.</p>
<p>Something that bothered me is that Apple did not mark the bugs as resolved and did not update the change logs to indicate that there were any changes.  So you are just going to have to take my word for it that these mistakes where there.<br />
<strong>Spelling mistake in SKRequestDelegate documentation</strong><br />
In the <a href="http://developer.apple.com/library/ios/#documentation/StoreKit/Reference/SKRequestDelegate/Reference/Reference.html">SKRequestDelegate documentation</a> the header for the section 'Handling Errors' read 'Handling Errrors', with the extra 'r'.  It was a bit ironic.</p>
<p><strong>Mistaking an enumerated type for a BOOL</strong><br />
UITableView has a bunch of functions for modifying the tableview, such as adding, removing and reloading cell.  For all of these there is an enumerated type of what kind of animation you want to you (fade, push from left, push form top etc). In the <a href="https://developer.apple.com/library/ios/#documentation/uikit/reference/UITableView_Class/Reference/Reference.html"> UITableview documentation </a> for - (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation<br />
it did state that the row animation was a BOOL not an enumerated type.  This was already pointed out on stackoverflow (<a href="http://stackoverflow.com/questions/6431806/bug-in-uitableview-deletesectionswithrowanimation">here</a>) in June 2011, but it wasn't fit until Feb 2012 after I submitted the bug report.</p>
<p><strong> iOS documentation confuses a path for a URL</strong><br />
I know that I am being really pedantic, but this one bothered me a little.  I (like most iOS developers) has some trouble at first with the difference between a path (a kind of NSString) and a url (and kind of NSURL). So when the documentation confuses them it can be really tough for a new programmer.  In <a href="https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html">NSFileManager</a> there are two very similar functions:<br />
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error<br />
and<br />
- (BOOL)removeItemAtURL:(NSURL *)URL error:(NSError **)error<br />
for the path one it used to state:<br />
"Return value: YES if the item was removed successfully or if URL was nil." - which is confusing since there is no URL there is only a path.  Seems like it was a copy-paste mistake. Thankfully they fixed it, and they even added italics to the words 'URL' and 'path'.</p>
<p><strong>Misnamed variable in Programming Guide</strong><br />
In the a href="https://developer.apple.com/library/mac/#documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_pdf_scan/dq_pdf_scan.html"&gt;programing guid to PDF</a> there is some sample code called "Open the PDF Document".  This is the code that Apple posted</p>
<pre class="brush: objc;">
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL(url);// 1
if (myDocument == NULL) {// 2
        error ("can't open `%s'.", filename);
        CFRelease (url);
        return EXIT_FAILURE;
}
CFRelease (url);
if (CGPDFDocumentIsEncrypted (myDocument)) {// 3
    if (!CGPDFDocumentUnlockWithPassword (myDocument, "")) {
        printf ("Enter password: ");
        fflush (stdout);
        password = fgets(buffer, sizeof(buffer), stdin);
        if (password != NULL) {
            buffer[strlen(buffer) - 1] = '';
            if (!CGPDFDocumentUnlockWithPassword (myDocument, password))
                error("invalid password.");
        }
    }
}
if (!CGPDFDocumentIsUnlocked (myDocument)) {// 4
        error("can't unlock `%s'.", filename);
        CGPDFDocumentRelease(myDocument);
        return EXIT_FAILURE;
    }
}
 if (CGPDFDocumentGetNumberOfPages(document) == 0) {// 5
        CGPDFDocumentRelease(document);
        return EXIT_FAILURE;
}
</pre>
<p>Did you catch it?.  The last check uses of the variable "document" when the rest of the code used "mydocument".  This is the only one of the four which is still now fixed.  </p>
<p>The lesson here is that Apple bug reporter works, but don't expect any feedback or a thank you, or even a notice in the change log.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/ios-developer-tips/iphone-documentation-errors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Proverbidioms</title>
		<link>http://www.appstudio.co.il/portfolio/apps/proverbidioms</link>
		<comments>http://www.appstudio.co.il/portfolio/apps/proverbidioms#comments</comments>
		<pubDate>Tue, 17 Apr 2012 09:20:04 +0000</pubDate>
		<dc:creator>cnotethegr8</dc:creator>
				<category><![CDATA[Apps]]></category>
		<category><![CDATA[Portfolio]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2431</guid>
		<description><![CDATA[Cat got your tongue...Time flies...An Apple a Day Keeps the Doctor Away. Find these expressions and hundreds more in the picturesque and audible game Proverbidioms! You can explore the pictures to find the phrases, or from a list of sayings identify the matching depictions. And as an added bonus, you can learn the captivating origins, [...]]]></description>
			<content:encoded><![CDATA[<p>Cat got your tongue...Time flies...An Apple a Day Keeps the Doctor Away.  Find these expressions and hundreds more in the picturesque and audible game Proverbidioms! You can explore the pictures to find the phrases, or from a list of sayings identify the matching depictions.  And as an added bonus, you can learn the captivating origins, meanings and usage of these animated proverbs and idioms. With this iPad app, feel free to get carried away!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/portfolio/apps/proverbidioms/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ten steps to get started with Facebook on Andriod</title>
		<link>http://www.appstudio.co.il/blog/android-developer-tips/ten-steps-to-get-started-with-facebook-on-andriod</link>
		<comments>http://www.appstudio.co.il/blog/android-developer-tips/ten-steps-to-get-started-with-facebook-on-andriod#comments</comments>
		<pubDate>Tue, 03 Apr 2012 09:49:46 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[Andriod Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2665</guid>
		<description><![CDATA[Lately, I’ve been trying to learn how to create posts on Facebook but the web is not very clear about how to do this. In the end, after a couple of days looking around, I found the way to do this, and decided to write down in a few quick words, how to do this. [...]]]></description>
			<content:encoded><![CDATA[<p>Lately, I’ve been trying to learn how to create posts on Facebook but the web is not very clear about how to do this. In the end, after a couple of days looking around, I found the way to do this, and decided to write down in a few quick words, how to do this.</p>
<ol>
<li> Download the Facebook SDK for Android. It can be downloaded easily from the <a href="https://developers.facebook.com/docs/mobile/android/build/#sdk">Facebook developers website.</a></li>
<li>Get a hash key from the Android keytool. The command I found around the net is:
<pre class="brush: java;">
	keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
</pre>
</li>
<li>Create an app on Facebook.</li>
<li>Add the hash key to your app (you have to choose “native android app” below “select how your app  integrates with Facebook").</li>
<li>In Your project, add the external Jar file for the facebook SDK.  The way to do this is to follow these simple steps:
<ol>
<li>Right click on the project in eclipse.</li>
<li>Choose “properties” (command+i).</li>
<li>Choose the java build path.</li>
<li>Add external jar.</li>
<li>Choose the Facebook sdk jar from the /%facebook-sdk-folder%/facebook/bin/com_facebook_android.jar.</li>
</ol>
</li>
<li> In your code, add an import to the facebook sdk.
<pre class="brush: java;">
import com.facebook.andriod.Facebook;
</pre>
</li>
<li>The next thing to do, is to create a new instance of the Facebook object.
<pre class="brush: java;">
Facebook facebook = new Facebook(“your-app-id”);
</pre>
<p>this will create an instance of a Facebook object that’s linked to your app.
</li>
<li>The next thing to do is to sign in with Facebook’s SSO (Single Sign-On). the way to do this, is with the function authorise, you need to call it with the calling activity, the permissions requested and a FacebookDialogListener that has to be implemented.</li>
<li>The facebookDialogListener implements 4 functions.
<ul>
<li>onCancel (handles clicking the back button or the x button on the login popup).</li>
<li>onError (handles java-side errors and network errors).</li>
<li>onFacebookError (handles errors received from the server-side).</li>
<li>onComplete </li>
</ul>
<p>the overriding of onComplete is what to do when you get back the access token from the server side.<br />
the way to get the session key is:</p>
<pre class="brush: java;">
public void onComplete(Bundle values){
	String token = values.getString(Facebook.TOKEN);
	//DO SOMETHING
}
</pre>
<p>every time you need to interact with the facebook servers you need to send the token with the request.</p>
<li> The main problem with SSO is that you are probably already signed in with your facebook app and therefore the authorize function doesn’t return a new token, instead you need to get the token from the existing sign-on.<br />
to get that value, you’ll need to override the onActivityResult function and call the authorizeCallback function. the code for this is:</p>
<pre class="brush: java;">
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	facebook.authorizeCallback(requestCode, resultCode, data);
}
</pre>
<hr />
Now you are all ready to go with using the Facebook Graph API.  Here is a code sample for posting on a Facebook wall.</p>
<pre class="brush: java;">
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.Facebook.DialogListener;
import com.facebook.android.FacebookError;

public class Main extends Activity{
Facebook facebook;
String permissions[] = {“publish_stream”};

@Override
public void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	facebook.authorize(Main.this, permissions, new DialogListener(){
		public void onComplete(Bundle values){
			updateStatus(values.getString(Facebook.TOKEN));
		}

		public void onFacebookError(FacebookError e){
		}

		public void onError(DialogError e){
		}

		public void onCancel(){
		}
	});
	public void updateStatus(String accessToken){
		try{
			Bundle msg = new Bundle();
			msg.putByteArray(“message”, “this is a sample message”.getBytes());
			msg.putByteArray(Facebook.TOKEN, accessToken.getBytes());
			String response = facebook.request(“me/feed”, msg, “POST”);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
		super.onActivityResult(requestCode, resultCode, data);
		facebook.authorizeCallback(requestCode, resultCode, data);
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/android-developer-tips/ten-steps-to-get-started-with-facebook-on-andriod/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSCalendar&#8217;s quirks with regards to weeks</title>
		<link>http://www.appstudio.co.il/blog/ios-developer-tips/nscalendar-week-calculations</link>
		<comments>http://www.appstudio.co.il/blog/ios-developer-tips/nscalendar-week-calculations#comments</comments>
		<pubDate>Tue, 13 Mar 2012 15:05:04 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[iOS Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2642</guid>
		<description><![CDATA[A former colleague of mine (who we are still on good terms with) recently asked me a NSDate related question: I'm struggling with a problem that should be simple. The problem is how do I get the NSDate that represents "nearest Sunday at 00:00:00" (for example, in the Gregorian calendar). So this is what I [...]]]></description>
			<content:encoded><![CDATA[<p>A former colleague of mine (who we are still on good terms with) recently asked me a NSDate related question:</p>
<blockquote><p>
I'm struggling with a problem that should be simple.</p>
<p>The problem is how do I get the NSDate that represents "nearest Sunday at 00:00:00" (for example, in the Gregorian calendar).  </p>
<p>So this is what I had in mind:</p>
<p>1. Create NSDateComponents from [NSDate date] against the gregorian calendar. Ask only for the year, the serial number of the week and the time.<br />
2. Change the weekday of this date components to "1" and the time to 00:00:00.<br />
3. Translate back to NSDate against the same calendar.</p>
<p>What's my problem:<br />
What if this sunday is not in the same year? For example, if we are in the first week of the year, and the year started in Monday, what will I get if I'll ask for the "Sunday of week 1"?<br />
Error? the right date? undefined?
</p></blockquote>
<p>This is a great question:  How do years interact with weeks?  While months and days never overlap two different years*, a week can start in on year and end in another!  This brings us to the often overlooked NSDateComponent: <strong>NSYearForWeekOfYearCalendarUnit</strong>.  </p>
<p>The YearForWeekOfYear has the property that it can start (or end) a little before or after the regular year, but will ensure that weeks do not straddle any year.  How these "years" are exactly broken up is decided by two properties of NSCalendar: firstWeekday  and minimumDaysInFirstWeek.</p>
<p>Now that were have a year system that guarantees that week will all be in the same year we can easily find the last Sunday:</p>
<pre class="brush: objc;">
-(NSDate*) LastSundayBeforeDate:(NSDate*) date{
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] ;
    NSUInteger unitFlags =NSWeekdayCalendarUnit | NSWeekOfYearCalendarUnit | NSYearForWeekOfYearCalendarUnit;
    NSDateComponents * components =[gregorian components:unitFlags fromDate:date];
    //1 is sunday in a gregorian calendar
    components.weekday=1;
    return [gregorian dateFromComponents: components];
}
</pre>
<p>Just like we can represent a date with {year-month-day}, we can also represent a date as {year-week-weekday} - as long as we remember that this is special kind of "year" where weeks are on only in one year.  All we are doing is saying that for any date find the {year-week-weekday} then give me the date for {year-week-1}.  This would be a very similar process if I wanted to find the date (NSDate) of the first day of a month that another date falls in.</p>
<p>Now to get next Sunday we would just need to add a week:</p>
<pre class="brush: objc;">
-(NSDate*) weekAfterDate:(NSDate*) date{
    NSDateComponents* oneWeekInterval=[[NSDateComponents alloc] init];
    oneWeekInterval.week=1;
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] ;
    return [gregorian dateByAddingComponents:oneWeekInterval toDate:date options:0];
}
</pre>
<p>Finally the function for next Sunday is just a week after last Sunday.</p>
<pre class="brush: objc;">
-(NSDate*) nextSunday:(NSDate*) date{
    return [self weekAfterDate: [self LastSundayBeforeDate:date]];
}
</pre>
<p>In the code above I am creating two different NSCalendars without any "real" benefit.  Some would argue that the code should be refactored to be a single function.  I disagree.  Code clarity is more important than efficiency especially with objects that are already very fast.  </p>
<p>In any event if you are calling this function over and over again, cutting the amount of NSCalendars in half is not the right answer.  You should create an instance variable for the Gregorian Calendar and reuse it many many times.</p>
<p>There is one more thing to note.  I said above that weeks can change years, unlike months which do not straddle years.  This is not completely tree. The Japanese Calendar numbers the years from the start of the emperor’s reign.  They normally change on December 31, but can change at any time of the year if the emperor dies.<br />
■ 31 December, Showa 63<br />
■ 1 January, Showa 64<br />
■ …<br />
■ 7 January, Showa 64<br />
■ 8 January, Heisei 1</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/ios-developer-tips/nscalendar-week-calculations/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UIGestureRecognizer Cancelled State</title>
		<link>http://www.appstudio.co.il/blog/ios-developer-tips/uigesturerecognizer-cancelled-state</link>
		<comments>http://www.appstudio.co.il/blog/ios-developer-tips/uigesturerecognizer-cancelled-state#comments</comments>
		<pubDate>Sat, 03 Mar 2012 12:58:14 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[iOS Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2532</guid>
		<description><![CDATA[UIGestureRecognizers were a great improvement to iOS starting in version 3.2. For those of you who had to deal with the touchesBegan: and touchesMoved: method of UIResponder you need no explanation. For the noobs out there, they provide a common interface for standard touch events and give a simple API to access what it means. [...]]]></description>
			<content:encoded><![CDATA[<p>UIGestureRecognizers were a great improvement to iOS starting in version 3.2. For those of you who had to deal with the touchesBegan: and touchesMoved: method of UIResponder you need no explanation.  For the noobs out there, they provide a common interface for standard touch events and give a simple API to access what it means.  For rotations that means that complex trigonometry of rotation calculations are done for you and all you have to do is call</p>
<pre class="brush: objc;">
    [rotationRecongizer rotation];
</pre>
<p>to get the rotation begin performed on the UIView and you can easy append it to the transform.</p>
<p>Something that may confuse people is the many states that a recognizer can be in:</p>
<pre class="brush: objc;">
typedef enum {
    UIGestureRecognizerStatePossible,   // the recognizer has not yet recognized its gesture, but may be evaluating touch events. this is the default state

    UIGestureRecognizerStateBegan,      // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop
    UIGestureRecognizerStateChanged,    // the recognizer has received touches recognized as a change to the gesture. the action method will be called at the next turn of the run loop
    UIGestureRecognizerStateEnded,      // the recognizer has received touches recognized as the end of the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible
    UIGestureRecognizerStateCancelled,  // the recognizer has received touches resulting in the cancellation of the gesture. the action method will be called at the next turn of the run loop. the recognizer will be reset to UIGestureRecognizerStatePossible

    UIGestureRecognizerStateFailed,     // the recognizer has received a touch sequence that can not be recognized as the gesture. the action method will not be called and the recognizer will be reset to UIGestureRecognizerStatePossible

    // Discrete Gestures – gesture recognizers that recognize a discrete event but do not report changes (for example, a tap) do not transition through the Began and Changed states and can not fail or be cancelled
    UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible
} UIGestureRecognizerState;
</pre>
<p>UIGestureRecognizerStatePossible and UIGestureRecognizerStateFailed are rarely relevant since they do not call the action method.  UIGestureRecognizerStateRecognized is also rarely relevant since it is only for discreet touch events, such as a tap.</p>
<p>In general the action method for the gestureRecognizer will test the recognizer's state and have different code for UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged and UIGestureRecognizerStateEnded. UIGestureRecognizerStateCancelled is often ignored - it shouldn't be.</p>
<p>Many people are confused what that cancelled state is, or why it would ever be used. The cancelled state is rarely seen, but if a gesture is cancelled it may leave the UIView in an undesirable state.   My rule is to run the same code for the Cancelled State as I do for Ended State.</p>
<p>Let me give you an example of what I mean. Take a look at the Facebook app - this will work on either the iPhone or the iPad version, but you need iOS 5.  The main view of the Facebook app can be panned to the right to reveal a menu below it.  Start your finger close the top center of the screen and start dragging right. Now move you finger up to the status and pull down - as if you are trying to pull down the iOS notifications.  If you did it right (it takes a little practice) you now have the Facebook sidebar half revealed and half hidden.  (You can also start with the menu revealed and start panning left, then move you finger up and pull down).</p>
<p>When you start moving your finger it trigger the UIPanGestureRecognizer to start moving the UIView.  But after you start moving down near the status bar iOS says "oops I was wrong" and cancels the GestureRecognizers using those touches.  </p>
<p>I don't need to see Facebook's code to know that they failed to implement the same code for UIGestureRecognizerStateCancelled as they did for UIGestureRecognizerStateEnded. In truth, Facebook should implement different code for the Cancelled State to return the UIView to where it started regardless of how it has been moved by the gesture, but that is a lot to ask for a case which is so rare.  Leaving the view half open and half close though is much worse, especially considering how easy it is to fix.</p>
<p>So don't make the same mistake as Facebook, go through all your code and replace</p>
<pre class="brush: objc;">
	if (UIGestureRecognizerStateEnded == [recognizer state])
</pre>
<p>with </p>
<pre class="brush: objc;">
	if (UIGestureRecognizerStateCancelled ==[recognizer state] || UIGestureRecognizerStateEnded == [recognizer state])
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/ios-developer-tips/uigesturerecognizer-cancelled-state/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hands On Equations</title>
		<link>http://www.appstudio.co.il/portfolio/apps/hands-on-equations</link>
		<comments>http://www.appstudio.co.il/portfolio/apps/hands-on-equations#comments</comments>
		<pubDate>Thu, 01 Mar 2012 10:49:38 +0000</pubDate>
		<dc:creator>cnotethegr8</dc:creator>
				<category><![CDATA[Apps]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2427</guid>
		<description><![CDATA[Hands-On Equations is the ideal first introduction to algebra for elementary and middle school students. Not only will these students have fun and be fascinated with the program, their sense of self-esteem will be dramatically enhanced as they experience success with sophisticated looking algebraic equations.]]></description>
			<content:encoded><![CDATA[<p>Hands-On Equations is the ideal first introduction to algebra for elementary and middle school students. Not only will these students have fun and be fascinated with the program, their sense of self-esteem will be dramatically enhanced as they experience success with sophisticated looking algebraic equations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/portfolio/apps/hands-on-equations/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Translate a UIView without creating a new XIB file</title>
		<link>http://www.appstudio.co.il/blog/ios-developer-tips/translate-a-uiview-without-creating-a-new-xib-file</link>
		<comments>http://www.appstudio.co.il/blog/ios-developer-tips/translate-a-uiview-without-creating-a-new-xib-file#comments</comments>
		<pubDate>Thu, 01 Mar 2012 09:53:43 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[iOS Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2553</guid>
		<description><![CDATA[When dealing with multiple languages Apple recommends creating a different XIB file for each language, and a strings file for the NSStrings embedded in your code. While creating a new XIB gives you the most flexibility, it is also a big pain. If you have 3 languages it is three times the amount of work [...]]]></description>
			<content:encoded><![CDATA[<p>When dealing with multiple languages Apple recommends creating a different XIB file for each language, and a strings file for the NSStrings embedded in your code.  While creating a new XIB gives you the most flexibility, it is also a big pain.  If you have 3 languages it is three times the amount of work when updating a XIB file.  And it is also a huge amount of work to add a new language.  It also creates two different translations job: one in the strings file which can be done by a professional translator and another in the XIB file which requires a programmer.</p>
<p>Sometime you have view with very few strings that need to be localized. This can happen if your main view is a UITableView and most of your string are returned programmatically through a UITableViewDataSource. In this case it is easier to make an outlet to the few views that you need localized and localize them programmatically.  </p>
<pre class="brush: objc;">
    self.myLabelThatNeedsToBeLocalized.text=NSLocalizedString(myLabelThatNeedsToBeLocalized.text, @"translation for myLabelThatNeedsToBeLocalized");
</pre>
<p>The problem with is method is that it gets real tiresome real fast as you have more and more UIViews to translate.  My solution is a UIView category that will translate a UIView and all of its subviews:</p>
<p>UIView+APPStudioIsraelLocalizeView.h</p>
<pre class="brush: objc;">
#import 

@interface UIView (APPStudioIsraelLocalizeView)
-(void) Localize;
@end
</pre>
<p>UIView+APPStudioIsraelLocalizeView.m:</p>
<pre class="brush: objc;">

#import "UIView+APPStudioIsraelLocalizeView.h"

@implementation UIView (APPStudioIsraelLocalizeView)
-(void) Localize{
    NSMutableSet* SetToTranslate=[NSMutableSet setWithObject:self];

    while ([SetToTranslate count] &gt;0) {
        UIView* toTranslate=[SetToTranslate anyObject];

        if ([toTranslate isKindOfClass:[UILabel class]]) {
            ((UILabel*) toTranslate).text=NSLocalizedString(((UILabel*) toTranslate).text, nil);
        }else if ([toTranslate isKindOfClass:[UIButton class]]) {
            for (UIControlState state=0; state &lt;16; state++) {
                [((UIButton*) toTranslate) setTitle:NSLocalizedString([((UIButton*) toTranslate) titleForState:state],nil) forState:state];
            }
        }else if ([toTranslate isKindOfClass:[UISegmentedControl class]]) {
            int numberOfSegments=[((UISegmentedControl*) toTranslate) numberOfSegments];
            for (int segment=0; segment &lt; numberOfSegments; segment++) {
                [((UISegmentedControl*) toTranslate) setTitle:NSLocalizedString( [((UISegmentedControl*) toTranslate)  titleForSegmentAtIndex:segment], nil) forSegmentAtIndex:segment];
            }
        }else if ([toTranslate isKindOfClass:[UITextField class]]){
            ((UITextField*) toTranslate).placeholder=NSLocalizedString(((UITextField*) toTranslate).placeholder, nil);
        }else if ([toTranslate isKindOfClass:[UITextView class]]){
            ((UITextView*) toTranslate).text=NSLocalizedString(((UITextView*) toTranslate).text, nil);
        }else if([toTranslate isKindOfClass:[UINavigationBar class]]){
            ((UINavigationBar*) toTranslate).topItem.title=NSLocalizedString(((UINavigationBar*) toTranslate).topItem.title,nil);
        }else if([toTranslate isKindOfClass:[UIToolbar class]]){
            for (UIBarButtonItem* item in ((UIToolbar*)toTranslate).items) {
                item.title=NSLocalizedString(item.title, @&quot;&quot;);
                if  (item.customView){
                    [SetToTranslate addObject:item.customView];
                }
            }
        }else if ([toTranslate isKindOfClass:[UIDatePicker class]]){
            //don&#039;t look at subviews
        }else  if([toTranslate isKindOfClass:[UIPickerView class]]){
            //Don&#039;t look at subviews
        }else{  //Otherwise it might have subview worth looking at
            for (UIView* view in toTranslate.subviews) {
                [SetToTranslate addObject:view];
            }
        }

        [SetToTranslate removeObject:toTranslate];
    }
}
@end
</pre>
<p>I use an iterative method instead of a recursive one because I find it easier to read, easier to debug, and less prone to problems. I try to avoid recursion because I think it make programmer try to be more cleaver than they are.</p>
<p>The advantage of the above method is that it avoids creating a different XIB for each language, and is super easy to implement.</p>
<pre class="brush: objc;">
-(void) viewDidLoad{
    [super viewDidLoad];
    [self.view Localize];
}
</pre>
<p>This will not translate view that are not inside the view hierarchy when the view loads - such as view that created programmatically or views that are outside of the main view in the XIB file.  You would need to call Localized on those views individually, or when you create then set the text using NSLocalizedString.</p>
<p>One thing to note is that this doesn&#039;t solve size problems.  Some languages such as German take up much more space than English.  You need to make sure your UILabels are big enough to handle the largest translations you are supporting.  If you are dealing with languges with very different sizes, such as German and Chineses you are probally better off creating different XIB files.  Otherwise you will have a lot of empty space in the small language and be very cramped in the large one.</p>
<p>Also you should note that there is no way to automatically find the strings using genstrings. So you need to be meticulous in adding string to the Localizable.strings file every time you add a new string. </p>
<p>Overall I find that this is a good alternative to multiple xib files especially if you plan the layout of your UI to expect to have different sized strings.</p>
<p>The code is free to use under the terms of the "<a href="http://en.wikipedia.org/wiki/BSD_licenses">Simplified BSD License</a>" </p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/ios-developer-tips/translate-a-uiview-without-creating-a-new-xib-file/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An important lesson about NSCalendarComponents</title>
		<link>http://www.appstudio.co.il/blog/ios-developer-tips/the-limits-of-nscalendarcomponents</link>
		<comments>http://www.appstudio.co.il/blog/ios-developer-tips/the-limits-of-nscalendarcomponents#comments</comments>
		<pubDate>Tue, 21 Feb 2012 13:14:45 +0000</pubDate>
		<dc:creator>rose</dc:creator>
				<category><![CDATA[iOS Developer Tips]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2528</guid>
		<description><![CDATA[I recently stumbled across some code that was so bad I had to comment on it. //returns a Hebrew date from a Gregorian date - (NSDate*)convertHebrewDateWithDate:(NSDate*)date { ... When I saw this I was shocked! As you may already know an NSDate does not have any calendar information attached to it. It is a point [...]]]></description>
			<content:encoded><![CDATA[<p>I recently stumbled across some code that was so bad I had to comment on it.</p>
<pre class="brush: objc;">
//returns a Hebrew date from a Gregorian date
- (NSDate*)convertHebrewDateWithDate:(NSDate*)date {
...
</pre>
<p>When I saw this I was shocked! As you may already know an NSDate does not have any calendar information attached to it.  It is a point in time.  Internally it is a just a fancy wrapper for a count from January 1, <del datetime="2012-03-11T11:32:04+00:00">1970</del> 2001 with a double precision floating point.  So if you look at just the input and output of the function it makes no sense.  You are inputing a NSDate (a point in time) and getting back another point in time. </p>
<p>Even more, there is no meaning to the words "Hebrew date" or "Gregorian date"  all NSDates are calendar independent!</p>
<p>So what does the function actually do.  Well nothing good, but lets take a look:</p>
<pre class="brush: objc;">
  NSCalendar* gergorianCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
  NSCalendar* hebrewCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar] autorelease];
</pre>
<p>It start off good making calendars which is often a good start when dealing calendar conversions.  But then it is all down hill:</p>
<pre class="brush: objc;">
	NSUInteger dateUnits = NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit;
	NSDateComponents *dateComponents = [hebrewCalendar components:dateUnits fromDate:date];
</pre>
<p>Then he creates a date Components from the Hebrew calendar.  Something important to realize with NSDateComponents is that there is no context for what they mean.  It is simply a collection of seconds, minutes, hours, days, weeks, months, and years.  It could represent an amount of time - if for example they were created from NSCalendar's components:fromDate:toDate:options.  Or they can represent numerical representations of calendar information as it does when it is created from NSCalendar's components:fromDate:.  NSDateComponents does not reference the calendar it was created with to know what the information represents - that is up to the programmer. In the code above the components are a representation of a Hebrew Date.  If, for example, you gave it a NSDate that was this year's Passover the components would be would be day=15, month=7 and year=5772.</p>
<p>This next line make me cringe a little:</p>
<pre class="brush: objc;">
	NSDate *hebrewDate = [gergorianCalendar dateFromComponents:dateComponents];
  return hebrewDate;
}
</pre>
<p>AHHHHH!  You can't use Hebrew date components in a Gregorian calendar!  This will create a date of July, 15, 5772 in the distant future (which by the way would be 18 Tammuz, 9532).  It is completely meaningless!</p>
<p>The lessen here is already stated in a big prominent box in the <a href="https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/Reference/Reference.html" title="Apple documentation">Apple's documentation of NSDateComponents</a>:</p>
<blockquote><p>
Important  An NSDateComponents object is meaningless in itself; you need to know what calendar it is interpreted against, and you need to know whether the values are absolute values of the units, or quantities of the units.</p></blockquote>
<p>Frankly I am not sure why NSDateComponents is an object instead of just a struct.  If it was a struct it would be a lot clearer that it is not meant to do anything beyond simply storing values, and we wouldn't be seeing mistakes like this. </p>
<p><strong>UPDATE</strong>:  I also realized that the reverse conversion will not necessarily return you to the same date!  In any Hebrew year where there isn't a leap year the 7th month is interpreted the same as a the 6th.  So you could jump form July to Adar and then back to June.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/blog/ios-developer-tips/the-limits-of-nscalendarcomponents/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iMegillah</title>
		<link>http://www.appstudio.co.il/portfolio/apps/imegillah</link>
		<comments>http://www.appstudio.co.il/portfolio/apps/imegillah#comments</comments>
		<pubDate>Mon, 20 Feb 2012 08:33:57 +0000</pubDate>
		<dc:creator>cnotethegr8</dc:creator>
				<category><![CDATA[Apps]]></category>

		<guid isPermaLink="false">http://www.appstudio.co.il/?p=2651</guid>
		<description><![CDATA[Just tap the electronic scroll to open and let the iMegillah of Purim envelop you. This free app lets you comfortably read and follow along in Megillat Esther, Esther's Scroll. It includes an easy to read font along with vowels, and provides smooth scrolling for a more enjoyable iMegillah experience.]]></description>
			<content:encoded><![CDATA[<p>Just tap the electronic scroll to open and let the iMegillah of Purim envelop you. This free app lets you comfortably read and follow along in Megillat Esther, Esther's Scroll.  It includes an easy to read font along with vowels, and provides smooth scrolling for a more enjoyable iMegillah experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.appstudio.co.il/portfolio/apps/imegillah/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

