tag:blogger.com,1999:blog-68648530533965322642024-02-08T10:37:29.385-07:00OsmorphisDeveloping software for the iPhone and iPod TouchJEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.comBlogger40125tag:blogger.com,1999:blog-6864853053396532264.post-59416408375683924912010-12-07T20:22:00.001-07:002010-12-07T20:24:00.024-07:00Welcome Back<div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><span style="color: black; font-family: Arial; font-size: 11pt;">Welcome back to me, after a long 10 month silence. I have been extremely busy with our iPhone app, getting a new job, moving, buying a house, settling in, etc. </span></div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><br />
</div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><span style="color: black; font-family: Arial; font-size: 11pt;">The current excitement is completing our long overdue iPhone app. After nearly 2 years in the making, it was finally accepted into the Apple Store. Check it out, if you’re a Colorado traveler:</span></div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><br />
</div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><img height="72.0" src="https://lh4.googleusercontent.com/8-02VltJFY7N5xvX75hIZFpkjcNAxveSyaQAdDWrAdSrpE5I-ciALYjeuy5MKEmkUlGkOX9gXO9P9DvFjjPj2IivCDIbyFfJSUs7vzSWb0kemInAuA" width="72.0" /></div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><span style="color: #000099; font-family: Arial; font-size: 11pt; text-decoration: underline;"><a href="http://www.google.com/url?q=http%3A%2F%2Fitunes.apple.com%2Fus%2Fapp%2Fcolorado-traveler%2Fid404705123%3Fmt%3D8&sa=D&sntz=1&usg=AFQjCNHVOkFbxMd8N0bKzgymcUhV1pfmSw">http://itunes.apple.com/us/app/colorado-traveler/id404705123?mt=8</a></span></div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><br />
</div><div style="direction: ltr; line-height: 1.15; text-indent: 0.0pt;"><span style="color: black; font-family: Arial; font-size: 11pt;">I’ve learned a lot these past 10 months, and hopefully I can share some of that knowledge here on the blog. So until next time!</span><br />
<span style="color: black; font-family: Arial; font-size: 11pt;"><br />
</span></div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-50633926598514624362010-02-21T11:28:00.000-07:002010-02-21T11:28:40.553-07:00Static Libraries in iPhone Projects (Part 3)This is an addendum to my earlier 2-part article on how to create and share static libraries for iPhone projects. <a href="http://osmorphis.blogspot.com/2010/02/static-libraries-in-iphone-projects.html" id="v-x_" title="Part 1">Part 1</a> discusses how to setup Xcode to create a static library target. <a href="http://osmorphis.blogspot.com/2010/02/static-libraries-in-iphone-projects_08.html" id="vfzq" title="Part 2">Part 2</a> discusses how to share a reference to that library from within another project.<br />
<br />
This addendum to address a missing step from part 1. According to Apple documentation, static libraries do not need to be code signed. This is only important if you are an "official" Apple iPhone developer ($99/year).<br />
<br />
<div>To remove code signing, select the library target under Groups & Files > Targets. Double click the target to bring up the info dialog window. Select the Build pane. </div><br />
<div>Scroll down to the Code Signing group. It should look something like this: </div><br />
<div><div id="wg3e" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_760dtsrd6cp_b" style="height: 623.077px; width: 648px;" /> </div>See the highlighted line and how it says "iPhone Developer"? Click on that value and you will get a little menu. Select "Don't Code Sign". </div><br />
<div>That's it! </div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-19947881066717867472010-02-08T19:57:00.000-07:002010-02-08T19:57:35.237-07:00Static Libraries in iPhone Projects (Part 2)<div>This is the second part of a two-part article on how to create and use static library projects in your iPhone apps. In <a href="http://osmorphis.blogspot.com/2010/02/static-libraries-in-iphone-projects.html" id="ot46" title="Part 1,">Part 1,</a> I discussed how to create a static library project, as well as including a test application.<br />
<br />
In this part, I will describe how to include this static library project into other projects. The steps outlined here offer several advantages. One is the ability to load the static library project simply by double-clicking on the project reference in your other project. This brings up a new Xcode window for the library project, where you can browse the code and even make changes. If you do make changes in the static library code, not to worry because when you build your application, it will also build your static library project.<br />
<br />
In order for this convenience to work, though, you must follow these steps closely. Xcode is powerful, but it is also non-intuitive and finicky in some areas.<br />
<br />
In this part, I will continue my example of using my BackgroundTask static library I put together in the first part. This static library is available with its project and source code at the <a href="http://groups.google.com/group/osmorphis/web/BackgroundTask.zip" id="jwfn" title="Osmorphis group">Osmorphis group</a>. I will be "importing" this library in another project I am working on that needs the BackgroundTask functionality.<br />
<br />
So let's begin!<br />
<br />
<h4>Bringing over the static library project </h4><br />
Bring up your client project, the project that wants to use the static library, in Xcode. To bring over the library project, all you need to do is drag the project over. You can do this one of two ways:</div><br />
You can drag the <i>whatever</i>.xcodeproj file (it is really a directory) from the Finder. This is the file to drag over:<br />
<br />
<div id="zlgz" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_722g7263vdc_b" style="height: 158px; width: 241px;" /> </div><br />
<br />
The other option is to drag the project from one Xcode window. This is the root element of the Groups & Files tree:<br />
<br />
<div id="z100" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_723fhqqmqf5_b" style="height: 119px; width: 257px;" /> </div><br />
Where you drag this is the Xcode project of the application that wants to use the library. You can drag and drop anywhere in the Groups & Files tree. When you drop, a dialog sheet comes down asking for the details of what you want to do:<br />
<br />
<div id="pw:c" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_7259gtb4zf2_b" style="height: 374px; width: 394px;" /> </div><br />
Be sure you do <i>not</i> select "Copy items..." and the reference type is selected as "Relative to Project".<br />
<br />
What you'll see after this is a new item in your Groups & Files tree with the same blue "A" icon for Xcode projects. Here is an example of my application that has several static libraries referenced:<br />
<br />
<div id="m3oh" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_726ctvn2hdp_b" style="height: 122px; width: 243px;" /> </div><br />
If you have many of these, you could group them in a folder called "libs" or something like that.<br />
<br />
<h4>Specify the Product </h4><br />
Now you have to tell Xcode what products from this external project you are interested in. Select the library project you just dropped in. If you don't see the "Detail", "Project Find", ... tabs, then you may have your editor window taking up the entire content pane, so drag down the split pane to show:<br />
<br />
<div id="ovuf" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_727hrm2xvcd_b" style="height: 109.009px; width: 648px;" /> </div><br />
As shown above, you want to select the library product, but not the test app.<br />
<br />
<h4>Locate Header Files </h4><br />
You need to tell your application where to find the header files of the referenced library. It would be nice if the reference would be sufficient, but it is not, so you have to muck with compile flags.<br />
<br />
Double-click on the project of your target application. <u>Important: don't click on the root element of the Groups & Files tree. This is not what you want. You want to click on the application in the Targets element of the tree. If you edit the wrong one, you'll be banging your head on the wall for hours with missing header file problems (like I did).</u><br />
<br />
Go to the "Build" Tab.<br />
<br />
Make sure you are editing for all configurations, since the location of the header files won't change, if you use the instructions below.<br />
<br />
We need to edit the "User Header Search Paths" property, so go ahead and start typing this in the search box (or you can hunt for it manually). Double click on the value field. This should bring up a dialog that may contain other entries.<br />
<br />
Add a new entry for your static library. The public header files are stored in a long-winded location, and it depends on whether you're building a Debug or Release build, and if you're building for the simulator or an actual iPhone device. These specifics are encoded in some variables. So copy and paste the following for your new user header search path:<br />
<br />
<span style="font-family: 'Courier New';"><span style="font-size: xx-small;">${PROJECT_DIR}/../<i>staticlib_project</i>/build/${BUILD_STYLE}-${PLATFORM_NAME}/usr/local/include</span><br />
<br />
</span>Replace the "<i>staticlib_project</i>" part with the directory of the static library you are trying to set up. This assumes that your static library project is in a peer directory.<br />
<br />
I have several static libraries referenced in my application, so my user header search paths property looks like this:<br />
<br />
<div id="m2g6" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_728gv5zszc7_b" style="height: 272px; width: 490px;" /> </div><br />
The ${BUILD_STYLE} and ${PLATFORM_NAME} variables will be replaced automatically to match your current build. This is how we can use the same settings for all builds.<br />
<br />
<h4>Setting Linker Flags </h4><br />
While we're in the build properties, we need to add an option to the linker flags: -ObjC. This tells the linker to load all classes and categories from static libraries. If you don't do this, then you may get linker errors.<br />
<br />
Clear out the "user header search" in the search box and type "other linker flags". Add -ObjC to this:<br />
<br />
<div id="cze5" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_729gwj3j5d6_b" style="height: 193px; width: 336px;" /> </div><br />
<h4>Set the Dependency </h4><br />
Now we would like to set a dependency on the library so that it will get compiled when you compile your application. Double-click on the application under Targets, and go to the "General" tab.<br />
<br />
Click on the + button for the Direct Dependencies. Select your new library.<br />
<div><br />
</div><div>You also may have to add the library to the Linked Libraries panel, also found on the "General" tab. Hit the + and select the library. I have seen times where the library is not available to choose. In these cases, drag the .a file from the project down to the "Link Binary With Libraries" section of the target. </div><br />
<h4>Good to Go </h4><div><br />
</div><div>At this point, your static library should be properly referenced. The nice thing about this setup is that your library is built whenever something is changed; no need to switch over to that project to build it separately. But, if you need to look at the source code, simply double-click on the project from your tree and the other project is opened up in a new window. </div><div><br />
</div><div>It is also to step into the source files of your referenced libraries in the debugger. </div><div><br />
</div><div>So stop dropping copies of reusable code into your projects. Build a library and reference them! </div><div><br />
</div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com7tag:blogger.com,1999:blog-6864853053396532264.post-89851285366678653082010-02-01T22:04:00.004-07:002010-02-08T19:58:33.210-07:00Static Libraries in iPhone Projects (Part 1)One of the conclusions I have come to in my year of iPhone programming is this: in order to be successful in the iPhone market, a lone developer has to take advantage of code reuse as much as possible. We part-timer coders don't have time to reinvent the wheel for every project.<br />
<br />
This is why Osmorphis has released a few libraries (frameworks) of reusable, general-use functionality. Things like the <a href="http://osmorphis.blogspot.com/2009/05/background-task-class.html" id="art1" title="BackgroundTask class">BackgroundTask class</a>, the <a href="http://osmorphis.blogspot.com/2009/09/jeson-enhancing-json-syntax.html" id="py33" title="JESON package">JESON package</a>, plus a few others I have not released to the public (I gotta protect <i>some</i> of my "secret" weapons ;-) are all designed to be dropped into a project and used.<br />
<br />
At first, this dropping of code, literally copying the code, worked fine. But I knew this was not a maintainable way to manage code, especially when the number of projects using these packages increased.<br />
<br />
I finally bit the bullet and figured out how to maintain these packages in separate projects, build a static library, and reference them from other projects. This allows me to maintain the source code in one project. The product (the library) is referenced from other projects instead of the source code being copied in. This prevents several versions of the same code scattered throughout your projects.<br />
<br />
(Note that these must be used as static libraries for iPhone development; Apple does not allow custom "frameworks" of shared libraries.)<br />
<br />
In this two-part article, I will share how I do it. I feel this is a fairly cumbersome task, and I am constantly in awe with how both powerful and clunky Xcode is. There may be easier/better ways to do this. If you know how, please comment. I would love to simplify my process.<br />
<br />
If you want to get to the summary of steps, jump to the bottom.<br />
<br />
<h3>Part 1. Creating a Static Library Project </h3><br />
This first part discusses how to create a static library project. I will run through the steps of converting my <a href="http://osmorphis.blogspot.com/2009/05/background-task-class.html" id="dz30" title="BackgroundTask">BackgroundTask</a> project to a proper static library. This project will contain the library itself plus a small test app.<br />
<br />
In the <a href="http://osmorphis.blogspot.com/2010/02/static-libraries-in-iphone-projects_08.html">part 2</a>, I discuss how to reference this library project from another project in order to use it.<br />
<br />
<h4>Create a New Project </h4><br />
From the menu in Xcode, select <u>File > New Project...</u><br />
<br />
Up comes a dialog that looks something like this:<br />
<br />
<div id="fwur" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_708dd28s2d7_b" style="height: 497.435px; width: 648px;" /> </div>You want to select <u>iPhone OS/Application</u>, and then select "<u>Window-based Application</u>". Hit the "<u>Choose...</u>" button, then name and locate your project where ever you see fit.<br />
<br />
For my example, I created a new directory called backgroundtask and named the project the same, backgroundtask.<br />
<br />
Your fresh project will look something like this:<br />
<br />
<div id="qv9_" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_709hdtbw77t_b" style="height: 452.872px; width: 648px;" /> </div><h4>Adding the Library Target </h4>The project we've created so far is for a window-based application, so it is not set up for creating a library. But that's ok; we can use the application as our test app. I'll get to this later. For now, we need to create a new target for our static library.<br />
<br />
Right click on the "<u>Targets</u>" element in the Groups & Files tree, and select <u>Add > New Target...</u><br />
<br />
<div id="kdoy" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_710drb83vdh_b" style="height: 166px; width: 475px;" /> </div><br />
Another dialog will come that looks something like this (your icon for static library may look like a red bullseye):<br />
<br />
<div id="xe7i" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_7114z7mstkg_b" style="height: 497.435px; width: 648px;" /> </div>You want to select <u>iPhone OS/Cocoa Touch</u>, then select the "<u>Static Library</u>" target. Hit "next".<br />
<br />
Enter the name of your library target. You probably want to use the "lib" prefix. For my example, I entered libbackgroundtask.<br />
<br />
After you enter the name, you will be presented with a dialog of properties for this project:<br />
<br />
<div id="hdkr" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_712fh4qbwgf_b" style="height: 683px; width: 608px;" /> </div><h4>Cleaning up the product name </h4><br />
Xcode will actually call your product "lib" + whatever you entered as the name. Which means my product name will be "liblibbackgroundtask". You can see this in the red entries under Products in the image below. I like the "lib" prefix as part of my target, but I want to clean up the product name to remove the extra "lib".<br />
<br />
To do that, we need to make some changes on the properties dialog. If you already closed this, you can always bring it back up by selecting in the Groups & Files tree <u>Targets > libwhatever > Get Info</u>.<br />
<br />
<div id="gyxw" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_713g5x479gx_b" style="height: 204px; width: 430px;" /> </div><br />
This will bring up the properties dialog again. Select the "Build" tab. The property we need to change is the Product Name property. You can find it by typing in the search box. All you need to type is "product n" before it shows up. This is what you'll see:<br />
<br />
<br />
<div id="gcok" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_714hhg7tccp_b" style="height: 683px; width: 608px;" /> </div>For libraries, Xcode prefixes the "lib" for you, so all we have to do is remove the "lib" already there. For me, I will change the Product Name to just "backgroundtask".<br />
<br />
(Now, you might ask: <i>Why didn't you name the target that in the first place?</i> Because there was already a target with that name.)<br />
<br />
<h4>Adding Code to the Library </h4><br />
Now we need to add some code to the library. In my case, and may be for most people, I already have the code. I have it sitting in another application. So I open a Finder window, locate the .h and .m files, and drag them to the Classes folder of the Groups & Files tree.<br />
<br />
This will bring up a dialog asking you for more details what to do with these files:<br />
<br />
<div id="hsz3" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_715hg6qzsfd_b" style="height: 408px; width: 618px;" /> </div><br />
Be sure to select "Copy items into..." because you want this project to "own" the sources to this code from now on. Other projects will merely reference this in the future. Select the libwhatever target to receive these files. The test app will actually link against the library rather than include the sources directly; this will test that we have the library built properly and can be linked.<br />
<br />
<h4>Making things public </h4><br />
Now we should configure which header files are public. These files are distributed with your library. Private header files are not. So select "Targets<i>/</i>libwhatever" from the Groups & Files tree.<br />
<br />
This brings up a window with the files you added to this target. Go to the "detail" tab if it's not already selected. Locate those header files you want to make private and change the role from "project" (the default?) to "public".<br />
<br />
<div id="cpsm" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_716hn8n7vfc_b" style="height: 99px; width: 629px;" /> </div><br />
<h4>Setting Dependencies </h4><br />
Before we can try building this, we need to configure the test app to use the library. Select the application target under "Targets" in the Groups & Files tree. Right click on the target and select <u>Get Info</u>. Go to the General tab.<br />
<br />
Here we need to add our library as both a dependency and a linked library. The first one makes sure the library is built when we build our application. The second one links in the library.<br />
<br />
Click the little + button underneath each section and add the static library.<br />
<br />
<div id="v6du" style="text-align: left;"><div id="yd05" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_720g72n63cm_b" style="height: 323px; width: 436px;" /><br />
<br />
</div></div><br />
<h4>Compiling </h4><br />
Now we can try compiling our project. This should build both the test app and the library. Of course, we haven't done anything with our test app yet, so when you run it, all it does is display a white window.<br />
<br />
To really test your library, you should add some code to the test app that uses/tests the library. I will leave this as an exercise for the reader.<br />
<br />
<h4>What's Next? </h4><br />
At this point, you have a static library project ready to be used in other projects. In part 2 of this article, I will describe the steps to do this. As expected, it's not trivial.<br />
<h3><br />
Summary of Steps </h3>I never remember how to do all the above. The following checklist is a quick list of steps to take to create a static library project. I use this myself to jog my memory what steps need to be done:<br />
<br />
<ol><li> File > New Project..., iPhone OS, Window-based Application </li>
<ol><li> enter name of project </li>
</ol>
<li> Targets > Add New Target..., iPhone OS, Cocoa Touch, Static Library </li>
<ol><li> enter name of library, with "lib" prefix </li>
</ol>
<li> Build tab, search for "product name" </li>
<ol><li> remove extra "lib" prefix from name </li>
</ol>
<li> Copy code files to project </li>
<ol><li> select "Copy items into..." </li>
<li> select library as target </li>
<li> deselect app as target </li>
</ol>
<li> Targets > lib..., "Detail" tab </li>
<ol><li> change role of public header files to "public" </li>
</ol>
<li> Targets > app, Get Info, "General" tab<br />
</li>
<ol><li> add library to dependencies and linked libraries </li>
</ol>
<li> Build and test<br />
</li>
</ol><br />
<h3>Acknowledgments </h3><br />
I used the following web sites to learn how to do this:<br />
<br />
<ul><li> Thanks to "keremk" at <a href="http://www.codingventures.com/2009/04/xcode-templates-for-iphone-static-libraries-with-unit-testing/" id="wcnw" title="http://www.codingventures.com/2009/04/xcode-templates-for-iphone-static-libraries-with-unit-testing/">http://www.codingventures.com/2009/04/xcode-templates-for-iphone-static-libraries-with-unit-testing/</a> </li>
<li> Thanks to "ampatspell" at <a href="http://www.amateurinmotion.com/articles/2009/02/08/creating-a-static-library-for-iphone.html" id="xmx1" title="http://www.amateurinmotion.com/articles/2009/02/08/creating-a-static-library-for-iphone.html">http://www.amateurinmotion.com/articles/2009/02/08/creating-a-static-library-for-iphone.html</a> </li>
</ul>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com1tag:blogger.com,1999:blog-6864853053396532264.post-21624137254613254232009-12-15T21:43:00.002-07:002009-12-16T08:37:36.924-07:00MapKit Span Doubling BugI am currently working on an application that uses the new MapKit API in OS 3.0. Although the feature set is a bit sparse, I have found it useful. I look forward to future added features to this neat package.<br />
<br />
There is one nagging bug, though: sometimes setting the map to a region will end up zoomed out too far. What appears to be happening, and has been confirmed by others in <a href="http://stackoverflow.com/questions/1353849/strange-behavior-of-iphone-mkmapkit" id="i2cv" title="this thread">this thread</a> over at stackoverflow, is that the span values are essentially doubled. A doubled span means a greater area is viewed, equating to a zoomed out view.<br />
<br />
This bug didn't happen all the time, but recently it now happens to me ALL the time on the simulator. Others say the bug persists on the actual device as well.<br />
<br />
Until Apple fixes this bug, I needed to provide a fix to get around this annoying defect. The error seems to be introduced when assigning the region to the map:<br />
<br />
<div style="color: #470084; margin: 0px;"><span style="color: black;">[</span><span style="color: #cb00a2;">self</span><span style="color: black;">.</span><span style="color: #418289;">mapView</span> setRegion<span style="color: black;">:</span><span style="color: #418289;">myRegion</span> animated<span style="color: black;">:</span><span style="color: #cb00a2;">YES</span><span style="color: black;">];</span> <br />
</div><div style="color: #470084; margin: 0px;"><br />
<br />
</div>The hack is to look at the map region after making the assignment. If the span does not equal what you set it to, then divide the original span values by 2.0 and try it again. Since the MapKit code is doubling the values, we will halve the values beforehand to get to the value we want. Idiotic hack, for sure, but gets the job done:<br />
<br />
<div style="color: #470084; margin-left: 0px; margin-right: 0px;"><span style="color: black;">[</span><span style="color: #cb00a2;">self</span><span style="color: black;">.</span><span style="color: #418289;">mapView</span> setRegion<span style="color: black;">:</span><span style="color: #418289;">myRegion</span> animated<span style="color: black;">:</span><span style="color: #cb00a2;">YES</span><span style="color: black;">];</span> <br />
</div><div style="margin-left: 0px; margin-right: 0px;"><br />
</div><div style="color: #008b00; margin-left: 0px; margin-right: 0px;">// did the span get screwed up? <br />
</div><div style="color: #7c20ac; margin-left: 0px; margin-right: 0px;"><span style="color: #cb00a2;">if</span><span style="color: black;">(</span><span style="color: #cb00a2;">self</span><span style="color: black;">.</span><span style="color: #418289;">mapView</span><span style="color: black;">.</span>region<span style="color: black;">.</span>span<span style="color: black;">.</span>latitudeDelta<span style="color: black;"> != </span><span style="color: #418289;">myRegion</span><span style="color: black;">.</span>span<span style="color: black;">.</span>latitudeDelta<span style="color: black;"> ) {</span> <br />
</div><div style="color: #e00500; margin-left: 0px; margin-right: 0px;"><span style="color: #470084;"> NSLog</span><span style="color: black;">(</span>@"Span got doubled, adjusting"<span style="color: black;">);</span> <br />
</div><div style="color: #008b00; margin-left: 0px; margin-right: 0px;"><br />
<br />
</div><div style="color: #008b00; margin-left: 0px; margin-right: 0px;"> // hack to fix span doubling bug <br />
</div><div style="color: #7c20ac; margin-left: 0px; margin-right: 0px;"> MKCoordinateRegion<span style="color: black;"> temp = </span><span style="color: #470084;">MKCoordinateRegionMake</span><span style="color: black;">(</span><span style="color: #418289;">myRegion</span><span style="color: black;">.</span>center<span style="color: black;">, </span> <br />
</div><div style="color: #7c20ac; margin-left: 0px; margin-right: 0px;"><span style="color: #470084;"> MKCoordinateSpanMake</span><span style="color: black;">(</span><span style="color: #418289;">myRegion</span><span style="color: black;">.</span>span<span style="color: black;">.</span>latitudeDelta<span style="color: black;">/</span><span style="color: #4000dd;">2.0</span><span style="color: black;">,</span> <br />
</div><div style="color: #7c20ac; margin-left: 0px; margin-right: 0px;"><span style="color: black;"> </span><span style="color: #418289;">myRegion</span><span style="color: black;">.</span>span<span style="color: black;">.</span>longitudeDelta<span style="color: black;">/</span><span style="color: #4000dd;">2.0</span><span style="color: black;">));</span> <br />
</div><div style="color: #470084; margin-left: 0px; margin-right: 0px;"><span style="color: black;"> [</span><span style="color: #cb00a2;">self</span><span style="color: black;">.</span><span style="color: #418289;">mapView</span> setRegion<span style="color: black;">:temp </span>animated<span style="color: black;">:</span><span style="color: #cb00a2;">YES</span><span style="color: black;">];</span> <br />
</div><div style="margin-left: 0px; margin-right: 0px;">} <br />
</div><div><br />
</div>The nice thing about this hack is that it only takes affect if the bug appears. Should you forget about this hack and Apple has long since fixed the problem, the hack is harmless.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com1tag:blogger.com,1999:blog-6864853053396532264.post-68636726973475975362009-10-31T18:38:00.003-06:002009-10-31T18:49:04.581-06:00A Truly Modal UIAlertViewI don't know why it took me so long to realize this, but UIAlertViews are not modal. Yes, they are modal as far as the UI is concerned, but your code continues running after you call the show method. <div>
</div> <div> I discovered this while making a callback in my <a href="http://osmorphis.blogspot.com/2009/04/tableformeditor-v14-text-field-settings.html" id="wcm7" title="TableFormEditor package">TableFormEditor package</a>. In the callback, the form is asking the delegate "is it ok to save this data?". My delegate takes a quick look, sees something wrong, and fires up a UIAlertView to get the users input if it is ok or not.
However, the [alert show] call came back immediately and the form was given a bogus answer, while the dialog was still waiting for user input. Dang. </div> <div>
</div> <div> After a bit of research, it seems that Mac UI frameworks do not embrace the concept of pure modal dialogs. I've read both sides of the argument, but it really shouldn't be an argument at all. You *should* design your code to not rely on modal behavior and instead make use of the delegate concept, but you *should* also have the ability to do modal if your code warrants it. </div> <div>
</div> <div> Sure, I could rewrite my code to move the logic from the location it belongs over to the delegate, but this creates an unmaintainable mess in my code. This is one case where a modal would really keep things neat and tidy.
To address this in a general way, I created a wrapper class around UIAlertView that shows a modal dialog. The class is called JESAlert. The show method will not return until the user selects a button, and it will return the selected button index. <div>
</div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>- (int) show;
</code></pre> <div>
<div> To simplify things, this class does not allow a delegate, so the init method is similar to the original UIAlertView init but without the delegate parameter. </div> <div>
</div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>- (id) initWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSString*) otherButtonTitles, ...;
</code></pre> <div> <div>
</div> <div> Simply call this init, then call the show method. What it returns is the selected button index. </div> <div>
I also enhanced the UIAlertView interface to allow for an array of otherButtonTitles, instead of just the varargs that is currently supported. I needed this feature once upon a time, so I added it.
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>- (id) initWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitleArray:(NSArray*) otherButtonTitles;
</code></pre> <div> </div>
And lastly, since I am on a <a href="http://osmorphis.blogspot.com/2009/10/jeson-this-is-continuation-of-my-series.html" id="gdcn" title="JESON">JESON</a> kick, I have created a JESON-aware interface. You can define your UIAlertView properties in a JESON file and deploy that as a resource with your application. This removes the typical static text settings from your code and moves it into a JESON file.
</div> <div> To use it this way, simply use the plain init method (or combine alloc and init with a new), and call the showWithJeson: method. The filename is expected to be a resource bundle stored in your application. This will also return the button index. </div> <div>
</div> </div> </div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>JESAlert* alert = [JESAlert new];
int button = [alert showWithFile:@"alert.jes"];
</code></pre> <div> <div> <div>
</div> <div> The JESON file contents look like this: </div> <div>
</div> </div> </div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>alert {
title = "Your alert title"
message = "More details of your message"
cancelButtonTitle = "cancel button title or null"
otherButtonTitles = ["button 1", "button 2"]
}
</code></pre> <div> <div> <div> <p style="MARGIN:0.0px 0.0px 0.0px 0.0px">
</p> </div> The JESON portion of JESAlert is a bit more feature rich than the init approach. You can also run the normal, non-modal version of UIAlertView, but build the properties in a JESON file. Just add the modal = false property. You can also specify a delegate by setting the delegate property. </div> <div>
</div> <div> For example, the old-fashioned way: </div> <div>
</div> </div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"An error"
message:@"Something really bad happened"
delegate:self
cancelButtonTitle:@"Stop doing it"
otherButtonTitles:@"try again", @"try harder", nil];
[alert show];
</code></pre> <div>
</div> <div> And here is how it could be set up in a JESON file: </div> <div>
</div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>alert {
title = "An error"
message = "Something really bad happened"
cancelButtonTitle = "Stop doing it"
otherButtonTitles = ["try again", "try harder"]
delegate = self
modal = false
}
</code></pre> <div> <div>
</div> </div> And accessed in the code like this: <div>
</div> </div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>JESAlert* alert = [JESAlert new];
alert.jesonContext = self;
[alert showWithFile:@"jeson_alert.jes"];
</code></pre> <div> <div> The jesonContext property is needed to handle variable references in your JESON text, like the "self" used above on the delegate property. </div> <div>
</div> <div> The JESON support can be easily disabled if you are not so inclined, as it requires the JESON library available <a href="http://groups.google.com/group/osmorphis/web/jeson.zip" id="y8eq" title="here">here</a>. To disable JESON support, simply comment out the define at the top of the JESAlert.h file. </div> <div>
</div> <div> <pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>//#define USE_JESON
</code></pre> </div> <div>
</div> <div> I have not yet taken the time to create an Xcode project for this, so for now I offer this class as a .h/.m pair of files. The code is available on the Osmorphis group: <a href="http://groups.google.com/group/osmorphis/web/JESAlert-1.0.zip" id="gph2" title="JESAlert-1.0.zip">JESAlert-1.0.zip</a>. </div> <div>
</div>
</div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-54062782514928030182009-10-13T11:42:00.003-06:002009-10-31T18:57:09.718-06:00Variable References in JESON<div>
<div id="erj." style="text-align: left;"><img style="width: 149px; height: 149px;" src="http://docs.google.com/File?id=ddkdktns_545dfp5gpxj_b" /><span style="font-size:6;">JESON</span></div>
This is a continuation of my series on JESON, an enhanced replacement for JSON. The previous articles were:
<ol><li><a title="An introduction to JESON" href="http://osmorphis.blogspot.com/2009/09/jeson-enhancing-json-syntax.html" id="lm7h">An introduction to JESON</a></li>
<li><a title="A quick overview of where to get JESON and how to use it" href="http://osmorphis.blogspot.com/2009/09/using-jeson.html" id="bvqt">A quick overview of where to get JESON and how to use it</a></li>
</ol>
In this part I describe an additional enhancement to JESON. I have been developing and redefining JESON as I go along, so a few things have changed and will continue to change as this specification evolves. These changes, of course, drift farther and farther away from the original JSON syntax, but all for the better.
The following enhancement is variable support in values.
In JSON and JESON, you can assign constant values to keys:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>x = 23
y = 'hello'
z = [1, 2, 3]
</code></pre>
and so on.
But now in JESON, you can assign a variable to a key. This is done by simply giving the name of the variable:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>x = 23
y = x
</code></pre>
This will assign 23 to y. You can also use variable references in array elements:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>x = 23
y = x
z = [x, y]
</code></pre>
Basically, anywhere a value is allowed (in dictionary key assignments and elements of an array), a variable reference can be used.
<h3>Valid key/variable names</h3>
In order for this to work, your variables and dictionary keys cannot look like a constant, meaning:
<ul><li>names cannot be <b><span style="font-family:Courier New;">true </span></b>or <b><span style="font-family:Courier New;">false </span></b>or <b><span style="font-family:Courier New;">null </span></b>or start with a number</li>
<li>names cannot have spaces in them</li></ul>
Variable/key names can be alpha-numerics (a-z, A-Z, 0-9), but can also include "." and "_". The need for "." will be apparent later.
Note that the old JSON key name rules can still be applied, like putting spaces or weird character in key names. But if you do, you cannot reference that key in a value. For example, you can still do the first line, but there is no way to do the second line:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>"my key" = true
x = my key // syntax error
</code></pre>
<h3>Name scoping</h3>
Variables have scope, just like in any programming language. Each nested dictionary forms a context. When trying to resolve a variable, JESON will search upwards through the nested dictionaries. In the following example, x will be assigned 72 because that is the nearest scope for y:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>outer {
y = 23
inner {
y = 72
x = y
}
}
</code></pre>
If you comment out the inner y, then x is assigned 23. JESON will continue up the nested contexts until it finds it. If it doesn't, it uses null for the value.
<h3>Exposing Host Scope</h3>
Scope is not limited to the JESON file itself; context searches can spill out into your host application. In the above example, if there are no y's at any level, then JESON can ask the host application for the variable. To support this, the host application needs to set the hostContext property on the JESON parser object. The value to this property is an object that supports Key-Value coding. You could use self, or even construct a context via JESON, as in this example:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>
// create a parser object
JESON* parser = [JESON new];
// create a dictionary
id context = [parser parseString:@"y='hello'"];
// set that dictionary as our external context
parser.hostContext = context;
// and parse something that references a variable
id root = [parser parseString:@"x = y"];
</code></pre>
This code will assign to root a dictionary with the key "x" set to the value "hello".
The extension to the NSString class has also been extended to support this:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>NSString* jeson = @"x = y";
id root = [jeson parseAsJESON:jeson usingContext:context];
</code></pre>
The beauty of this is a host application can provide himself as the context, and then the JESON has access to all its properties.
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>// set some properties
self.myProperty = somevalue;
self.anotherProperty = anothervalue;
// parse some JESON
parser.hostContext = self;
id root = [parser parseString:@"x = myProperty, y = anotherProperty"];
</code></pre>
As a practical application of this technique, I am using the new TableFormEditor which can have the form described in JESON. I want to edit a form that can have a title that varies depending on the situation. The host application determines the title and puts it in a property for the JESON to reference:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>if(editing) {
self.formTitle = @"Edit data";
} else {
self.formTitle = @"Add data";
}
id root = [parser parseString:myJESON];
</code></pre>
And the JESON text could have something like this:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>showLabels = true
title = formTitle
</code></pre>
</div>
<h3>Variable Paths</h3>
To be consistent with Key/Value Coding, the variable name can also be a path in order to traverse nested contexts and to dig into dictionaries:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>globals {
y = "Hi"
}
outer {
y = 23
inner {
y = 72
x = globals.y
}
}
</code></pre>
Instead of using one of the "local" y values, we pull y out of a different dictionary. You can use this syntax to dive into any dictionary:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>stats {
records {
years {
y2008 {
july { income = 5, expenses = 3 }
august {
income = 4
// expenses are the same as in July
expenses = july.expenses
}
}
}
}
}
income = stats.records.years.y2008.august.income
</code></pre>
Note that the path is relative to where the reference is. JESON will still search up through the nested contexts, but instead of looking for a single key, it is looking for a path. This variable "path" is also supported when accessing host application data.
<div>
</div>
<div>There is one caveat to what is supported, due to the way the nested dictionaries are parsed. You cannot reference a dictionary by name if you are a descendent of it. For example, the key "expenses" above could not reference "y2008.july.expenses" because expenses is a grandchild of y2008. This limitation is because the y2008 dictionary has not been created fully yet, as it is recursively getting built. In most cases, this is not a problem, as the contexts are searched upwards through the ancestors, so there is little reason to name your ancestor.
Many people don't realize that key/value coding also works with arrays. But the key is not applied directly to the array. Instead it is applied to every element in the array and returns an array of those results. For example:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>fields [
{ id = 1 }
{ id = 2 }
{ id = 55 }
]
ids = fields.id
// ids => [1, 2, 55]
</code></pre>
An updated JESON parser has been made available with the features described here. Get it off the Osmorphis group: <a href="http://osmorphis.googlegroups.com/web/jeson.zip?gda=l-UoajsAAADS6jh2Fd4xwR2qjS2wL2J3W6VeovnLjU7ZcMdk5fluWhhTVKjOw4tHiduufFDnxyoGRdr3QrylPkw2aRbXD_gF&gsc=hC-z2QsAAACa6moAfo9YKrRRavDNfdV5">jeson.zip</a>.
<div>
</div>
</div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-30248569348340130292009-10-08T17:45:00.003-06:002009-10-09T13:43:49.751-06:00kaLua<div style="font-family:verdana,helvetica,sans-serif;"> <div> For years I have been searching for the "perfect" scripting language. I started with Unix shells and Tcl, migrated to Python, toyed with Javascript and Groovy, and lately I have ventured into the world of Lua.
To me Javascript is one of the more elegant syntaxes. It is fairly simple with a good balance of words vs. puctuation. However, Javascript is designed for web pages and the various runtimes that are available are rather large and cumbersome. Lua's size is extremely attractive, and I like Lua's simple syntax and no-nonsense approach. </div> <div>
</div> <div> But I felt the language is too wordy. This is one of the turnoffs Ruby has as well. There is a good balance that can be reached between wordy, verbose languages (like Objective-C) and terse, cryptic languages (like Unix shell). I am constantly looking for that balance. Python is close, but I really dislike the "blocking via indent", even after programming in it for years; it never found a place in my heart.
</div> <div> So what's wrong with Lua? Not much, really, as long as you're not looking for a true OO language. But it's not perfect. For starters, Lua denotes blocks via do/end, function/end, and if/then/end keywords. To me, this makes the code too wordy. The density of words over punctuation is too great. I wanted to shift that balance, plus make the syntax a little closer to existing languages.
There are some other constructs in Lua that strike me as odd or "old-fashioned". For example, the [[/]] pair to create multiline strings. I find the Python/Groovy approach of using triple quotes (""" or ''') much more appealing.
</div> <div> So I looked at the Lua parser code and it seemed simple enough. I started tweaking and adding things. Before I knew it, I had changed a great deal of the syntax. </div> <div>
Once I realized I had a new language on my hands, I needed a name. I have come up with "kaLua", which could stand for "Kick Ass" Lua, but it really is just the best I could come up with and still retain the "Lua". I'm all for changing this name. One alternative that stands out is Super<sup>script</sup>. </div> <div>
</div> <div> kaLua is a derivative of Lua and is still very much Lua-like. It would be nice if it did not change existing syntax and merely added to it, but some things had to change. I'll describe these incompatible changes below.
This document summarizes those changes made to Lua to create the kaLua almost-superset. Mind you, these changes come from a syntax snob, and many will dislike these changes. Syntax is a matter of taste; this is my taste. If it's not yours, then move along. I won't be offended.
<h2> Function Blocking </h2> </div> <div style="font-family:verdana,helvetica,sans-serif;"> Functions can be declared like this in Lua:
<blockquote> <span style="font-family:Courier New;">function hello()</span> <span style="font-family:Courier New;">
print('hello world')</span> <span style="font-family:Courier New;">
end</span>
</blockquote>
and they can be declared anonymously (inline) like this:
<blockquote> <span style="font-family:Courier New;">if something then</span> <span style="font-family:Courier New;">
return function () print('hi') end</span> <span style="font-family:Courier New;">
end</span>
</blockquote>
kaLua adds curly brace blocking to function definitions. The above two could be written as:
<blockquote> <span style="font-family:Courier New;">function hello() {</span> <span style="font-family:Courier New;">
print('hello world')</span> <span style="font-family:Courier New;">
}</span> </blockquote>
and
<blockquote> <span style="font-family:Courier New;">if something {</span> <span style="font-family:Courier New;">
return function () { print('hi') }</span> <span style="font-family:Courier New;">
}</span> </blockquote> It does not matter what line the {} characters are on; Lua is fairly insensitive to line breaks as opposed to some scripting languages.
<h2> If/then/elseif/else Blocking </h2>
Blocking for the if/... set of statements is a bit more complex, mainly because the current Lua syntax is somewhat inconsistent. You can have numerous "then" portions but only one "end":
<blockquote> <span style="font-family:Courier New;">if something then</span> <span style="font-family:Courier New;">
do_something()</span> <span style="font-family:Courier New;">
elseif something_else then</span> <span style="font-family:Courier New;">
do_another_thing()</span> <span style="font-family:Courier New;">
elseif something_else_yet then</span> <span style="font-family:Courier New;">
do_that_again()</span> <span style="font-family:Courier New;">
else</span> <span style="font-family:Courier New;">
last_ditch_effort()</span> <span style="font-family:Courier New;">
end</span> </blockquote>
The blocks for each condition are separate contexts. To make this cleaner and clearer, kaLua adds support for braces and removes the useless "then" keyword:
<blockquote> <span style="font-family:Courier New;">if something {</span> <span style="font-family:Courier New;">
do_something()</span> <span style="font-family:Courier New;">
} elseif something_else {</span> <span style="font-family:Courier New;">
do_another_thing()</span> <span style="font-family:Courier New;">
} elseif something_else_yet {</span> <span style="font-family:Courier New;">
do_that_again()</span> <span style="font-family:Courier New;">
} else {</span> <span style="font-family:Courier New;">
last_ditch_effort()</span> <span style="font-family:Courier New;">
}</span> </blockquote>
The braces do not have to appear on the same line or on a different line. Although you can continue to use the old style blocking, you have to be consistent within one if compound statement. In other words, you can't use braces in the if block and use the old style blocking in the else portion.
<h2> While Blocking </h2>
The while loop blocks via a do/end pair:
<blockquote> <span style="font-family:Courier New;">while something_is_true do</span> <span style="font-family:Courier New;">
something()</span> <span style="font-family:Courier New;">
end</span>
</blockquote>
kaLua adds an addition to support braces:
<blockquote> <span style="font-family:Courier New;">while something_is_true {</span> <span style="font-family:Courier New;">
something()</span> <span style="font-family:Courier New;">
}</span> </blockquote>
<h2> Repeat/Until Blocking </h2> Lua creates yet another form of blocking with the repeat/until pair:
<blockquote> <span style="font-family:Courier New;">x = 3</span> <span style="font-family:Courier New;">
repeat</span>
<span style="font-family:Courier New;">print('repeat')</span> <span style="font-family:Courier New;">
x = x - 1</span> <span style="font-family:Courier New;">
until x == 0</span> </blockquote>
kaLua simply adds braces to form the block for consistency. The block creates a new context, and the condition in the until clause does have visibility to that context, even though it is physically outside the block.
<blockquote> <span style="font-family:Courier New;">x = 3</span> <span style="font-family:Courier New;">
repeat {</span> <span style="font-family:Courier New;">
print('repeat')</span> <span style="font-family:Courier New;">
x = x - 1</span>
} <span style="font-family:Courier New;">until x == 0</span> </blockquote>
<h2> Standalone Blocks </h2> Lua uses do/end blocks to create a nested context:
<blockquote> <span style="font-family:Courier New;">x = 'hello'</span>
<span style="font-family:Courier New;">do</span> <span style="font-family:Courier New;">
local x = 23</span> <span style="font-family:Courier New;">
end</span> </blockquote>
kaLua replaces the do/end pair with {}:
<blockquote> <span style="font-family:Courier New;">x = 'hello'</span>
{ <span style="font-family:Courier New;">
local x = 23</span> <span style="font-family:Courier New;">
}
</span> </blockquote> <h2> Function Calls </h2>
Lua supports 3 different syntaxes for making function calls:
<blockquote> <span style="font-family:Courier New;">x = callme("23")</span> <span style="font-family:Courier New;">
x = callme{f="23"}</span>
<span style="font-family:Courier New;">x = callme"23"</span> </blockquote>
Of these, only the first one makes sense. The other two muddle up the language syntax and offer little advantage. I guess they are syntactic sugar, but they don't seem very "sweet" to me. The second two examples above are no longer supported. Only the following is allowed:
<blockquote> <span style="font-family:Courier New;">x = callme("23")</span>
</blockquote>
Because of the additional support for braces in the syntax, the second one conflicts with the updated grammar. The third function call form is just loopy; I hope no one really uses that. </div> <div style="font-family:verdana,helvetica,sans-serif;">
</div> <div style="font-family:verdana,helvetica,sans-serif;"> If you need to pass a table as an argument, surround with parens like you would expect. In other words, function calls <b>always</b> involve parens. To me this is consistent and clean:
<blockquote> <span style="font-family:Courier New;">x = callme({f="23"})</span>
</blockquote>
<h2> Multiline Strings </h2>
Lua supports multiline strings with the [[/]] pair, and also supports nested multiline strings with [=[/]=], [==[/]==], etc pairs:
<blockquote> <span style="font-family:Courier New;">print([[this is</span> <span style="font-family:Courier New;">a
multiline </span> <span style="font-family:Courier New;">string]])</span>
<span style="font-family:Courier New;">print([=[ this is a [==[nested string]==] so there you have it]=])</span> </blockquote>
The use of [[/]] is pretty ugly and uses the bracket characters where they would be best used for indexing. kaLua changes the multiline string to use the triple quote concept from Python and other languages:
<blockquote> <span style="font-family:Courier New;">print("""this is</span> <span style="font-family:Courier New;">a
multiline </span> <span style="font-family:Courier New;">string""")</span>
<span style="font-family:Courier New;">print('''this is</span> <span style="font-family:Courier New;">also a
multi-</span> <span style="font-family:Courier New;">line string''')</span> </blockquote> kaLua gets rid of the nested string format altogether. Its value is very dubious and it is extremely ugly. For an embedded language that prides itself on simplicity, this <i>feature</i> seems unnecessary.
<h2> Comments </h2>
Lua uses the -- characters to denote a single line comment, and --[[/]] for multiline comments:
<blockquote> <span style="font-family:Courier New;">-- this is a comment</span> <span style="font-family:Courier New;">
--[[</span> <span style="font-family:Courier New;">
print("this code is commented out")</span> <span style="font-family:Courier New;">
]]</span> </blockquote> kaLua changes these to more common comment sequences:
<blockquote> <span style="font-family:Courier New;">// this is a comment</span> <span style="font-family:Courier New;">
/*</span> <span style="font-family:Courier New;">print("this code is commented out")</span> <span style="font-family:Courier New;">*/</span> </blockquote> <h2> Operators </h2> Lua uses ~= for "not equals". kaLua adds a more common operator sequence !=
<span style="font-size:85%;">
</span> </div> <h2> Summary </h2> <div style="font-family:verdana,helvetica,sans-serif;"> <span class="Apple-style-span" style="font-family:tahoma,'new york',times,serif;"><span class="Apple-style-span" style=";font-family:verdana,helvetica,sans-serif;font-size:100%;" ><span style="font-size:85%;">That sums up the additions and changes made to the Lua syntax. I have these changes implemented in a version of the library. I really haven't used it much and the code needs some more tweaking. I would like to make kaLua be a true superset of Lua and put back some of the things I removed. The only thing kaLua cannot support is the function call syntax that uses curly braces instead of parens. This is one feature of Lua that won't survive in kaLua.</span></span></span> </div> <div style="font-family:verdana,helvetica,sans-serif;"> <span style="font-size:85%;">
</span> </div> <div style="font-family:verdana,helvetica,sans-serif;"> <span style="font-size:85%;">There are a few other quirks of Lua I don't like, but will require a lot more thought and code mangling. The biggest offender to me is the "method call" syntax:</span> </div> <div style="font-family:verdana,helvetica,sans-serif;"> <span style="font-size:85%;">
</span> </div> <blockquote> <span class="Apple-style-span" style="font-family:'Courier New';">object:method(parms)</span> </blockquote> <div style="font-family:verdana,helvetica,sans-serif;"> <span style="font-size:85%;">
</span> </div> <div style="font-family:verdana,helvetica,sans-serif;"> <span style="font-size:85%;">It's really not that bad, but I find it a little hokey. How else to do it? No idea. This is still better than:</span> </div> <div face="verdana,helvetica,sans-serif"> <span style="font-size:85%;">
</span> </div> <blockquote> <span class="Apple-style-span" style="font-family:'Courier New';">object.method(object, parms)</span> </blockquote> <div face="verdana,helvetica,sans-serif"> <span style="font-size:85%;">It would be preferable that I can call it with a dot instead of the colon and have it just figure it out, and pass object as the self parameter:</span> </div> <div face="verdana,helvetica,sans-serif"> <span style="font-size:85%;">
</span> </div> <blockquote> <span class="Apple-style-span" style="font-family:'Courier New';">object.method(parms)</span> </blockquote> <div style="font-family: verdana,helvetica,sans-serif;"> <span style="font-size:85%;">
</span> </div> <div style="font-family: verdana,helvetica,sans-serif;"> <span style="font-size:85%;">If anyone is interested in getting a copy of kaLua, let me know via a comment or an email. If there is enough demand (which I don't expect), then I can post the code.</span> </div> </div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-66783972662352597492009-09-23T19:47:00.004-06:002009-09-23T20:21:09.663-06:00Using JESON<div> <div style="TEXT-ALIGN:left"> <i style="font-family:Comic Sans MS;"><span style="font-family:Times New Roman;font-size:7;"><img id="ig-:" src="http://docs.google.com/File?id=ddkdktns_546htpzhw62_b" style="WIDTH:149px; HEIGHT:149px" /><span style="font-family:Verdana;">JESON</span></span></i>
</div> In <a href="http://osmorphis.blogspot.com/2009/09/jeson-enhancing-json-syntax.html" id="ru1q" title="part 1">part 1</a> of this series, I introduced JESON, a superset of JSON that adds various syntax enhancements. Some may be appalled that I would dare change JSON, but I based my decision on several factors:
</div>
<div> <ol> <li> JSON's compliance with JavaScript syntax is becoming less an advantage because of the dangers of blindly evaluating JSON source, </li> <li> I don't use JavaScript, so I could care less about maintaining compatibility with it, and
</li> <li> Since I am mostly writing JESON text, I wanted the format to be as simple and visually appealing as possible. </li> </ol>
The enhancements in JESON are summarized again as:
<ol> <li> keys in dictionaries do not need quotes if the word is all alphanumeric characters + '_' </li> <li> single quotes are interchangeable with double quotes </li> <li> the '=' character is interchangeable with the ':' character </li> <li> the ':' or '=' characters are optional </li> <li> Outer object is assumed to be a dictionary if '{' or '[' does not start the text
</li> <li> "()" characters are interchangeable with "{}" </li> <li> commas separating array items and dictionary key/value pairs are optional </li> <li> comments via "//" and "/**/" are supported </li> </ol>
For my JESON implementation, I modified Stig Brautaset's <a href="http://code.google.com/p/json-framework/" id="u62h" title="json-framework">json-framework</a>, version 2.2.1. I mostly changed the parsing routines. I also rearranged some of the files and renamed classes to avoid confusion. Kudos to Stig for his wonderful JSON work.
The JESON parser code and an example application can be fetched from the <a href="http://groups.google.com/group/osmorphis/web/jeson.zip" id="lr8-" title="Osmorphis group">Osmorphis group</a>.
Currently this is an iPhone XCode project, but the JESON parser code should also be usable on the Mac. However, since I don't develop in Objective-C on the Mac, I cannot vouch for that. The project creates a static library, one that is usable in iPhone applications.</div><div>
<h2> Including the JESON library </h2> <div>
</div><div> To use the JESON library in your project, XCode seems to make the process a bit convoluted. Perhaps there are easier ways, but I follow the instructions given here at <a href="http://www.codingventures.com/2009/04/xcode-templates-for-iphone-static-libraries-with-unit-testing/" id="wjz6" title="Coding Ventures">Coding Ventures</a>. Be sure to change your "search for headers" setting to include ../jeson/JESON, which is where the JESON header files are located. </div> <div>
</div> <h2>
</h2><h2> Accessing the JESON code </h2><div>
</div> To access the JESON definitions in your code, you must import the header file:
<span style="font-family:Courier New;">#import "JESON.h"</span>
<h2> Parsing JESON </h2>
The primary use for JESON package is to parse it JESON text. JESON text might be in a file, inside your code, or come from the web. Where it comes from is of no concern to the parser. The JESON parser only parses strings, so wherever it comes from, you have to get it into an NSString object.
There are a couple approaches you can take to parse JESON text. The first way is to directly call the JESON parser:
<span style="font-family:Courier New;">JESON* parser = [JESON new];</span> </div><div><span style="font-family:Courier New;">id root = [parser parseString:myJESONText];</span> </div><div><span style="font-family:Courier New;">[parser release];</span>
What is put into root depends on the JESON text. If the topmost container is a dictionary, then root will be an NSDictionary. If it is an array, then root will be an NSArray. As mentioned in part 1, JESON does not support JESON fragments. The topmost object will be either an array or a dictionary.
If there was an error parsing the JESON text, then parserString: returns nil. In order to get the actual error, look at the error property of the parser:
<span style="font-family:Courier New;">if(root == nil) {</span></div><div><span style="font-family:Courier New;"></span> <span style="font-family:Courier New;"> NSLog("Error parsing JESON: %@", [parser.error localizedDescription]);</span> </div><div><span style="font-family:Courier New;">}</span>
The second way of parsing JESON is via a category extension made to NSString. If you have your JESON text in a NSString object, then simply call the parseAsJESON method to return the root object:
<span style="font-family:Courier New;">NSString* myJESONText;</span> </div><div><span style="font-family:Courier New;">// ....</span> </div><div><span style="font-family:Courier New;">id root = [myJESONText parseAsJESON];
</span>
<b><span style="font-size:130%;">Writing JESON</span></b>
JSON can also be written given a dictionary or an array. Obviously, the objects inside these containers must be compatible with JSON/JESON. Currently, the JESON package does not create JESON syntax; it creates pure JSON. This is a low priority for me at the moment, since I don't have a need to reverse the parse operation and actually write JESON. This will be added later. In the meantime, the write code is essentially the same as what Stig has in his original json-framework package.
<span style="font-family:Courier New;">NSMutableDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:...];</span> </div><div><span style="font-family:Courier New;">JESON* writer = [JESON new];</span> </div><div><span style="font-family:Courier New;">NSString* JESONText = [writer createFromObject:dict];</span></div><div><span style="font-family:Courier New;"></span><span style="font-family:Courier New;">[writer release];</span>
<h2> Some Examples </h2>
The following are some code snippets from the TableFormEditor package which is currently being enhanced to allow configuration via JESON/JSON. Since the TableFormEditor package will accept a dictionary of configuration information, you could also use a plist if you so desire, but I find JESON much more to my liking. As you can see below, it's not a bad format to enter this type of information. Here is an example of how to configure a particular TableFormEditor instance.
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>
title = 'Person Record'
showLabels = true
allowDelete = true
labels { delete = "Delete Record", save = "Save", cancel = "Cancel" }
firstFocusRow = 1
fields [
# fields will be displayed in this order
{
name = "Name"
textfield {
adjustsFontSizeToFitWidth = true
minimumFontSize = 7.0
autocorrectionType = 'No'
autocapitalizationType = 'Words'
text= ''
}
}
{
name = "Age"
textfield {
keyboardType = 'NumberPad'
text = 23
}
}
{
name = "Homepage"
textfield {
// can also use the longer enum name
keyboardType = 'UIKeyboardTypeURL'
autocorrectionType = 'UITextAutocorrectionTypeNo'
autocapitalizationType = 'UITextAutocapitalizationTypeNone'
// some enums can use booleans
clearButtonMode = true
text = ''
}
}
{
name = "Password"
textfield {
secureTextEntry = true
text = ''
}
}
]
</code></pre>
</div> I will discuss the new TableFormEditor in another post; the example above just shows the type of input that is expected. The new initializers for the TableFormEditor class now take a template of type NSDictionary*. The template is the above data, parsed of course. The following code is what reads in the above text from a file and parses it into a NSDictionary root:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>// read the JESON file in
NSDictionary* templ;
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"formTemplate" ofType:@"txt"];
if (filePath) {
NSString *myText = [NSString stringWithContentsOfFile:filePath];
templ = (NSDictionary*) [myText parseAsJESON];
}
</code></pre>
This root is then passed to the TableFormEditor initializer. The initializer then initializes itself based on the key/values above. Before, you had to do this via properties in code. Now it can be done in a config file. Here is a snippet of code that looks at the first 5 settings:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>// get values from template
if(templ) {
id obj;
if(obj = [templ objectForKey:@"title"]) {
self.title = obj;
}
if(obj = [templ objectForKey:@"showLabels"]) {
self.showLabels = [obj boolValue];
}
if(obj = [templ objectForKey:@"labels"]) {
NSDictionary* l = obj;
if(obj = [l objectForKey:@"save"]) {
self.saveButtonLabel = obj;
}
if(obj = [l objectForKey:@"cancel"]) {
self.cancelButtonLabel = obj;
}
if(obj = [l objectForKey:@"delete"]) {
self.deleteButtonLabel = obj;
}
}
if(obj = [templ objectForKey:@"allowDelete"]) {
self.allowDelete = [obj boolValue];
}
if(obj = [templ objectForKey:@"firstFocusRow"]) {
self.firstFocusRow = [obj intValue];
}
}
</code></pre>
As you can see, there is still a fair bit of parsing to do, but this is only written once. The clients of the TableFormEditor just write config files in JESON (or a plist if that's their desire).
In future articles I'll go into more detail of how to use the new TableFormEditor package, and I'll discuss scripting possibilities with JESON. <div>
</div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-89790693572867592342009-09-10T12:55:00.004-06:002009-10-13T11:48:29.999-06:00JESON: Enhancing JSON Syntax<div style="text-align: left;"><img id="d:5z" style="width: 149px; height: 149px;" src="http://docs.google.com/File?id=ddkdktns_545dfp5gpxj_b"><font size="5">JESON</font><br>
</div>
<br>
When I work in Swing/Java, I don't write out all the code to build the components to construct the GUI. How tedious! Instead, I make use of a technology based on <a title="SwiXml" href="http://www.swixml.org/" id="z2t:">SwiXml</a> to describe my GUI layouts via an external description file in XML. <br>
<br>
Since working on the iPhone, I find myself doing similar tedious coding. Even with my own <a title="TableFormEditor" href="http://osmorphis.blogspot.com/2009/04/tableformeditor-v14-text-field-settings.html" id="xn2b">TableFormEditor</a>, I am doing lots boring setup coding that can best be done in a string-based description. I like to call this technique "configuration-based coding". In short, this technique replaces code with a more terse description that achieves the same thing.<br>
<br>
The benefits of using such a technique is that you can tweak your "configuration file" or "script file" without changing your code. This also implications with the iPhone's 3.0 support for downloading software updates inside your app. Apple doesn't prescribe what these downloads are, except that they aren't "code". So configuration files seem like a logical choice here.<br>
<br>
So my desire was something like SwiXml to use on the iPhone. However, I don't want XML; it is a pig to parse and not fun at all to hand-edit. Certainly on the iPhone plists can achieve my requirements. Plists can be persisted to a file and read back in quite easily. Plists also support basic constructs like dictionaries, arrays, strings, etc. But I wanted something more friendly for hand editing. I don't like the clunky interface of the plist editor. So I started looking at JSON.<br>
<br>
<a title="JSON" href="http://www.json.org/" id="by8c">JSON</a> is one of latest developments to gain a lot of hype. The data interchange format JSON (JavaScript Object Notation) started life during the AJAX craze. Many think JSON spells the end for XML. JSON can do many of the things that XML can, but in a simpler, cleaner way. I'm all for anything that would put XML to rest for good. XML is an abomination; the idea is great, the implementation is awful. There are even several decent Objective-C implementations for JSON reading and writing. I'm on the JSON bandwagon. <br>
<br>
Almost.<br>
<br>
As I worked with JSON a little bit, I started to realize that JSON is only marginally better than XML from a syntactical standpoint. I understand JSON is a subset of Javascript expression syntax, and thus its specification is limited to the confines of what Javascript can handle. But this argument is becoming more and more moot given the dangers of actually <i>eval</i>ing JSON.
People are saying you should <b>never, ever </b>do this. (Check out this <a title="blog" href="http://directwebremoting.org/blog/joe/2007/03/05/json_is_not_as_safe_as_people_think_it_is.html" id="v65f">blog article</a>.) I don't use Javascript and probably never will. So why should I suffer through its syntax?<br>
<br>
To address the bad taste JSON leaves in my mouth, I have come up with a set of enhancements to the JSON syntax. I call this "JESON" (I stuck the "E" where I did because "JES" happens to be my initials). JESON can read and write original JSON just fine, but it also supports the syntax enhancements described below. The implementation I have modified is Stig Brautaset's wonderful json-framework package available at <a title="http://code.google.com/p/json-framework/" href="http://code.google.com/p/json-framework/" id="ouf7">http://code.google.com/p/json-framework/</a>. This package has a simple enough parser to allow these changes to be made quite easily.<br>
<br>
So, what's my beef with JSON syntax? There are several minor annoyances, but annoyances nonetheless. JSON incurs plenty of useless noise which I would prefer not to see or type. Let me demonstrate with an example of JSON syntax.<br>
<br>
This example was swiped from the <a title="JSON website example page" href="http://www.json.org/example.html" id="o:zq">JSON website example page</a>:<br>
<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> "menu": {</font><br>
<font face="Courier New"> "id": "file",</font><br>
<font face="Courier New"> "value": "File",</font><br>
<font face="Courier New"> "popup": {</font><br>
<font face="Courier New"> "menuitem": [</font><br>
<font face="Courier New"> {"value": "New", "onclick": "CreateNewDoc()"},</font><br>
<font face="Courier New"> {"value": "Open", "onclick": "OpenDoc()"},</font><br>
<font face="Courier New"> {"value": "Close", "onclick": "CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
<br>
JSON syntax violates several of my syntax rules I apply to good languages. The first violation is this syntax rule: "Don't require syntactical elements that serve no purpose".<br>
<br>
I am a minimalist when it comes to syntax. Less is better. You have to admit when looking at the above example, JSON has <b>lots </b>of punctuation. But is it all necessary? <br>
<br>
According to the spec, a dictionary key must always be a quoted string. Why? Unless the key can be anything but a string, what is the point of the quotes? For <b>most </b>needs, the key is always an identifier, an alphanumeric word. Requiring the quotes here serves no purpose. And the busy little tick marks make it hard to quickly discern between the keys and values.<br>
<br>
To fix this, JESON makes the quotes on the keys optional:<br>
<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">menu</b>: {</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">id</b>: "file",</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);"> value</b>: "File",</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);"> popup</b>: {</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">menuitem</b>: [</font><br>
<font face="Courier New"> {<b style="color: rgb(255, 0, 0);">value</b>: "New", <b style="color: rgb(255, 0, 0);">onclick</b>: "CreateNewDoc()"},</font><br>
<font face="Courier New"> {<b style="color: rgb(255, 0, 0);">value</b>: "Open", <b style="color: rgb(255, 0, 0);">onclick</b>: "OpenDoc()"},</font><br>
<font face="Courier New"> {<b style="color: rgb(255, 0, 0);">value</b>: "Close", <b style="color: rgb(255, 0, 0);">onclick</b>: "CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
<br>
To me, this one little change makes a big difference. I find this cleaner and easier to read. If your key happens to have spaces or weird characters in it, then you will have to keep the quotes there.<br>
<br>
Here is another one of my rules of a good language: "Minimize shifted characters as much as possible".<br>
<br>
I type a lot. A LOT. By the end of the day, my wrists and fingers are pretty stressed. Thus this rule is designed to minimize moving the fingers over to that shift key. Typing CamelCase code all day long can really kill me. So in the context of JSON, I have two problems: the colons and the double quotes.<br>
<br>
Using a colon for assignment is certainly non-intuitive. The predominant operator for assignment in most modern languages is the equal sign. The '=' character has more "width", and therefore it is easier to see than the tiny colon. And best of all, the '=' requires no shift to type.<br>
<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> menu<b style="color: rgb(255, 0, 0);">=</b> {</font><br>
<font face="Courier New"> id<b style="color: rgb(255, 0, 0);">=</b> "file",</font><br>
<font face="Courier New"> value<b style="color: rgb(255, 0, 0);">=</b> "File",</font><br>
<font face="Courier New"> popup<b style="color: rgb(255, 0, 0);">=</b> {</font><br>
<font face="Courier New"> menuitem<b style="color: rgb(255, 0, 0);">=</b> [</font><br>
<font face="Courier New"> {value<b style="color: rgb(255, 0, 0);">=</b> "New", onclick<b style="color: rgb(255, 0, 0);">=</b> "CreateNewDoc()"},</font><br>
<font face="Courier New"> {value<b style="color: rgb(255, 0, 0);">=</b> "Open", onclick<b><span style="color: rgb(255, 0, 0);">=</span></b> "OpenDoc()"},</font><br>
<font face="Courier New"> {value<span style="color: rgb(255, 0, 0);">=</span> "Close", onclick<b style="color: rgb(255, 0, 0);">=</b> "CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
<br>
Now let's look at the quotes. Since JSON has no distinction between characters and strings, we can optionally support single quotes. Some may like the bolder style of double quotes, and even I prefer them sometimes when I want them to stand out more, but there is no reason not to support single quotes. And single quotes require no shift.<br>
<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> menu= {</font><br>
<font face="Courier New"> id= <b style="color: rgb(255, 0, 0);">'</b>file<span style="color: rgb(255, 0, 0);">'</span>,</font><br>
<font face="Courier New"> value= <span style="color: rgb(255, 0, 0);">'</span>File<span style="color: rgb(255, 0, 0);">'</span>,</font><br>
<font face="Courier New"> popup= {</font><br>
<font face="Courier New"> menuitem= [</font><br>
<font face="Courier New"> {value= <span style="color: rgb(255, 0, 0);">'</span>New<span style="color: rgb(255, 0, 0);">'</span>, onclick= "CreateNewDoc()"},</font><br>
<font face="Courier New"> {value= <span style="color: rgb(255, 0, 0);">'</span>Open<span style="color: rgb(255, 0, 0);">'</span>, onclick= "OpenDoc()"},</font><br>
<font face="Courier New"> {value= <span style="color: rgb(255, 0, 0);">'</span>Close<span style="color: rgb(255, 0, 0);">'</span>, onclick= "CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
I left some double quotes in the example to show they can be mixed. You can't mix them on the same string, though.<br>
<br>
Hey, now it's looking better. But I'm looking at rule 1 again (no useless characters) and I see 2 more useless characters. The = character, which I so triumphantly argued for, now looks superfluous. But you might like them, you might not. I prefer to not use them for assigning a dictionary or array, but to use them for simple key/value pairs inside a dictionary.<br>
<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">menu {</b></font><br>
<font face="Courier New"> id='file',</font><br>
<font face="Courier New"> value='File',</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">popup {</b></font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">menuitem [</b></font><br>
<font face="Courier New"> {value='New', onclick="CreateNewDoc()"},</font><br>
<font face="Courier New"> {value='Open', onclick="OpenDoc()"},</font><br>
<font face="Courier New"> {value='Close', onclick="CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
<br>
<br>
The other useless characters are the commas. They add no value to the parser, so they are strictly visual. Thus, JESON makes them optional. To me, they help separate key/value pairs when they are all in the same line, but commas are worthless when elements are separated across lines. My preference is to remove the commas between those elements one their own line, but use commas between elements that are in the same line:<br>
<br>
<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> menu {</font><br>
<font face="Courier New"> id='file'</font><br>
<font face="Courier New"> value='File'</font><br>
<font face="Courier New"> popup {</font><br>
<font face="Courier New"> menuitem[</font><br>
<font face="Courier New"> {value='New', onclick="CreateNewDoc()"}</font><br>
<font face="Courier New"> {value='Open', onclick="OpenDoc()"}</font><br>
<font face="Courier New"> {value='Close', onclick="CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font></blockquote>
<br>
One change I made to Stig's JSON implementation I modified was to remove support for "fragments", which are not strict JSON anyway, and comments in the code alluded that it was a deprecated feature. With fragments removed, JESON must begin with either a dictionary or an array, nothing else. The majority of the JSON/JESON text I use has a dictionary as the outer object. I wanted that to be the default so I didn't need the outer {} characters. I enhanced JSON to assume the object is a dictionary if '{' or '[' were not the first non-whitespace characters. Thus, the following is exactly the same as the above, only a little cleaner:<br>
<br>
<blockquote><font face="Courier New">menu {</font><br>
<font face="Courier New"> id='file'</font><br>
<font face="Courier New"> value='File'</font><br>
<font face="Courier New"> popup {</font><br>
<font face="Courier New"> menuitem[</font><br>
<font face="Courier New"> {value='New', onclick="CreateNewDoc()"}</font><br>
<font face="Courier New"> {value='Open', onclick="OpenDoc()"}</font><br>
<font face="Courier New"> {value='Close', onclick="CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
<br>
Man, that is looking sweet. It is a far cry better than the noisy original, which I'll put up again just so you can compare:<br>
<blockquote><font face="Courier New">{</font><br>
<font face="Courier New"> "menu": {</font><br>
<font face="Courier New"> "id": "file",</font><br>
<font face="Courier New"> "value": "File",</font><br>
<font face="Courier New"> "popup": {</font><br>
<font face="Courier New"> "menuitem": [</font><br>
<font face="Courier New"> {"value": "New", "onclick": "CreateNewDoc()"},</font><br>
<font face="Courier New"> {"value": "Open", "onclick": "OpenDoc()"},</font><br>
<font face="Courier New"> {"value": "Close", "onclick": "CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New"> }</font><br>
<font face="Courier New">}</font><br>
</blockquote>
One other enhancement in JESON is to make () synonymous with {}. <br>
<br>
<blockquote><font face="Courier New"> menu<b><span style="color: rgb(255, 0, 0);">(</span></b></font><br>
<font face="Courier New"> id='file'</font><br>
<font face="Courier New"> value='File'</font><br>
<font face="Courier New"> popup<b style="color: rgb(255, 0, 0);">(</b></font><br>
<font face="Courier New"> menuitem[</font><br>
<font face="Courier New"> {value='New', onclick="CreateNewDoc()"}</font><br>
<font face="Courier New"> {value='Open', onclick="OpenDoc()"}</font><br>
<font face="Courier New"> {value='Close', onclick="CloseDoc()"}</font><br>
<font face="Courier New"> ]</font><br>
<font face="Courier New"> <b style="color: rgb(255, 0, 0);">)</b></font><b style="color: rgb(255, 0, 0);"><br>
<font face="Courier New">)</font></b>
<br>
</blockquote>
Now some of those dictionaries look like function calls. Why would I want this? I have a vision of a lightweight scripting language based on the JESON syntax. Consider the following:<br>
<br>
<blockquote style="font-family: Courier New;"> tableViewController {<br>
if [x == true] then {<br>
type='grouped' <br>
doSomething(var='value')<br>
}<br>
else { <br>
type = 'ungrouped' <br>
doSomethingElse(var1='value1', var2='value2')<br>
}<br>
}<br>
</blockquote>
<br>
Kinda sorta looks like code, doesn't it? But it is actually valid JESON. The original JSON would look like this:<br>
<br>
<blockquote><span style="font-family: Courier New;">{</span><br style="font-family: Courier New;">
<span style="font-family: Courier New;">"tableViewController" : {</span><br style="font-family: Courier New;">
<span style="font-family: Courier New;"> "if" : ["x" == true], "then" : </span><span style="font-family: Courier New;"> { "type" : "grouped", "doSomething" : { "var":"value"} },</span><br style="font-family: Courier New;">
<span style="font-family: Courier New;"> "else" : { "type" : "grouped", "doSomethingElse" : { "var1":"value1", "var2":"value2"} }</span><br style="font-family: Courier New;">
<span style="font-family: Courier New;">}</span><br style="font-family: Courier New;">
<span style="font-family: Courier New;">}</span><br>
</blockquote>
<br>
The usefulness of this may seem dubious, but I will discuss this in part 3.<br>
<br>
One other thing that JSON doesn't support is comments. For any hand-edited configuration language, comments are mandatory, so JESON adds support for the basic // and /**/ formats:<br>
<blockquote style="font-family: Courier New;"> <b><span style="color: rgb(255, 0, 0);">// this is a menu</span></b><br>
menu(<br>
id='file'<br>
value='File'<br>
popup(<br>
menuitem[<br>
<b><span style="color: rgb(255, 0, 0);">// removed this one for now</span></b><br>
<b><span style="color: rgb(255, 0, 0);">/*{value='New', onclick="CreateNewDoc()"}</span></b><b><span style="color: rgb(255, 0, 0);">*/</span></b><br>
{value='Open', onclick="OpenDoc()"}<br>
{value='Close', onclick="CloseDoc()"}<br>
]<br>
)<br>
)<br>
</blockquote>
<br>
So that's it for JESON. Not much, really, but to me it makes it much easier to write and read. Here is a summary of all the enhancements JESON makes to the JSON syntax:<br>
<br>
<ol><li>keys in dictionaries do not need quotes if the word is all alphanumeric characters + '_'</li>
<li>single quotes are interchangeable with double quotes</li>
<li>the '=' character is interchangeable with the ':' character</li>
<li>the ':' or '=' characters are optional</li>
<li>Outer object is assumed to be a dictionary if '{' or '[' does not start the text<br>
</li>
<li>"()" characters are interchangeable with "{}"</li>
<li>commas separating array items and dictionary key/value pairs are optional</li>
<li>comments via "//" and "/**/" are supported<br>
</li>
</ol>
<br>
In part 2 of this series, I'll discuss where to get the JESON parser and how to use it.<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-43873209715125264712009-08-03T21:50:00.002-06:002009-08-03T21:53:22.273-06:00Assigning DelegatesKind reader Demitri Muna pointed out a flaw in my <a href=http://osmorphis.blogspot.com/2009/04/tableformeditor-v14-text-field-settings.html id=bn_k title="TableFormEditor package">TableFormEditor package</a>. I stumbled into a trap I fear many newbie Objective-C programmers also fall into: that of retaining delegates. It is a two-line change, but I feel this issue is important enough to write about it.<br> <br> The basic problem is a retain cycle which results in a memory leak. This has been fairly well documented in this <a href=http://stackoverflow.com/questions/918698/why-are-objective-c-delegates-usually-given-the-property-assign-instead-of-retain/918732 id=p3.1 title=thread>thread</a>, but I will go into more detail here in the context of the TableFormEditor.<br> <br> In this context, there are 2 actors involved:<br> <br> <ol> <li> the client object<br> </li> <li> the TableFormEditor object </li> </ol> <br> When the client object creates a TableFormEditor instance, it needs to pass a delegate to handle the various callbacks. Typically, but not required, the delegate is the client object (i.e. self).<br> <br> The TableFormEditor has this declaration in its .h file:<br> <br> <pre style="BORDER:1px dashed #999999; FONT-FAMILY:Andale Mono,Lucida Console,Monaco,fixed,monospace; COLOR:#000000; BACKGROUND-COLOR:#eeeeee"><font size=2>@property (nonatomic,retain) id <TableFormEditorDelegate> delegate; </font></pre> <br> <br> So what this means is that the client has a retain on the TableFormEditor (because it created it via [alloc]), and the TableFormEditor instance has a retain on the client (via the "retain" keyword in the @property declaration).<br> <br> This is the dreaded A -> B and B -> A scenario described in the Stack Overflow thread mentioned above. When you are in this situation, A and B will never go away because B has a retain on A that will not release until B goes away. But B won't go away until A goes away. Result: memory leak!<br> <br> However, all is not lost if you followed the pattern I have in the <a href=http://groups.google.com/group/osmorphis/web/TableFormEditorExample.zip id=gic4 title="TableFormEditor example">TableFormEditor example</a>. In the example, I do not keep the TableFormEditor object around. As soon as I push it on the Navigation Controller's stack, I release it:<br> <br> <br> <pre style="BORDER:1px dashed #999999; FONT-FAMILY:Andale Mono,Lucida Console,Monaco,fixed,monospace; COLOR:#000000; BACKGROUND-COLOR:#eeeeee"><font size=2>// stick the editor onto the navigator's stack
[self.navigationController pushViewController:form animated:YES];
// release the form since the navigator retained it
[form release]; </font></pre> <br> <br> But, <b>if you retain the pointer to the TableFormEditor</b>, like keeping it in an instance variable, then you will likely end up with a memory leak.<br> <br> Thus I have released <a href=http://groups.google.com/group/osmorphis/web/TableFormEditorExample.zip id=tfky title="version 1.6">version 1.6</a> of the TableFormEditor class to make this change:<br> <br> <pre style="BORDER:1px dashed #999999; FONT-FAMILY:Andale Mono,Lucida Console,Monaco,fixed,monospace; COLOR:#000000; BACKGROUND-COLOR:#eeeeee"><font size=2>@property (nonatomic,assign) id <TableFormEditorDelegate> delegate; </font></pre> <br> <br> This simply assigns the pointer without bumping up the retain count. This breaks the cycle and the potential for memory leaks.<br> <br> For more information on retain cycles and how to prevent them, I urge you to check out this blog article at <a href=http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html id=sv97 title="Cocoa With Love">Cocoa With Love</a>.<br> <br> <br> <br> <br> <br>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-5629653721153056632009-07-06T21:40:00.004-06:002009-07-07T13:31:26.560-06:00Changing the Accessory ViewIn my application, I want to replace the button in the accessory view area of a table cell with my own button. I want it to look like this:
<div id="k7ld" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_470d6mcrgdn_b" style="width: 309px; height: 70px;" /> </div>
Clicking on the cell should produce the callback tableView:(UITableView *) aTableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath. However, when the pencil icon is hit, I want it to do a different callback.
I didn't want to make a custom table cell class, and from reading the documentation, it appeared relatively straight forward to use the existing table cell class. All I had to do was set the cell property accessoryView to something else. Here is what the SDK documentation says:
<blockquote> <span style="font-family:Courier New;">@property(nonatomic, retain) UIView *accessoryView
</span><u>Discussion</u>
If the value of this property is not nil, the UITableViewCell class uses the given view for the accessory view and ignores the value of the accessoryType property. The provided accessory view can be a framework-provided control or label or a custom view. The accessory view appears in the the right side of the cell. If the cell is enabled (through the UIView property userInteractionEnabled) , the accessory view tracks touches and, if tapped, sends the accessory action message set through the accessoryAction property.
</blockquote>
Ok, sounds simple enough, so I went ahead and coded up what I thought was a trivial solution. I picked a UIImageView to put into the accessoryView. I was careful about setting the userInteractionEnabled flag and everything. Here is the snippet of code I came up with (which belongs in the cellForRowAtIndexPath method, in the case we have to create a new UITableCell object):
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>// stick the pencil icon on the accessory view
UIImageView* pencil = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon-pencil.gif"]];
pencil.userInteractionEnabled = YES;
pencil.frame = CGRectMake(0, 0, 15, 15);
cell.accessoryView = pencil;
cell.accessoryAction = @selector(didTapEditButton:); </code></pre>
Well, this didn't work. All taps on the image produced the didSelectRowAtIndexPath callback.
I re-read the documentation on accessoryView. That last sentence mentions the accessoryAction property, so I thought I should take a peek at that:
<blockquote> <span style="font-family:Courier New;">@property(nonatomic) SEL accessoryAction
</span><u>Discussion</u>
If you specify a selector for the accessory action, a message is sent only if the accessory view is a detail disclosure button—that is, the cell's accessoryType property is assigned a value ofUITableViewCellAccessoryDetailDisclosureButton. If the value of this property is NULL, no action message is sent.
The accessory view is a UITableViewCell-defined control, framework control, or custom control on the right side of the cell. It is often used to display a new view related to the selected cell. If the accessory view inherits from UIControl, you may set a target and action through the addTarget:action:forControlEvents: method. See accessoryView for more information.
</blockquote>
Hmmm. That very first sentence says I can't do this with a custom view. But the next paragraph states I can just use the addTarget:action:forControlEvents: method. (Then it makes a circular reference back to accessoryView for more info, which doesn't offer more info.)
But a UIImageView is not derived from UIControl, so that is not available.
The solution to this mess is to use a UIButton instead of a UIImageView. UIButtons are UIControls, so the final code looks like this:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>// stick the pencil icon on the accessory view
UIButton* pencil = [UIButton buttonWithType:UIButtonTypeCustom];
[pencil setImage:[UIImage imageNamed:@"icon-pencil.gif"] forState:UIControlStateNormal];
pencil.frame = CGRectMake(0, 0, 15, 15);
pencil.userInteractionEnabled = YES;
[pencil addTarget:self action:@selector(didTapEditButton:) forControlEvents:UIControlEventTouchDown];
cell.accessoryView = pencil; </code></pre>
This time it works. I get the desired callback when the pencil icon is touched. The summary is: use a UIControl based widget in the accessoryView, and ignore the accessoryAction property.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-40322761228886848212009-06-09T21:37:00.002-06:002009-06-09T21:38:19.151-06:00Java on the iPhone?Is it possible? Can you run Java on the iPhone? Well, no, at least not at this time. Perhaps never, due to the rules Apple have in place disallowing interpreted languages from operating on the iPhone.
This is a real shame because quite frankly, Objective-C is not an easy language to work with. And since it is the only language we have to work on for the iPhone, our hands are extremely tied. (One could argue that Objective-C++ allows C++, but in my opinion, this is a much uglier situation than just coding in Objective-C.)
I am a former Java coder. Java may not be the most enabling language (think Python or Groovy), but the grammar is clean and simple and arguments about Java being too verbose are lost when comparing it to Objective-C.
I like the power of the Cocoa-Touch run-time environment. However, the vehicle to get to that power (Objective-C) is a nightmare. Objective-C is clunky, verbose, inconsistent, and archaic. It is loosely based on SmallTalk, a relatively unused language in the industry. There's a reason for that.
To me, doing anything in Objective-C is painful. Take the mundane task of creating a dictionary and adding a key/value pair to it. In Objective-C, it would look something like this:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">NSMutableDictionary* dict;
dict = [[NSMutableDictionary alloc] initWithCapacity:3];
[dict addObject:@"Some data" forKey:@"key"];
</span></pre>
I have many issues with this code:
<ol> <li> Why does Objective-C insist of dealing with pointers? Since you can't instantiate an object on the stack like you can in C++, having to specify the "*" character is superfluous. The fact that these are pointers should be hidden, as they are in Java. In the rare cases you need to actually refer to the class name and not the pointer, use some other syntax.
</li> <li> The [object method] call syntax is really whacked. My opinion is that this is not an intuitive syntax, nor is it easy to read or write. It is nearly impossible to visually parse, especially with nested calls.
</li> <li> Semicolons? Come on. There is no reason why a language parser cannot figure out the end of a statement. These are artifacts from the days of Pascal and C when they didn't know better. Tcl, Groovy, Python, Ruby, JavaScript, et al prove that semicolons are extraneous syntax fluff. It's a shame that most programmers accept them as the de facto for languages, when in fact they indicate a poorly designed grammar.
</li> <li> Look how verbose and awkward it is to add a single element to the dictionary. I get carpal tunnel syndrome just reading Objective-C code. Objective-C forces you to use positional arguments <b>and </b>named arguments at the same time. If it wasn't for Xcode helping to write Objective-C, it would be a horrid language to type.
</li> <li> I miss the commas between arguments. These are not needless syntactical fluff, as the "*" and ";" characters are. Commas help visually separate arguments. Without them, the args all blend together and make it hard to read.
</li> <li> What's with the @ characters in front of strings? I understand they are trying to differentiate between C-style string constants and NSString constants, but why give the simpler syntax to C? I have <b>never </b>used a C-style string in an Objective-C program. I would have made "string" automatically be an NSString constant, and if you want a dinosaur C-style string, then use @"string".
</li> </ol>
Okay, that's six major complaints in just 3 lines of code. This doesn't even go into my other major beefs, such as separate files for class definitions and declarations, the @property/@synthesize malarkey, the use of "@end" as a block terminator, etc.
Java can do the same task a little better and with a much cleaner syntax:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">HashMap dict;
dict = new HashMap(3);
dict.put("key", "Some data");
</span></pre>
It still has those dumb semicolons, but this is still a major improvement.
I know all this bitching and moaning doesn't accomplish much. Objective-C is the tool we have to work with on iPhone development. There is nothing you can do about it. Adapt and move on.
And adapt I did. I tolerated Objective-C's quirks for months. But I always thought about how much easier and productive it would all be in another language. I couldn't let it go.
Then I came up with an idea: What if I just used the <b>syntax</b> of Java, and not the Java run-time environment? What if I wrote a translator, one that translated Java code into Objective-C? How hard would it be?
I think this is quite possible, as long as you lay down a few ground rules. I have accumulated a fair number of these ground rules and revelations from tinkering with prototypes. The above Objective-C code could look like this in Java syntax:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">NSMutableDictionary dict;
dict = NSMutableDictionary.alloc().initWithCapacity(3);
dict.addObject("Some data", forKey="key");</span></pre>
Notice a few things different? But some things are the same. The most important aspect of this is how we pass parameters. The first parameter is passed like normal, but all subsequent parameters are passed as if they are keyword parameters (ala Python). Although this is parseable Java syntax, it wouldn't compile. But it can be translated to Objective-C very easily.
The whole idea is boiled down to this:
In Xcode, write your iPhone software using Java syntax. Calls to the Objective-C runtime and Cocoa Touch are pretty much the same. There are no separate .h and .m files, just .java files. Then run the Java code through a translator that generates the Objective-C .h and .m files, which then get compiled.
Xcode provides the ability to run preprocess steps in a build operation. So you could set up your builds to translate your Java source to Objective-C, then the normal build process would take it from there. Another benefit is that Xcode will think you're typing in Java code (because you are, sort of), so you will get all the nice keyword highlighting and other editor shortcuts.
This idea is not limited to Java. Although Python does not have static typing, the <a href="http://shed-skin.blogspot.com/" id="a8:n" title="ShedSkin">ShedSkin</a> project proves that you can translate Python to C++, so it is likely possible to also translate Python to Objective C.
But this situation is not perfect. For starters, any compile errors in the Objective-C source will have to be corrected in the original Java source. Unless you want to abandon your original source, you should never edit the generated Objective-C source code. Runtime debugging will have to be in Objective-C.
For some, these problems may be enough to warrant this as an exercise in futility. I will reserve judgment until trying it in production software rather than just in tinkering.
This introduction is just to whet your appetite of the possibilities. This project I call "Typhoon". Typhoon will comprise the set of language translators and any additional run-time support necessary.
In future articles, I will describe some of the ideas of Typhoon. I invite readers to leave comments on what you think about this idea. Is it worth pursuing? Or is it an idiotic waste of time? Please let me know.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com11tag:blogger.com,1999:blog-6864853053396532264.post-65964105617652878932009-06-04T21:05:00.004-06:002010-01-30T12:04:42.191-07:00Multiple Parameters to ThreadsThis hint is fairly trivial, but I was surprised I could not find any information on this little "problem". I wanted to pass more than one parameter to a thread entry method. The standard NSThread class only supports 0 or 1 parameter to be passed, as can be seen in this initializer:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
</code></pre><i> </i><br />
Another way of starting a thread is with the method:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
</code></pre><br />
But as you can see, this has the same limitation. The object parameter can be nil or some other parameter, but at most 1 parameter can be passed. Even the more modern NSOperation class has this same limitation and its remedy is pretty much the same as described here. There are two ways I see to overcome this limitation. One is more complicated than the other, but I will present both. <span style="font-size: 130%;"> </span><br />
<br />
<span style="font-size: 130%;">Subclassing NSThread</span><br />
<br />
The more complicated way is to subclass the NSThread class and override the main method to be your thread entry point. Since you create your own class, your initializer can accept any number of parameters, which you assign to instance variables. Then the main method can easily access this data:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
@interface MyThread : NSThread
{
NSString* data1;
NSInteger data2;
}
- (id) initWithData1:(NSString*) data1 andData2:(NSInteger) data2;
- (void) main;
@end
@implementation MyThread
- (id) initWithData1:(NSString*) data1 andData2:(NSInteger) data2
{
if((self = [super init])) {
// save off our parameters
self.data1 = data1;
[self.data1 retain];
self.data2 = data2;
}
return self;
}
- (void) main
{
// no need to call [super main], as per the Apple reference docs
// do whatever your thread needs to do
}
- (void) dealloc
{
[data1 release];
}
@end
</code></pre><br />
In order to kick off this thread, you do something like this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
// initialize it, passing all your parameters
MyThread* thread = [[MyThread alloc] initWithData1:@"hello there" andData2:23];
// now start it
[thread start];
// done with it
[thread release];
</code></pre><br />
As you can see, this can be a bit involved, forcing you to create a new class, but it gets the job done. <span style="font-size: 130%;"> </span><br />
<br />
<span style="font-size: 130%;">Stuffing Parameters</span><br />
<br />
The other way is simpler, but at the same time a little clunkier. This way uses the simple initializer or the detach method as mentioned above. The way to get multiple parameters passed is to cheat: we pass a single container that holds all our parameters. Since this parameter is defined as id, it can be anything (as long as it is an object and not a primitive type). The perfect container is an NSArray. However, this is where things get a little clunky. First you have to create the array and populate it with your data. Worse is the fact that you can only put class objects into the array; scalars like integers will have to be converted to an object before adding.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
// fire up a thread
[NSThread detachNewThreadSelector:@selector(myMain:)
toTarget:self
withObject:[NSArray arrayWithObjects:@"hello there",
[NSNumber numberWithInt:23], nil]];
</code></pre><br />
And then your thread entry method must pull the parameters back out of the array:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
- (void) myMain:(NSArray*) parameters
{
NSString* data1 = [parameters objectAtIndex:0];
NSInteger data2 = [(NSNumber*) [parameters objectAtIndex:1] intValue];
// the rest ...
}
</code></pre><br />
Neither of these two solutions are perfect. The best solution, of course, is to write your thread code such that it doesn't need more than one parameter, but sometimes this is unavoidable. If any readers out there have any other ideas to solve this, I would love to hear them!JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-42553889019312616002009-05-29T19:40:00.002-06:002009-05-29T19:42:17.581-06:00Trapping the UINavigationBar Back Button (part 3)I have covered the topic of trapping the back button in order to do something. These previous forays are <a href="http://osmorphis.blogspot.com/2009/03/trapping-uinavigationbar-back-button.html" id="yqh0" title="part 1">part 1</a> and <a href="http://osmorphis.blogspot.com/2009/03/trapping-uinavigationbar-back-button_11.html" id="vr-g" title="part 2">part 2</a>. I had implemented my solution from part 2, and it is working well. However, I am always on the look out for a better, cleaner solution.
Just recently, an anonymous commenter pointed out something I had not noticed before: the UINavigationBarDelegate prototype has a method called navigationBar:shouldPopItem: It is called just before the item is popped. If it returns NO, then the pop won't actually happen. But this can be the perfect way to insert some logic before the pop happens (and return YES at the end).
Here is how you would implement your back-button press event logic:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">- (BOOL)
navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
//insert your back button handling logic here
// let the pop happen
return YES;
} </span></pre>
This is so much cleaner than my previous solution. I love it! Thanks to whomever pointed out the obvious.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-72097419212827493132009-05-20T20:51:00.002-06:002009-05-20T20:54:22.942-06:00A Background Task ClassI am working on an app that makes XML calls to a web service. At first, I made the calls within the main thread and waited for the results to come back. Not surprising, when these calls took longer than usual, the user interface suffered. Basically, the UI locks up while waiting for a response from the web service. This is because the main thread is busy and cannot service UI-related events, such as touch events.
What I had to do was make the web service calls in a separate thread so that the main thread can continue to service the UI.
I coded up a few uses and I quickly discovered that my app wanted two different behaviors while making web service calls in the background. These behaviors are:
<ol> <li> The background task should operate transparently. It would only alert the user if the operation timed out,
</li> <li> The user had to wait for the operation to complete, but user is given the option to cancel the background operation.
</li> </ol>
I decided to create a utility class to encapsulate these behaviors and make it all a little easier. Thus I created the BackgroundTask class, which I present here.
What does it do? The BackgroundTask class is like a NSThread class; it allows you to spin off code in a separate thread. But this class is more powerful because it supports the two behaviors described above.
<h3> The Behaviors </h3>
First, let's discuss the desired behaviors in a little more detail.
Behavior #1 listed above is for tasks that are low priority and don't require the user to wait for it to complete. The task is kicked off in the background, and the main thread retains control for the user to do whatever they need. They don't even know there is something going on in the background (except for the spinning network access icon in the status bar).
The only feedback the user may get is if the operation timed out, meaning it failed. Each task created is given a timeout value. If the operation is not complete by this timeout period, then an alert message pops up that displays something like this:
<div id="ehv4" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_384c599gmcg_b" style="width: 279px; height: 133px;" /> </div>
The alert message displayed below "Operation failed" is also configurable when you create the task object.
Behavior #2 is more of a blocking operation, but with the option to cancel it if the user feels it is taking too long. This is useful for higher-priority tasks that require the user to wait until it is complete. For example, if the user hit a refresh button to update the items displayed in a table, it kind of makes sense for the refresh to complete before continuing.
When running a task like this, it displays a modal dialog like this:
<div id="xsfo" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_385hfqcmg55_b" style="width: 277px; height: 131px;" /> </div>
I added a little optimization to this behavior as well. This dialog won't pop up for X number of seconds, where X is configurable. This is to avoid those situations where the background task completes almost immediately. When this happens, it was silly for the alert to pop up then disappear so fast that the user couldn't even read what it said. So the alert will only come up if the task takes longer than X seconds.
<h3> Instantiating </h3>
Since the BackgroundTask class supports two different behaviors, it also supports two different initializers.
This first one initializes the object for behavior #1, where the task runs the background without any user interaction:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">BackgroundTask* task = [[BackgroundTask alloc] initWithTarget:self
selector:@selector(executeEmailPage:)
argument:myparent.page
timeout:40.0
alertMsg:@"Attempt to email page timed out"]; </span></pre>
The target/selector arguments specify the method to run in the new thread. The argument is optional data you can pass to the above method. Timeout specifies how long to give that thread before putting up an alert. And the final argument is the alert message to put up when the operation times out.
This next initializer is for behavior #2, where the user can cancel the operation:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">BackgroundTask* task = [[BackgroundTask alloc]
initWithTarget:self
selector:@selector(backgroundRefresh)
argument:nil
waitBeforeAlert:0.5
title:@"Refreshing data"
msg:@"Standby while refreshing pages"]; </span></pre>
<p> The target, selector, and argument parameters are the same as the first initializer. The waitBeforeAlert parameter specifies how long to give the operation to complete before putting up the modal box. The title and msg parameters allow you to configure the text displayed in the modal dialog.
</p> <h3> Usage </h3> To use the BackgroundTask object after you create it is very simple:
<pre style="border: 1px dashed rgb(153, 153, 153); font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238);"><span style="font-size:85%;">// start the background thread
[task start];
// release it since we don't need it anymore
[task release]; </span></pre>
<h3> Getting The Code </h3>
The code for the BackgroundTask class is available on the Osmorphis google group. You can download the .zip archive <a href="http://groups.google.com/group/osmorphis/web/BackgroundTask.zip" id="dird" title="here">here</a>. Hopefully its usage is clear enough that you can easily stick the code in your own project and begin using it right away.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-48834228169157285322009-05-12T16:13:00.004-06:002009-12-10T08:43:33.123-07:00Multiple Buttons on a Navigation BarPreviously, I wrote about how to <a href="http://osmorphis.blogspot.com/2009/05/using-standard-toolbar-and-navbar.html" id="l5xy" title="use standard icons in your navigation bar">use standard icons in your navigation bar</a>. This takes advantage of the nav bar's ability to put a button on the right side. But what if you want to put multiple buttons there? If your title is short enough, you can easily fit 2 or 3 buttons in that space. The nav bar allows you to stick content on the right hand side via the rightBarButtonItem property. On the surface, you might think you can add but one button to this property. But it's not so. There is an initializer for UIBarButtonItem that takes a view: <pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>initWithCustomView:(UIView *)customView
</code></pre>With this, you can create multiple UIButton objects, add them to a UIView, and then create a UIBarButtonItem passing in this parent UIView. The following pseudo-code shows what I mean: <pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>// create the container
UIView* container = [[UIView alloc] init];
// create a button and add it to the container
UIButton* button = [[UIButton alloc] init...];
[container addSubview:button];
[button release];
// add another button
button = [[UIButton alloc] init...];
[container addSubview:button];
[button release];
// now create a Bar button item
UIBarButtonItem* item = [[UIBarButtonItem alloc] initWithCustomView:container];
// set the nav bar's right button item
self.navigationItem.rightBarButtonItem = item;
[item release];
</code></pre>But, what if you want multiple *standard* buttons. Access to the standard buttons/icons is through the UIBarButtonItem class, not UIButton. You can't add UIBarButtonItem objects to a UIView. While there is support to create a UIBarButtonItem object from a UIView-derived object, there does not seem to be a way to do the opposite; there is no way to create a UIView object from a UIBarButtonItem. The only way I found how to deal with multiple UIBarButtonItem objects is to stick them in a toolbar. A UIToolBar is designed to hold multiple UIBarButtonItem objects. Think of a toolbar as your container, instead of the UIView object. And since a UIToolBar is UIView based, it can be added to the right side of a nav bar using the above trick. The following code shows how you can add two standard buttons to the right side: <pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
// create a toolbar to have two buttons in the right
UIToolbar* tools = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 133, 44.01)];
// create the array to hold the buttons, which then gets added to the toolbar
NSMutableArray* buttons = [[NSMutableArray alloc] initWithCapacity:3];
// create a standard "add" button
UIBarButtonItem* bi = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:NULL];
bi.style = UIBarButtonItemStyleBordered;
[buttons addObject:bi];
[bi release];
// create a spacer
bi = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
[buttons addObject:bi];
[bi release];
// create a standard "refresh" button
bi = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refresh:)];
bi.style = UIBarButtonItemStyleBordered;
[buttons addObject:bi];
[bi release];
// stick the buttons in the toolbar
[tools setItems:buttons animated:NO];
[buttons release];
// and put the toolbar in the nav bar
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tools];
[tools release];
</code></pre>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com37tag:blogger.com,1999:blog-6864853053396532264.post-62462104761367511402009-05-06T21:49:00.003-06:002009-05-06T21:55:03.857-06:00Reflection in Objective-CWhen I first learned Java, I thought the whole reflection package was novel, and it put Java closer to the realm of interpreted scripting language and farther away from the then-mainstream languages of C and C++. The idea of being able to look inward at the class metadata of an object at runtime was really fascinating, although not always terribly useful in everyday application programming.
Those programmers coming over to the Objective-C world from Java will be happy to know that Objective-C also supports the concepts of reflection, AKA introspection.
In fact, Objective-C 2.0 has many runtime features such as dynamically changing a class definition and even creating a new class dynamically. The necessity for these abilities is rather obscure, and it firms my belief that Objective-C is a ridiculously bloated language.
To me, Objective-C has a bit of an identity crisis: it's not quite sure if it's an interpreted language or a compiled language. The runtime is mostly dynamic. Unlike C++, Objective-C does runtime binding. This is why you can do things like define methods for an implementation that are never declared in your header file, or extend existing classes with categories.
Unfortunately, because of all this bloat, it is hard to find just the simple stuff that you might actually use in your day-to-day code. I will try to unearth some of these jewels and bring them to light.
<h3> Grandpa NSObject </h3>
Most, if not all, the runtime reflection support comes from the NSObject class. NSObject, like Java's Object class, is the granddaddy class of all classes (except for some rare exceptions). Therefore, all of your classes already have access to this reflection support.
It's important to note that all this reflection support is not part of the Objective-C language per se; it is part of the NS* runtime environment. This is also why some of this stuff seems tacked on. It's because it has, uh, been tacked on.
<h3>
</h3><h3> Getting Class Metadata </h3>
You can access the class metadata for an object by calling the <span style="font-family:Courier New;">class</span> method:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
Class c = [self class];
</code></pre>
This method is both an instance and a class method. It returns a C struct full of all sorts of mysterious stuff, like the list of instance variables, methods, etc. All of this is old hat to the java.lang.reflect package users out there, but the interfaces to reach this stuff in Objective-C seems really complex. This is probably difficult by design to keep the riff-raff out.
So far, the only use I have for the class method is to provide the parameter to the isKindOfClass method described below. I never need to actually look at the contents of the Class structure.
<h3> Dynamic Method Invocation </h3>
I already discussed one aspect of reflection in my article about <a href="http://osmorphis.blogspot.com/2009/04/invoking-selectors.html" id="f2lk" title="invoking methods">invoking methods</a>. This allows you to build up a method call, arguments and all, at runtime. This is similar to using the java.lang.reflect.Method class in Java.
<h3> Testing inheritance </h3>
Java has an operator called <span style="font-family:Courier New;">instanceof</span> that allows you to check if a object is an instance of a particular class or interface. Objective-C has a similar feature, the <span style="font-family:Courier New;">isKindOfClass:</span> method.
<span style="font-family:Courier New;">isKindOfClass:</span> will return YES if the receiver is an instance of the given class or an instance of any class derived from the class. For example, if I had an array of related pointers, I can operate on each differently according to its type:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
for(BaseClass* base in myArray) {
if([base isKindOfClass:[ClassOne class]]) {
// do stuff specific to ClassOne
}
else if([base isKindOfClass:[ClassTwo class]]) {
// do stuff specific to ClassTwo
}
else if([base isKindOfClass:[ClassThree class]]) {
// do stuff specific to ClassThree
}
// etc
}
</code></pre>
If you want an exact class match, and not match any inheriting classes, then you use <span style="font-family:Courier New;">isMemberOfClass:</span>.
<h3> Testing Protocol Conformance </h3>
Similar to class instance testing, you can also test whether an object conforms to a particular protocol. Java neatly uses <span style="font-family:Courier New;">instanceof</span> for both classes and interfaces, but Objective-C has to have a more clunkier approach. To test conformance, use the <span style="font-family:Courier New;">conformsToProtocol:</span> method:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
BOOL conforms = [obj conformsToProtocol:@protocol(MyInterface)];
</code></pre>
<h3> Testing for Method Existence </h3>
To an old Java and C++ hack like me, it seems extremely odd that you may not know if an object implements a method or not. But since Objective-C classes are largely dynamic, you need a way to check if a method you need is actually there. Hence the method <span style="font-family:Courier New;">respondsToSelector:</span>. Here you are asking the receiver if it implements (or inherits) the given method:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
if([obj respondsToSelector:@selector(aMethod:)]) {
// it's there, so we can call it
[obj aMethod:YES];
}
</code></pre>
Certainly, there is way more you can do on the reflection front in Objective-C, but I tried to discuss the more commonly used reflection mechanisms.
If you need too add hardcore dynamic nature to your software, you should be familliar with these documents:
<a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/" id="gday" title="Runtime Programming Guide: Introduction">Runtime Programming Guide: Introduction</a>
<a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/ObjCRuntimeRef/" id="i8ow" title="Runtime Reference">Runtime Reference</a>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-56729440970520099122009-05-04T19:40:00.003-06:002009-05-04T19:45:59.232-06:00Using Standard Toolbar and Navbar ButtonsIn an article several months back, I discussed <a href="http://osmorphis.blogspot.com/2009/02/tab-bar-icons-part-1_4115.html" id="e18x" title="how to use standard Tab bar buttons">how to use standard Tab bar buttons</a>. These are icons provided by Apple for you to use in the tab bar. But tab bars are not the only container that offers system-provided icons. There are standard icons available for toolbars and navigation bars.
Recently I wanted to make use of a system icon, but it took me some time to find what icons were standard and how to use them. Even though it is fairly trivial, I would like to share this information, if nothing else but to save people a few minutes of needless searching.
If you feel weird about using system-provided icons, don't. Apple is very keen on developers making use of the standard icons and encourages it in the HIG. However, Apple is also adamant about the <i>consistent</i> use of these icons. If your application uses a standard icon in a way unintended for that icon, then it is likely your app will get rejected from the app store. For example, if you are using the standard Contacts icon to bring up a list of contact lens providers, <i>ding</i>!
Here is the <a href="http://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/MobileHIG/SystemProvided/SystemProvided.html" id="ycq:" title="section in the HIG">section in the HIG</a> that lists the standard icons and their intended uses. This gives you an idea to what is available, but doesn't help you coding one of them up.
You have to know how to reference each of these in your code. For this, you have to look at the <a href="http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIBarButtonItem_Class/Reference/Reference.html" id="e93k" title="UIBarButtonItem class reference">UIBarButtonItem class reference</a>. If you go to the Constants section, you will see the UIBarButtonSystemItem enumerations which define the values for all the system icons.
<h3> For nav bars </h3> To put a system icon on the navigation bar, you have several choices for the location. At the most basic level, you can put the icon on the left or the right. If you require more refinement, it's quite easy to do with subviews, but that technique is well-documented and outside the scope of this article.
Here is the simple code for putting the standard refresh icon <img src="http://docs.google.com/File?id=ddkdktns_358f45s33ds_b" style="width: 18px; height: 21px; float: left; margin-left: 1em; margin-right: 0pt;" />in the left position:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:@selector(refresh:)];
</code></pre>
The first parameter is the enum from the UIBarButtonItem reference. The target/action parameters specify the method to call when the button is hit.
<h3> For toolbars </h3> Adding the standard icons to a toolbar is a little more involved, but still straight-forward. Toolbars also take UIBarButtonItem objects, but instead of assigning them to specific locations, you must add them to an NSArray object first (in the order you want them) and then add the array to the toolbar object.
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
// create the toolbar object
UIToolBar* toolbar = [[UIToolBar alloc] init];
// create an array to hold the buttons
NSMutableArray* buttons = [[NSMutableArray alloc] init];
// create a standard button
UIBarButtonItem* button = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:@selector(refresh:)];
// stick it in the array
[buttons addObject:button];
// add more buttons
//...
// add the array to the toolbar
toolbar.items = buttons;
// done with the buttons array
[buttons release];
</code></pre>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-64729760804578871752009-04-28T20:30:00.002-06:002009-04-28T20:35:05.708-06:00Invoking SelectorsThere are many instances in the Cocoa-Touch SDK where you need to specify a callback method. For example, UIButton has a method where you set the callback for when the button is hit. Or an NSTimer can have a callback for when the timer expires. UIBarButtonItem also has a callback when the button is hit.
Every one of these examples follows the same pattern: you have to provide the target (usually self, but doesn't have to be), and a selector created with the mysterious @selector() construct.
Wouldn't it be neat if you could use these target/selector pairs in your own code?
There are many possibilities of why you would want to implement your own callbacks, like writing your own GUI buttons, or you wanted to create a convenience class to make threading a little easier.
Let's demonstrate using that last example: create a convenient Thread wrapper class. This class is very similar to the NSOperation class, so this is really for demonstration purposes and not something terribly useful.
<div style="text-align: left;"> <img id="mp-b" src="http://docs.google.com/File?id=ddkdktns_356grrw63sh_b" height="118" width="228" />
</div> The NSThread class requires you to provide the target/selector for the function's main entry point. That method must create a new autorelease pool, and then release it when it is done. It would be nice if we didn't have to do that boilerplate code every time we wanted to spawn off a thread. So a wrapper class can do it for us.
Let's call this new class MyThread:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>// MyThread.h
@interface MyThread
{
NSThread* thread;
NSInvocation* inv;
}
@property(nonatomic,retain) NSThread* thread;
@property(nonatomic,retain) NSInvocation* inv;
- (id) initWithTarget:(id)target selector:(SEL) selector object:(id) argument;
- (void) start;
@end
</code></pre>
Obviously, this class doesn't do as much as the NSThread class, but these two methods are sufficient to demonstrate method invocation.
What this class does is create the NSThread object, then provide the thread main entry point, which points back into the MyThread class. This will create the autorelease pool, then call the "other" entry point (the one that was supplied to MyThread). When that returns, it releases the pool.
The key here, and the point of this article, is calling the other entry point. It is not trivial, as you'll soon see.
Most of the grunt work is done in the MyThread initializer:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>
- (id) initWithTarget:(id)target selector:(SEL) selector object:(id) argument
{
// create the thread object
thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMain) object:nil];
// create the invocation object
//
// first we need the method signature
NSMethodSignature* sig = [target methodSignatureForSelector:selector];
// now create the invocation object from the signature
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:sig];
// setup the invocation
[inv setTarget:target];
[inv setSelector:selector];
// set the argument, if there is one
if(argument) {
[inv setArgument:&argument atIndex:2];
}
[inv retainArguments];
}
</code></pre>
If you are familiar with Java, you'll notice that the NSInvocation class is similar to the java Method class in the reflection package. The NSInvocation object is what you use to piece together a method call at runtime. Once it's all put together, you can invoke it.
This code first constructs a NSMethodSignature object which is used to create the NSInvocation object. Then we configure the target and selectors (not sure why, since the signature should have all that embedded). Finally, we set the arguments to the call.
The argument goes at index 2 because the self argument occupies index 0, and the _cmd argument takes index 1. Thus, any additional arguments start at index 2.
Now everything is all setup in our MyThread class. All we do is wait for the thread to be started via the start method. This just delegates the start to the internal NSThread object:
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>- (void) start
{
[thread start];
}
</code></pre>
The thread is configured to use the thread entry point threadMain defined in MyThread. This is where we put the boilerplate pool code, then call the callback supplied to us in the initializer.
<pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>- (void) threadMain
{
// create the autorelease pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// now run the selector provided to us
[inv invoke];
// release the pool
[pool release];
}
</code></pre>
The NSInvocation class is a little clumsy to set up, but it can be quite powerful when you want to specify and use your own callbacks.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0tag:blogger.com,1999:blog-6864853053396532264.post-15468298404103035452009-04-22T10:24:00.003-06:002010-12-14T19:31:37.828-07:00TableFormEditor v1.4: text field settingsA while ago, I introduced a reusable class for producing editable forms. This article can be read <a href="http://osmorphis.blogspot.com/2009/03/general-purpose-table-form-editor.html" id="jpl1">here</a>. There was also a <a href="http://osmorphis.blogspot.com/2009/03/tableformeditor-example.html" id="ez.g">followup article</a> containing a detailed usage example and some bug fixes in the TableFormEditor code. I have been using this class since then, and it quickly became clear that I needed a way to configure the text fields that were used in the form. For instance, one of the fields in my app takes a URL as input, and I would have liked to use the special keyboard that is designed for that type of input. This forced me to do some research on how to configure text fields. This research culminated into these two articles: <a href="http://osmorphis.blogspot.com/2009/04/configuring-text-fields-part-1.html" id="fap:">part 1</a> and <a href="http://osmorphis.blogspot.com/2009/04/configuring-text-fields-part-2.html" id="n-yr">part 2</a>. Now it is time to put this research into the TableFormEditor class. I came up with a solution that may not be the best, but since I need to make some progress on my app, I forged ahead and implemented this solution. Comments are appreciated on other ways to do this. It currently serves its purpose and might even be deemed "clever". If you are familiar with the TableFormEditor class, you know that you provide the field labels in an array. These labels are also used as keys to a dictionary that contains the field data. The edited data is also returned in a dictionary, again keyed by the row labels. Even if you don't use the field rows as labels, you still need to provide those for keying purposes. I extended this idea by allowing you to provide text field properties for each field. These properties are set to configure the behavior of the text field, as well as the keyboard behavior. All the supported properties are described in the two-part article mentioned above. I first thought about using a dictionary to hold the properties, or creating a new class, but decided to use a real UITextField object to hold the properties. After all, this class already has all the properties I want. What you do is create a UITextField object, set all the properties you need, and put this object in a dictionary. The field labels provide the dictionary keys, just as they do for the field data dictionary. It's important to understand that these UITextField objects you create are not used in the GUI; they are only used to hold values for properties, then they are thrown away. In this sense, they serve as "prototype" UITextField objects. The reason I chose to do it this way was based purely on convenience. There was no sense creating another class with all the same properties. And when setting the properties, XCode knows what the properties and it does the code completion for you. I have modified the TableFormEditor class to have an additional property: <b><span style="font-family: 'Courier New';">textfieldProto</span></b> This is a mutable dictionary. The keys are the label names of each field. The value for each key is a UITextField object that has all the desired properties set. I have modified the example to have 4 fields: <br />
<ol><li> name field. For this field I would like auto correction turned off, but would like to auto capitalize the beginning of each word. </li>
<li> age. This field is all numbers, so I would like the numeric keypad to come up when this field has the focus. </li>
<li> homepage. For this, I want the URL keyboard, and turn off any auto capitalization and auto correction. </li>
<li> password. This field should use the secure key feature, which dots out each letter as you type it. </li>
</ol>The following is the code snippet from the example that demonstrates how you create the UITextField prototype objects and set them in the TableFormEditor object: <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
// create the dictionary to hold the text field properties
NSMutableDictionary* textFieldProto = [[NSMutableDictionary alloc] initWithCapacity:4];
// prototype for the Name field
// shrink the font to fit, don't autocorrect, autocap first letter
UITextField* tf = [[UITextField alloc] init];
tf.adjustsFontSizeToFitWidth = YES;
tf.minimumFontSize = 7.0;
tf.autocorrectionType = UITextAutocorrectionTypeNo;
tf.autocapitalizationType = UITextAutocapitalizationTypeWords;
// add it to the dictionary
[textFieldProto setObject:tf forKey:@"Name"];
[tf release];
// prototype for the Age field
// use the numeric keyboard
tf = [[UITextField alloc] init];
tf.keyboardType = UIKeyboardTypeNumberPad;
[textFieldProto setObject:tf forKey:@"Age"];
[tf release];
// prototype for the Homepage field
// use the URL keyboard, turn off autocorrect, show clear button, autocap off
tf = [[UITextField alloc] init];
tf.keyboardType = UIKeyboardTypeURL;
tf.autocorrectionType = UITextAutocorrectionTypeNo;
tf.autocapitalizationType = UITextAutocapitalizationTypeNone;
tf.clearButtonMode = UITextFieldViewModeAlways;
[textFieldProto setObject:tf forKey:@"Homepage"];
[tf release];
// prototype for the Password field
// use secure entry
tf = [[UITextField alloc] init];
tf.secureTextEntry = YES;
[textFieldProto setObject:tf forKey:@"Password"];
[tf release];
// now register all the text field prototypes
form.textFieldProto = textFieldProto;
</code></pre>The updated example XCode project is available for you to play around with, as well as the updated TableFormEditor class to support text field prototypes, using <a href="http://sites.google.com/site/osmorphis/TableFormEditorExample.zip" id="byv_">this link</a>.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com1tag:blogger.com,1999:blog-6864853053396532264.post-44285563476843099572009-04-15T13:40:00.002-06:002009-04-15T13:42:01.971-06:00Creating Stretchable Button ImagesIn a <a href="http://osmorphis.blogspot.com/2009/04/putting-button-in-table.html" id="p_dv" title="previous article">previous article</a>, I described a couple techniques for putting buttons in a table. If you want your buttons to have a background color, and likely some kind of gradient, the trick is to use a custom UIButton. These are interesting because they can have an image that forms the background of the button, and this image can be stretched to fits the frame of the button.
In this article I will describe how to create these stretchable button images that look nice in a table. I will demonstrate this using Inkscape, a wonderful vector drawing application that can be freely downloaded from <a href="http://www.inkscape.org/" id="deuj" title="here">here</a>.
What I will show is how to create an image that looks like this:
<div id="xoc_" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_304d6hvqwtv_b" style="width: 63px; height: 29px;" />
When this image is applied to a custom UIButton, with some text added, you get something like this:
<div id="y0rt" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_306d96wnrg8_b" style="width: 313px; height: 60px;" />
This shows how the image is stretched in order to fit the button's frame.
<h2> Step 1. Starting Inkscape
</h2>
The first step is to fire up Inkscape. We're only dealing with an image of around 100x40 pixels, so your canvas shouldn't be too big. Bring up the document properties (File>Document Properties) and set the custom size to something like 200 x 60 pixels. But this will make your canvas really small, so zoom in with View>Zoom>Page
</div> </div>
Here is what your Inkscape window should look like:
<div id="u6eb" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_307dj6wkzd3_b" style="width: 640px; height: 533.093px;" /> </div>
<h2> Step 2. Drawing the Rectangle
</h2>
Now we will use the rectangle tool to draw our image. I don't think the size of the image is terribly important, since Cocoa Touch will stretch it to fit. For this exercise, I will create an image roughly 90x40 pixels.
Click on the rectangle and squares tool (F4). Now draw a rectangle on your canvas about 90x40 pixels in size. The size will be displayed in the status bar at the bottom and will adjust as you drag your mouse. Don't worry about fill or stroke color at this point; we'll adjust those later.
Now you might have something like this (fill color uses whatever color you used last):
<div id="lafn" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_308fxnjjgcv_b" style="width: 640px; height: 536.118px;" />
<h2> Step 3. Rounding the Corners
</h2>
Time to make the rounded corners. If you don't see the little circle in the upper right corner of your rectangle, select the Edit Paths by Node tool (F2) and click on your rectangle. That should bring up the little circle.
Now drag that circle down, which creates the rounded corners. Make them as round as you want, but I pulled the circle down about a ¼ of the way down: <div id="r9pu" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_309f938sdfh_b" style="width: 470px; height: 217px;" /> </div> <h2> Step 4. Filling with Color
</h2>
Now we have to change the fill color. Bring up the Object>Fill and Stroke window. You may have to make the window a little larger to fit it on. Make sure the Fill tab is selected and click on the Flat Color icon at the top (the one to the right of the "X"). Now you can enter RGB values, or use the wheel, or any of the 5 methods to set the color just the way you want. I prefer to use the wheel to get to the general color, then switch over to RGB to fine tune it.
For this example, I want a color with RGB values 0, 189, 0. Now my image looks like this:
</div> <div id="ow-_" style="text-align: left;"> <div id="rbaa" style="text-align: left;"> <div id="ol:r" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_316fc7m2kc8_b" style="width: 366px; height: 165px;" /> </div> </div> </div>
<h2> Step 5. Coloring the Border
</h2>
To set the stroke, you can make this whatever you want, but I prefer a stroke weight of 0.5 pixels. This allows the button to look more like a table row. This is set on the Stroke Style tab of the Fill and Stroke window. The stroke color is set on the Stroke Paint tab. I want a sort of gray color to match the table row borders. I think I am pretty close with these RGB values: 63, 118, 83:
<div id="i0hs" style="text-align: left;"> <div id="i38m" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_317dh49cqcc_b" style="width: 375px; height: 170px;" /> </div>
<h2> Step 6. Adding the Glare
</h2>
We're in the home stretch now, but this is the trickiest part: applying the gradient to give it that shining light affect. For this we will use the Create and edit gradients tool (above the eye-dropper tool on the left, or Ctrl-F1). Click in the middle of your image and drag the mouse up. This will create a gradient that gradually gets lighter as you go up. You can click on the endpoints and move them around to get your desired gradient affect:
<div id="j5_7" style="text-align: left;"> <div id="gtg3" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_318cmj6bhgh_b" style="width: 375px; height: 191px;" />
</div> You might want to add another point on the gradient line to give a more enhanced affect. To do this double click on the bottom handle. You'll see a dialog like this:
<div id="e8cf" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_313c4dh7cfm_b" style="width: 248px; height: 431px;" />
Click on the "Add stop" button, and this will add another handle on the gradient line in the middle. You can also drag this around. While the gradient editor is up, you can adjust the colors of each handle.
</div>
One problem is that the default settings for the gradient tool is to go towards a translucent color. This might look fine within Inkscape, but when you create a button with translucence, it will actually show the background through the button. This may or may not be a desired affect. If it isn't, you can change the color of each end of the gradient. Simply click on the handles and make sure the opacity is set to 100% and the color will now be solid.
Unfortunately, this has the affect of hiding your gradient. Don't worry; just select each handle and adjust the colors the way you want them look.
After fiddling with colors of each of the handles, I got an end product that looks like this:
<div id="sr.2" style="text-align: left;"> <div id="m_oc" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_319d75z8mc3_b" style="width: 387px; height: 201px;" /> </div>
<h2> Step 7. Saving your Work
</h2>
Now you need to save it. This is a very confusing part of the Inkscape interface. When exporting a bitmap, Inkscape saves it as a PNG file, the perfect format for the iPhone. Select File>Export Bitmap. Make sure the Selection tab is selected and that the entire image is selected.
Click on the Browse button. The browse button brings up another dialog where you select the directory and enter a filename. There is a save button on this dialog, but don't be fooled. This does not save the file. It really behaves like an Ok button, so go ahead and click it.
Now you can actually save the file by hitting the Export button. Copy the resulting .png file into your XCode project, and use it as described in the article mentioned above.
I hope this was clear and helpful.
</div> </div> </div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com3tag:blogger.com,1999:blog-6864853053396532264.post-33396363194784949502009-04-09T20:38:00.005-06:002011-06-28T12:28:19.519-06:00Putting a Button in a TableSometime you may need to add a button to the contents of a UITableViewController. While you have the ability to put buttons in the navigation bar or in a toolbar at the bottom, it is sometimes best to simply put the button "inline" near your data. Sure, you could simply put a UIButton control right in a UITableCell object, but I have found the results of that not very attractive, especially in grouped tables. So what's the best way? I like to use the Apple applications as examples of good design. There are a couple Apple applications that put UIButtons in UITableViewControllers. Take a look at these examples. This one is from the mail settings, where there is a "Delete Account" button at the bottom of the table: <br />
<div id="hwa:" style="text-align: left;"><img height="401" src="http://docs.google.com/File?id=ddkdktns_286hrmdj5fg_b" width="285" /> </div>And this one is when you are editing a contact, where there is another "Delete" button at the bottom: <br />
<div id="epz8" style="text-align: left;"><img height="428" src="http://docs.google.com/File?id=ddkdktns_287cmgx24hp_b" width="286" /> </div>Although they are the same size of a single cell section, you can tell these are not normal rows. The giveaways are the rounded corners that don't quite match those of the neighboring rows. My guess is these are custom buttons, which stretch a background image to fit a frame that's the same size of a cell. But using UIButton controls is not the only way to get button behavior. You can simulate a button with just a basic grouped table cell; no UIButton at all. This is what I call cell-based buttons, for lack of a better term. I found a couple Apple applications that appear to use this technique. For example, here is the the settings from Safari: <br />
<div id="q:ie" style="text-align: left;"><img height="430" src="http://docs.google.com/File?id=ddkdktns_288fqnrsvct_b" width="286" /> </div>That section of three rows in the middle contain cells where each operates as a button. The phone settings also uses this, with the "Change Voicemail Password" cell in the middle. There are probably other ways to get button functionality into your tables, but these two seem to be the most common. This article will explain the advantages and disadvantages of each approach, and I'll provide some code snippets that shows how to do them. <br />
<h3>Cell-Based Buttons </h3><div>Simulating a button in a cell has one big advantage: it's super easy to do. If you don't care about it looking fancy, or want to bunch up several "buttons" in one section, as the one above for editing a contact, then a cell-based button is a good option. For simple black on white text, all you have to do is set the cell.text property to your button text. Since the visual aspects of a table cell can be customized quite extensively, you really have lots of flexibility here. However, once you go beyond the standard UITableCell object, the complexity of your code increases. I believe that once you have gone beyond the basic black on white text, you might as well go with a real button. <br />
<h4>Implementing </h4>How a cell-based button works is that your code simply traps the tableView:didSelectRowAtIndexPath: message. You associate the section and row with which "button" was hit and perform whatever action that button is supposed to do. For example, from the image above, you can associate that block of buttons with section #1, and row #0 is the "Clear History" button, row #1 is "Clear Cookies", etc. One thing to remember is that the action of touching a cell automatically highlights the cell. Before you do anything else, you should turn off that highlight. Here is some example code of how we might implement the above section of three buttons. There are two aspects here: setting up the buttons for display, and handling the actions when the buttons are selected. <u>Setting up for display</u>. All of this is fairly boilerplate code for the tableView:cellForRow: message. The big difference here is that we are not fetching the row contents from a database, but hard-coding the button title. This can easily be internationalized as well. <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (UITableViewCell *)
tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// are we setting up our button section?
if(indexPath.section == 1) {
switch(indexPath.row) {
case 0: cell.text = @"Clear History"; break;
case 1: cell.text =@"Clear Cookies"; break;
case 2: cell.text = @"Clear Cache"; break;
}
}
else {
// do whatever for the other sections
}
return cell;
}
</code></pre>For cell-based buttons, you want to avoid using the accessory view, like putting in a detailed disclosure button or the checkmark. Having these items on a "button" will be confusing. <u>Handling actions</u>. All you do here is figure out which "button" was hit and do whatever it is you need to do. Also notice the code to turn the highlight off. <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (void)
tableView:(UITableView *) aTableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath
{
// remove the row highlight
[aTableView deselectRowAtIndexPath:indexPath animated:YES];
// Is this section our "button" section?
if(indexPath.section == 1) {
switch(indexPath.row) {
case 0: [self doClearHistory]; break;
case 1: [self doClearCookies]; break;
case 2: [self doClearCache]; break;
}
return;
}
else {
// do other stuff...
}
}
</code></pre><h3>Real Buttons </h3>Real buttons offer all the advantages you get with a real button. For one thing, the size of the button can be fully customizable. This allows you to have two buttons side by side, as in this example from showing detailed info of a contact: <br />
<div id="sm9s" style="text-align: left;"><img height="431" src="http://docs.google.com/File?id=ddkdktns_289ckhd3gcg_b" width="287" /> </div>You can't have two table cells side by side like that, so these have to be buttons. You'll note that these rounded corners match the rounded corners of the table cells. I think these buttons use the normal RoundedRect button, as opposed to custom buttons. Custom buttons are mostly needed when you want a background color other than white. But if all you need are plain white backgrounds, you can use the RoundedRect buttons. Which leads to the other advantage of using real buttons: better control over background colors. Setting a background color in a grouped table cell is difficult. Just simply setting the background property to a color is not enough, as the rounded corners do not get the color. The only solution I've seen to this problem is a complicated bit of code to color in the curved corners (as demonstrated <a href="http://pessoal.org/blog/2009/02/25/customizing-the-background-border-colors-of-a-uitableview/" id="ms_n" title="here">here</a>). You also don't get the cool gradients as you see in the two red buttons on the top two examples. </div>There are probably other advantages to using real buttons, but to me these are enough to force me to use buttons sometimes. <br />
<h4>Implementing </h4>So how are UIButtons integrated into a UITableView? Again, there may be several ways, but I find the easiest is to sneak the buttons into a section header. Each section can have a header view. In this view is where you put your UIButton objects. The section itself has no data rows, only a header. So what I do is accommodate for one extra section in my table, but return 0 for the number of rows. <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (NSInteger)
numberOfSectionsInTableView:(UITableView *)aTableView
{
// return the number of sections the data is organized in, plus 1 for the button
return 2 + 1;
}
</code></pre>Assuming you want your button at the end of the table, you would use code like this to return the number of rows: <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (NSInteger)
tableView:(UITableView*) aTableView numberOfRowsInSection:(NSInteger) sectionNum
{
if(sectionNum == 3) {
// this is our button section
return 0;
}
else {
// do whatever, according to the data
}
}
</code></pre>Now we have to create our buttons. This is done in the tableView:viewForHeaderInSection: <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (UIView *)
tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionNum
{
if(sectionNum == 2) {
// create the parent view that will hold 1 or more buttons
UIView* v = [[UIView alloc] initWithFrame:CGRectMake(10.0, 0.0, 300.0, 44.0)];
// create the button object
UIButton* b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setBackgroundImage:[[UIImage imageNamed:@"redbutton.png"] stretchableImageWithLeftCapWidth:12.0 topCapHeight:0.0] forState:UIControlStateNormal];
[b setBackgroundImage:[[UIImage imageNamed:@"bluebutton.png"] stretchableImageWithLeftCapWidth:12.0 topCapHeight:0.0] forState:UIControlStateHighlighted];
b.frame = CGRectMake(10.0, 0.0, 300.0, 44.0);
[b setTitle:@"Button Title" forState:UIControlStateNormal];
// give it a tag in case you need it later
b.tag = 1;
// this sets up the callback for when the user hits the button
[b addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
// add the button to the parent view
[v addSubview:b];
return [v autorelease];
}
else {
// stuff for other sections
}
}
</code></pre>The values for the frames are specific to portrait mode; landscape mode will need some modifications. To add more buttons in this view, just adjust the y parameter in the frame for the button. I typically add 46.0 from the last one. This code makes use of two button images: <br />
<div id="y.cx" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_291ck4n53cb_b" style="height: 40px; width: 130px;" /> <br />
<div id="xngf" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_292hr4ttsgn_b" style="height: 40px; width: 130px;" /> I got these from user "hakimny" from this <a href="http://www.iphonedevsdk.com/forum/iphone-sdk-development/3119-setting-uibutton-color.html" id="p2bw" title="thread">thread</a>. Creating these aren't hard. (I have posted an <a href="http://osmorphis.blogspot.com/2009/04/creating-stretchable-button-images.html">article</a> on how to create simple background images like this in Inkscape.) </div></div>If you want to create a button with a white background, then you don't need to create a custom button. You can create a RoundedRect button that will look more like the surrounding cells, like you saw above. In this case, your button creation is simply: <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace;"><span style="font-size: 85%;">b = [UIButton buttonWithType:UIButtonTypeRoundedRect]; </span></pre>You don't need to set the background images. If you want to create two side by side buttons, all you have to do is monkey around with the frames of the buttons so that they are side by side instead of on top of each other. There is one gotcha I have discovered using this mechanism, and I think it is an SDK bug. If your table takes up more than one screen and you have to scroll to see your button, some of the button may remain hidden under the tab bar or tool bar. You won't be able to scroll the entire header view into view. This is especially noticeable if you have 2 or more buttons stacked on top of each other. I think Cocoa Touch is confused by there being no data rows, or maybe it can't quite figure out how high the header view is. So the way around it is to tell how high your view is. Once you do this, the view is no longer partially hidden: <br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>- (CGFloat)
tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionNum
{
return 46.0;
}
</code></pre>Of course, if you have more buttons in this section, you would return the appropriate height. There you have a quick tutorial on putting buttons in a table. How you choose which mechanism to use is up to you. My own guidelines are as follows: <br />
<ol><li> If I want a simple black on white button: use a cell-based button </li>
<li> If I need a colored button: use a real button </li>
<li> If I want multiple buttons per row: use real buttons </li>
</ol>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com6tag:blogger.com,1999:blog-6864853053396532264.post-85576482143738656502009-04-06T09:34:00.004-06:002009-08-18T15:32:24.960-06:00Configuring Text Fields (Part 2)<div> In <a href="http://osmorphis.blogspot.com/2009/04/configuring-text-fields-part-1.html" id="h3y." title="Part 1">Part 1</a> of this article, I described the various properties used to modify the "look and feel" of text fields. Most of these properties deal with the visual aspects, such as font and background color. They also handle various techniques for clearing out the text in a text field.
In this second part, I will focus on the virtual keyboard and the behaviors of changing your entered text (due to spelling or capitalization errors). It is likely that most people will be interested in changing some of the default behaviors.
As revolutionary as the iPhone virtual keyboard is, some of the things it does can be quite annoying for some applications. At the same time, some of the customizations you can make really help the usability of your application, so it is best to understand all your options in order to make the best user experience possible.
These are additional properties of the UITextField object you can change:
<b><span style="font-family:Courier New;">autocapitalizationType</span></b>
</div> <div style="margin-left: 40px;"> Setting this property determines when characters are auotmatically capitalized. The allowed enumerations are:
<ul style="font-family: Courier New;"> <li> UITextAutocapitalizationTypeNone </li> <li> UITextAutocapitalizationTypeWords </li> <li> UITextAutocapitalizationTypeSentences </li> <li> UITextAutocapitalizationTypeAllCharacters </li> </ul>
None will not autocapitalize anything. Words will capitalize the first character of every word, whereas Sentences will capitalize the first character of every sentence. AllCharacters will capitalize every character. The default is None.
</div>
<div> <b><span style="font-family:Courier New;">autocorrectionType</span></b>
<div style="margin-left: 40px;"> The autocorrection mechanism on the iPhone allows you to type "fast" and it will correct most of your mistakes. I find this works well, but in some cases I don't want this behavior. Luckily you can disable it. This property can be set to one of these values:
</div> <div style="margin-left: 40px;"> <ul style="font-family: Courier New;"> <li> UITextAutocorrectionTypeDefault </li> <li> UITextAutocorrectionTypeNo </li> <li> UITextAutocorrectionTypeYes </li> </ul>
The Default defers to what the documentation refers to what the "script system" supports, with no explanation of what a script system is. I assume this indicates in what context the keyboard is used. The UITextField is not the only user of the keyboard.
By setting <span style="font-family:Courier New;">autocorrectionType </span>to Default, you will get the auto-correction behavior *if* your current script system supports it. For the purposes of UITextField, it does support auto-correction. Setting this property to No will disable auto-correction. The default is Default, which for UITextField views, means auto-correction is enabled.
</div> <div style="margin-left: 40px;"> </div>
<b><span style="font-family:Courier New;">enablesReturnKeyAutomatically</span></b>
<div style="margin-left: 40px;"> By default, the return key on the keyboard is enabled. However, you can change this to be disabled *until* some text has been entered in the text field. I'm not sure what use this is for text fields, but you might have a need.
If you set this property to YES, then you will have this keyboard when you have no text entered:
<div id="x44n" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_256dx4csdfm_b" style="width: 316px; height: 411px;" /> </div>
The return key is disabled, but as soon as you entered some text, the keyboard changes to this:
<div id="l.e7" style="text-align: left;"> <div id="zd0y" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_258fvbgppjj_b" style="width: 318px; height: 414px;" /> </div> </div> </div>
<b><span style="font-family:Courier New;">keyboardAppearance</span></b>
<div style="margin-left: 40px;"> There are two types of keyboard appearances supported: one has the blue-gray background like the one above, and the other has a black background, like you see on alerts. The two enums this property supports are:
</div> <div style="margin-left: 40px; font-family: Courier New;"> <ul> <li> UIKeyboardAppearanceDefault </li> <li> UIKeyboardAppearanceAlert </li> </ul> </div>
<div style="margin-left: 40px;"> If you choose the alert appearance, the keyboard looks like this:
<img src="http://docs.google.com/File?id=ddkdktns_259cgr9rdfz_b" style="width: 323px; height: 216px;" />
As far as I can tell, there is no other difference in looks or behavior with this keyboard
</div> <div id="oymz" style="text-align: left;">
</div>
</div> <div> <b><span style="font-family:Courier New;">keyboardType</span></b>
</div> <div> <div style="margin-left: 40px;"> Depending on what kind of input you are gathering in your text field, you can have different keyboards that are optimized for that type of input. The keyboardType property can be set to one of the following enums. I also show what each keyboard looks like:
</div> <div style="margin-left: 40px;"> <pre>UIKeyboardTypeDefault:
<div id="j-8j" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_260gw7gj5gt_b" style="width: 319px; height: 213px;" />
</div>
</pre> </div> <div style="margin-left: 40px;"> <pre>UIKeyboardTypeASCIICapable:
</pre> </div> <div style="margin-left: 40px;"> <pre><div id="v-3q" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_261dv9x2b83_b" style="width: 321px; height: 214px;" />
<p style="font-family: Verdana;">The default looks the same as this. My guess is the default can change depending on context, whereas the ASCIICapable one always look like this.</p></div>
</pre> </div> <div style="margin-left: 40px;"> <pre>UIKeyboardTypeNumbersAndPunctuation:
</pre> </div> <div style="margin-left: 40px;"> <pre><div id="s9x1" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_262cgbc2qg3_b" style="width: 321px; height: 213px;" />
<p style="font-family: Verdana;">This is your standard numbers and punctuation keyboard.</p></div>
</pre> </div> <div style="margin-left: 40px;"> <pre>UIKeyboardTypeURL:
</pre> </div> <div style="margin-left: 40px;"> <pre>
</pre> </div> <div style="margin-left: 40px;"> <pre><div id="s615" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_2639ps3kfp5_b" style="width: 321px; height: 212px;" />
<p style="font-family: Verdana;">This keyboard is handy if you are typing in a URL. Also note that if you tap and hold on the .com button, you'll get a little pop-up window that will allow you to choose .edu, .net, .org, etc. Here is what that looks like:</p><p style="font-family: Verdana;">
</p></div></pre> </div> <div style="margin-left: 40px;"> <pre><div id="s615" style="text-align: left;"><p> </p><div id="z17f" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_264hjrpc6d5_b" style="width: 322px; height: 216px;" /></div>
</div></pre> </div> <div style="margin-left: 40px;"> <pre>UIKeyboardTypeNumberPad:
</pre> </div> <div style="margin-left: 40px;"> <pre><div id="c:yv" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_265hh84hghc_b" style="width: 325px; height: 223px;" />
<p style="font-family: Verdana;">This is useful if all you need is to enter numbers.</p>
</div></pre> </div> <div style="margin-left: 40px;"> <pre>UIKeyboardTypePhonePad:
<div id="bkfe" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_2663k6nzpgc_b" style="width: 323px; height: 224px;" />
<span style="font-family:Verdana;">This is similar to the NumberPad, but this one resembles a phone keypad, with the letters under the numbers and the "+*#" button.</span>
</div>
</pre> <pre>UIKeyboardTypeNamePhonePad:
<div id="vcz8" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_2677ptxsxfn_b" style="width: 322px; height: 219px;" />
<span style="font-family:Verdana;">This looks like your standard ASCII keypad, but the difference is when you hit the digits button in the lower left, you get a phone-specific keypad:</span>
<div id="sjqt" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_268cjtgtf2b_b" style="width: 325px; height: 222px;" /></div></div>
</pre> <pre>
UIKeyboardTypeEmailAddress:
<div id="sj.j" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_269cwdbq8w9_b" style="width: 320px; height: 213px;" /> <div id="f76t" style="text-align: left;"><img src="http://docs.google.com/File?id=ddkdktns_270d8vs7npv_b" style="width: 321px; height: 210px;" />
<span style="font-family:Verdana;">These are slightly optimized for entering email addresses.</span>
</div></div></pre> </div> <b><span style="font-family:Courier New;">returnKeyType</span></b>
<div style="margin-left: 40px;"> Just the return key can be changed with different labels. Like the keyboardType property, this allows you to customize the keyboard to fit your scenario. However, many of these are very application specific and may not have much use for text fields:
<span style="font-family:Courier New;">UIReturnKeyDefault</span> <span style="font-family:Courier New;">
UIReturnKeyGo</span> <span style="font-family:Courier New;">
UIReturnKeyGoogle</span> <span style="font-family:Courier New;">
UIReturnKeyJoin</span> <span style="font-family:Courier New;">
UIReturnKeyNext</span> <span style="font-family:Courier New;">
UIReturnKeyRoute</span>
<span style="font-family:Courier New;"> UIReturnKeySearch</span> <span style="font-family:Courier New;">
UIReturnKeySend</span> <span style="font-family:Courier New;">
UIReturnKeyYahoo</span>
<span style="font-family:Courier New;"> UIReturnKeyDone</span>
<span style="font-family:Courier New;"> UIReturnKeyEmergencyCall</span>
I won't show what all these keyboards look like. The only difference is the label on the return key. The useful ones for most text fields would be Next and Done.
When the return key is tapped, no matter what text is on it, the text field will call the <span style="font-family:Courier New;">textFieldShouldReturn:</span> method on its delegate. You can use this callback as a means to do something when the return is hit. One common trick is have <span style="font-family:Courier New;">textFieldShouldReturn:</span> resign the first responder, or in normal English: give up the focus, which in turn hides the keyboard.
</div>
<b><span style="font-family:Courier New;">secureTextEntry</span></b>
<div style="margin-left: 40px;"> If your text field is for entering passwords or other sensitive information, you can get the password-like entering behavior by setting this property to YES. When this is YES, only the last character entered will display in the text field; all others are replaced with a dot. Here is what is looks like:
<div id="e7:5" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_271f5wfg5gk_b" style="width: 318px; height: 413px;" /> </div>
</div> There you have all the properties you can change to modify the keyboard and auto-correction behaviors of your text fields. Instead of accepting the defaults, you can customize your text fields and make them more user-friendly and efficient.
</div>JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com2tag:blogger.com,1999:blog-6864853053396532264.post-33339928127322678812009-04-02T20:22:00.003-06:002009-04-06T09:36:22.165-06:00Configuring Text Fields (Part 1)<div> For something as seemingly simple as the UITextField view, it is a fairly rich control. Because of the limitations of the iPhone interface, the text field can be customized in many different ways to make it easier to use.
This two-part article will attempt to shed some light on all the options used to configure the text field, as they are lightly documented in the SDK documentation. Even the iPhone "Bible" (<u>Beginning iPhone Development</u>) only gives it a cursory mention.
Most of the configurations on a UITextField object is done through properties. In Part 1, I describe the properties used for modifying the behavior and look of text fields. In the follow-up <a href="http://osmorphis.blogspot.com/2009/04/configuring-text-fields-part-2.html">Part 2</a>, I describe the properties used to configure the virtual keyboard that is associated with each text field.
So on to the properties:
</div> <b><span style="font-family:Courier New;">adjustsFontSizeToFitWidth
minimumFontSize
</span></b>
<div style="margin-left: 40px;"> As you enter text in a text field and you reach the end of the field, it will scroll left so that what you are typing will stay visible. The following image shows what this looks like when entering a long input:
<div id="rb53" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_241cb8gpbfj_b" style="width: 314px; height: 54px;" />
The text at the beginning of the text field has scrolled to the left so that it is no longer visible.
If you want to support long input but not scroll, you can set the <span style="font-family:Courier New;">adjustsFontSizeToFitWidth</span> property to YES so that the font will reduce in size in order for the entire input to remain visible. Here is what a long line looks like with this option set to YES: <div id="x8gx" style="text-align: left;"> <div id="mito" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_243cgjgmhd6_b" style="width: 310px; height: 48px;" /> </div> See how the font got smaller? Of course, the font won't get infinitely smaller, else you wouldn't be able to read it. Once the font size reaches its minimum size, it begins to scroll. The text in the image above was the smallest it would get. The next character I typed started the field scrolling. While this technique helps a little, it really doesn't offer much more vertical space.
According to the documentation, there is another property called <span style="font-family:Courier New;">minimumFontSize</span> that allows you to specify what the minimum is before the shrinking stops and the scrolling starts. By default, this value is 0.0. But no matter how I changed this property, the font shrinking behavior never changed. This may be a limitation in the iPhone Simulator, as I did not try this on a real iPhone.
</div> </div> </div>
<b><span style="font-family:Courier New;">background</span> <span style="font-family:Courier New;">disabledBackground</span></b>
<div style="margin-left: 40px;"> The <span style="font-family:Courier New;">background</span> property allows you to provide a background image for the text field. The image will be scaled to fit the field. Here is an example of a text field with a custom background:
<div id="xdl9" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_244c59rf7c4_b" style="width: 310px; height: 50px;" />
Although it appears the image does not fill up the entire text field, be aware that my text field example lives inside a table cell, which has its own border around it.
The <span style="font-family:Courier New;">disabledBackground</span> property is similar, but is used when the text field is disabled. This property is ignored unless the <span style="font-family:Courier New;">background</span> property is also set.
</div> </div> <b><span style="font-family:Courier New;">backgroundColor</span></b>
<div style="margin-left: 40px;"> You can change the background color from the default white to any color. If you have a background image specified, it will override your backgroundColor settings. Here is a text field with a red background:
<div id="fuk:" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_2557zt2t8g7_b" style="width: 310px; height: 52px;" /> </div> </div>
<b><span style="font-family:Courier New;">borderStyle
</span></b> <div style="margin-left: 40px;"> <span style="font-family:Courier New;"><span style="font-family:Verdana;">If you have no background image, you can change the border style of the text field. This property can be set to one of four possible enums. The following image shows what the border style looks like with the enum name entered in the text field:
<div id="dq3h" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_245hnvdqtcm_b" style="width: 310px; height: 183px;" />
The default is UITextBorderStyleNone.
</div> </span></span> </div> <div style="margin-left: 40px;"> </div> <b><span style="font-family:Courier New;">clearButtonMode</span></b>
<div style="margin-left: 40px;"> This property allows you to put a little "x" button on the right to quickly clear out the contents of the text field. It looks like this:
<div id="mm66" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_247dz9kf4dd_b" style="width: 311px; height: 50px;" />
This property can be set to one of several enumerations, which determine when this clear button is shown:
</div> </div> <div style="margin-left: 40px;"> <div id="mm66" style="text-align: left;"> <ul> <li> <span style="font-family:Courier New;">UITextFieldViewModeNever </span> </li> <li style="font-family: Courier New;"> UITextFieldViewModeWhileEditing </li> <li style="font-family: Courier New;"> UITextFieldViewModeUnlessEditing </li> <li style="font-family: Courier New;"> UITextFieldViewModeAlways </li> </ul> </div> </div> <div style="margin-left: 40px;"> <div id="mm66" style="text-align: left;">
The WhileEditing enum will only show the button while you are editing that particular text field. The UnlessEditing enum will do the opposite: it will show the button when you are not editing the field, and hide it when you are editing. In this context, editing means that the field has the focus. Never and Always should be obvious. The default value is UITextFieldViewModeNever.
</div> </div> <b><span style="font-family:Courier New;">clearsOnBeginEditing</span></b>
<div style="margin-left: 40px;">
Here is another property for controlling clearing the contents of a text field. When this is set to YES, the field will remove whatever is there when it gets the focus. By default, this is set to NO.
</div>
<b><span style="font-family:Courier New;">enabled</span></b>
<div style="margin-left: 40px;"> By default, your text fields are enabled, meaning they can accept input. If for some reason you wanted to disable a text field (making it read-only), then set the <span style="font-family:Courier New;">enabled </span>property to NO.
Disabling a text field doesn't change its appearance. However, if you are setting a custom background via the <span style="font-family:Courier New;">background</span> property, and have also set a <span style="font-family:Courier New;">disabledBackground</span> property, then this latter property will go in effect if the text field is disabled.
</div>
<b><span style="font-family:Courier New;">font</span></b>
<div style="margin-left: 40px;"> This changes the font of the text inside a text field. It takes a UIFont object. Here is an example of setting the font to [UIFont italicSystemFontOfSize:16.0]:
<div id="iu50" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_248gq5s472m_b" style="width: 304px; height: 51px;" /> </div> </div> <div> <div style="margin-left: 40px;">
The default font is 12-point Helvetica plain.
</div> </div>
<b><span style="font-family:Courier New;">leftView</span> <span style="font-family:Courier New;">leftViewMode</span></b>
<div style="margin-left: 40px;"> These two properties allow you to put a view, like an image, on the left side of the text field. Any image will be scaled to fit the space. Here is an example of putting a little magnifying glass icon there:
<div id="ik5q" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_249gswsmbds_b" style="width: 315px; height: 51px;" />
Just setting leftView to an image is not enough, though. You also have to set the mode. The modes are the same as for clearButtonMode. The default is UITextFieldViewModeNever.
This property accepts any view, as the name implies, so you could even put a button here (this is how the clearButton does it).
</div> </div>
<b><span style="font-family:Courier New;">placeholder</span></b>
<div style="margin-left: 40px;"> When this is set to a string, it displays that text when there is no text in the text field. As soon as you start entering text, the placeholder disappears. It simply gives you a hint as to what is supposed to be entered in the text field. Here is what it looks like:
<div id="gzen" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_250crr4b2dt_b" style="width: 311px; height: 54px;" />
Notice how the font color is not so dark. By default, the placeholder is empty.
</div> </div>
<b><span style="font-family:Courier New;">rightView</span> <span style="font-family:Courier New;">rightViewMode</span></b>
<div style="margin-left: 40px;"> These two properties work the same as <span style="font-family:Courier New;">leftView </span>and <span style="font-family:Courier New;">leftViewMode</span>, except it deals with the space on the right hand side of the text field. Here is what that looks like:
<div id="cmpi" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_251xzk3mff7_b" style="width: 310px; height: 49px;" /> </div> </div>
<b><span style="font-family:Courier New;">text</span></b>
<div style="margin-left: 40px;"> This property contains the text that is displayed on the text field. It is a read/write property, so you can pre-populate the text in a text field before showing it. And, of course, you can read the text so you know what the user entered.
</div> <b><span style="font-family:Courier New;">textAlignment</span></b>
<div style="margin-left: 40px;"> The allows you to align the text in the text field horizontally. This setting also applies to any placeholder text. The allowed values are:
</div> <div style="margin-left: 40px;"> <ul> <li> <span style="font-family:Courier New;">UITextAlignmentLeft </span> </li> <li style="font-family: Courier New;"> UITextAlignmentCenter </li> <li style="font-family: Courier New;"> UITextAlignmentRight </li> </ul>
The default is UITextAlignmentLeft. Here are three text fields, each with a different <span style="font-family:Courier New;">textAlignment </span>setting:
<div id="hueb" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_253fkn4fwdx_b" style="width: 310px; height: 134px;" /> </div> </div>
<b><span style="font-family:Courier New;">textColor</span></b>
<div style="margin-left: 40px;"> You can change the text color from the default black. Here is an example of setting the text color to [UIColor redColor]:
<div id="tf9u" style="text-align: left;"> <img src="http://docs.google.com/File?id=ddkdktns_252fxr2qrfn_b" style="width: 310px; height: 50px;" /> </div> </div>
There you have most of the properties that affect the behavior and look of a text field. In the next part, I will cover the properties that have to do with the virtual keyboard.JEShttp://www.blogger.com/profile/05678402081101110580noreply@blogger.com0