Layout Manager, or is there a better solution? - iphone

I have a table view where cells can display a variable amount of information. For example, the first cell could display 2 labels, the next cell 5 labels, and the third cell could display 1 label. The cell contents are stored in managed objects.
I would like to make this data driven, where I have a plist to configure the cells. I'm thinking that I can create a layout manager that reads in the config data and can intelligently determine how to display the labels.
Is there a better way to do this with UIKit? I realize that ultimately I could use Core Text to do the text rendering, but I would like for that to be an implementation detail. For starters I'd be happy with just have UILabels that are dynamically setup.
EDIT:
One side effect of making this driven from a configuration file is that I could update these configurations after the app has been deployed. I might consider generated xib files for download as well, but ideally I'd like to only delivery binary plists.

If all you're doing is configuring a single kind of table view cell with a variable number of labels, it seems like that's just a one-off piece of code for laying out the right number of labels. I can't quite tell from your question what your experience level with doing programmatic layout it; if you're new to doing UI outside of IB, let us know.
Speaking to the more varsity idea of a "layout manager", do consider that the NIB/XIB system is effectively a data-driven layout engine itself. If you're thinking about something that's generic enough to specify explicit layouts and properties of views, consider that that's what XIB files basically are-- a schematized XML layout. See the command line tool ibtool's documentation (manpage here) to learn more about how you can manipulate them.
If your layout needs are specific enough to your app but too general to handle with a set of fixed XIBs, then consider a lightweight manager like you describe. But I would think hard before going off and building something super-generic. The equivalent of Zawinski's law here is that any layout manager will eventually end up incorporating more and more of the XIB functionality.

Related

Making an iPhone Application Configurable

For my application I have multiple customers. For each customer there is a different set of images and server URLs. To address this issue I have created customer-specific files. So according to the target selected, the specific file is used for getting the images and dynamically loading them in the UI. But this method works only in case of similar layout for each customer. So precisely saying, the method I am using currently is not scaleable.
Following are the issues which I am facing right now:
The real problem comes when I need to change the layout according to the customer. In case of few screens I can dynamically set the position of elements in UI but its not a feasible solution in case of several XIB files. What is the best industry standard to achieve this?
Addition/deletion/modification of a feature is an issue. Suppose I have a Tab bar in my application. To provide 6 features to a customer, I have 6 different TabBar items in the app. Suppose if one the customer doesn't want any one of the feature from those. Is using a simple if-else to suppress any specific tab a right way to achieve this?
My approach is to not use XIB files and create all objects programmatically.
I have plist configuration files which define the objects in the app going so far as to define:
1) if the app starts with a tabbar or not, (if so how many items, their names and what viewcontrollers they refer to),
2) the viewcontrollers and tableviewcontrollers,
3) any buttons or images or text fields within the view of each viewcontroller etc.
then each version of the app can have different plist files and associated resources.

Editable UITableViewCell having a left-aligned label

I am very new to iphone application development and am struggling to create a table view page where each row contains a left-aligned label with an editable text next to it - just like how it works in the email account details page in the settings application on my iphone.
I have been googling the subject for hours and it is now somehow clear to me that I need to add UITextFields to UITableViewCells, but it is still not at all clear to me how I make these text fields take up the right amount of space:
How do I make the text fields align above each other?
How do I make the text fields expand as far as possible to the right?
How do I prevent the text fields from hiding part of the left-aligned label?
Read the Apple Docs on Tableviews there are a number of predefined table cells. Also look at the Tableview programming Guide. Pick the one that has the font characteristics that you want and Apple will take care of it for you. Also, in the Settings app, the settings are a Grouped style.
For the look you are describing I think it is called UITableViewCellStyleSubtitle.
You need custom UITableViewCells and there are a number of ways of making them. For your purposes, any one of the techniques detailed in the Apple documentation will probably suffice.
An alternative to those approaches is in GSUtils (full disclosure: open-source library written by me), where you can use the same approach to designing your table view cells as you would design a UIView.

Rendering a Long Document on iPad

I'm implementing a document viewer with highlighting/annotation capabilities for a custom document format on iPad. The documents are kind of long (100 to 200 pages, if printed on paper) and I've had a hard time finding the right approach. Here are the requirments:
1) Basic rich-text styling: control of left/right margins. Control of font name, size, foreground/background color, and line spacing. Bold, italics, underline, etc.
2) Selection and highlighting of arbitrary text regions (not limited to paragraph boundaries, like in Safari/UIWebView).
3) Customization of the Cut/Copy/Paste popup (UIMenuController) This is one of the essential requirements of the app.
My first implementation was based on UIWebView. I just rendered the document as HTML with CSS for text styling. But I couldn't get the kind of text selection behavior I wanted (across paragraph boundaries) and the UIMenuController can't be customized from within UIWebView.
So I started working on a javascript approach, faking the device text-selection behavior using JQuery to trap touch events and dynamically modifying the DOM to change the background color of selected regions of text. I built a fake UIMenuController control as a hidden DIV, positioning it and unhiding it whenever there was an active selection region.
Not too shabby.
The main problem is that it's SLOOOOOOOW. Scrolling through the document is nice and quick, but dynamically changing the DOM is not very snappy. Plus, I couldn't figure out how to recreate the magnifier loupe, so my fake text-selection GUI doesn't look quite the same as the native implementation. Also, I haven't yet implemented the communication bridge between the javascript layer and the objective-c layer (where the rest of the app lives), but it was shaping up to be a huge hassle.
So I've been looking at CoreText, but there are precious few examples on the web. I spent a little time with this simple little demo:
http://github.com/jonasschnelli/I7CoreTextExample/
It shows how to use CoreText to draw an NSAttributedText string into a UIView. But it has its own problems: It doesn't implement text-selection behavior, and it doesn't present a UIMenuController, so I don't have any idea how to make that happen. And, more importantly, it tries to draw the entire document all at once, with significant performance degradations for long documents. My documents can have thousands of paragraphs, and less than 1% of the document is ever on screen at a time.
On the plus side, these documents already contain precise formatting information. I know the exact page-position of every line of text, so I don't need a layout engine.
Does anyone know how to implement this sort of view using CoreText? I understand that a full-fledged implementation is overkill for a question like this, but I'm looking for a good CoreText example with a few basic requirements:
1) Precise layout & formatting control (using the formatting metrics and text styles I've already calculated).
2) Arbitrary selection of text.
3) Customization of the UIMenuController.
4) Efficient recycling of resources for off-screen objects.
I'd be happy to implement my own recycling when text elements scroll off-screen, but wouldn't that require re-implementing UIScrollView?
I'm brand-new to iPhone development, and still getting used to Objective-C, but I've been working in other languages (Java, C#, flex/actionscript, etc) for more than ten years, so I feel confident in my ability to get the work done, if only I had a better feel for the iPhone SDK and the common coding patterns for stuff like this. Is it just me, or does the SDK documentation really suck?
Anyhow, thanks for your help!
Does your document have any semantic components other than each paragraph? If you already have some concept of sections or pages, I would recommend you render each one of those as an independent tablecell. It's pretty simple to create a tablecell that makes you forget you're actually looking at a UITableView. All you would need to do is override drawRect: and setSelected: and setHighlighted: and tah dah! No More cell dividers unless you want them. Furthermore you could do some nifty things by using a tableview as your base. If you defined sections in the UITableView then you could have a nifty header that scrolls along as you're paging through your document. Another thing you could do is add a "jump to section" bar / a bookmarks menu, and that way you don't have to provide selection across the boundaries of sections.
Massive copy paste blocks would be pretty painful on the system as well. Further, if you went through the trouble to provide this content you might not want to make it too easy for someone to copy it all at once... (Can't follow this line of thought more without more specifics on your project).
If you really do want to provide the copy paste options you could add buttons to each logical page or section that immediately selects and copies the whole section for the user's convenience. (Maybe with citation associated?)
I recommend you lookup the UITableViewCell UITableViewDelegate and UITableViewDataSource in the SDK docs as those pages will significantly help if you choose to use this suggestion.
Just two random observations:
Can you afford to create a paging interface? (As opposed to “endless scrolling”.) It looks like a paging interface would be a lot easier on system resources.
The UIActionBar is actually the UIMenuController class. The interface is a bit weird, as the menu is a singleton (wtf?), but I’m sure you’ll have no trouble figuring it out.
Hope that helps.
Here's a potential solution, but I don't know if it's crazy. Since I'm still so new to iPhone development, this might be a big no-no.
Anyhow, I had the idea to render each paragraph of the document (whose dimensions I've already precisely calculated) as a cell in a UITableView. Since UITableView already has mechanisms for cell recycling, I wouldn't have to implement that from scratch, and the document could be arbitrarily long without causing resource consumption problems.
Of course, I'd want to get rid of the line separators between cells, since I want the UI to look like a document instead of a table.
Or maybe I could render each page of the document (like a typical PDF, this is a paged-document format) as a table cell, and override the cell-separator graphic to look like a page boundary...
But would it be possible to get rid of the default touch behavior within the table, and instead implement text-selection on the table cell contents? Would it be completely impossible to implement text selection that crosses paragraph boundaries (between multiple table cells)?
The UIWebView is a good choise, but we need another application to pre render the pages percisely using each font and each style sheet and store the rendring information into a database table:
chapter_id int primary key,
startlocation int,
end location int,
fontsize int (or stylesheetname string)
Using JavaScript we can calculate how many words fit in a div with out scrolling.
UIWebView is good as it provide rich content and it has selection and highlighting behavior.
Hope this helps.

UITableViewCell textLabel and detailTextLabel tags?

I am designing an interface that basically looks the same as the Settings application. That is, I have a grouped TableView with cells that look like UITableViewCellStyleValue1. There are labels with values associated with them. The difference is, I am making custom UITableViewCell nibs so that the "value" can be a textbox, segmented control, etc., just like in the Settings app.
To keep my code general, I am giving each label a tag of 1, and the associated value a tag of 2. I would also like to incorporate generic UITableViewCells without having to use a special case. Are there default tags associated with the textLabel and detailTextLabel views with which I can match my customs cells? Other design suggestions are welcome too.
You may benefit from the hard work already done by people to achieve this:
http://furbo.org/2009/04/30/matt-gallagher-deserves-a-medal/
That blog post links to a Generic Table Views set of classes that really make this kind of interface simple to create. I use it in my own apps and it's perfect.
The only thing you'll need to do is rename some of the method calls to update them from 2.x APIs to 3.0 (replace initWithFrame:reuseIdentifier: to initWithStyle:reuseIdentifier: on the table cells).
Nice and simple, and looks great.

Settings-style grouped table

So it's trivial to create a Settings style table on the iPhone. The problem is, they add a great deal of code as your Settings have a gamut of options/styled cells. One section might have a check list, another might have cells with accessory disclosures to drill down further, another might be labels with UITextFields.
My question here is, what's the cleanest way to go about creating this table. Do you typically create a subclass of UITableViewController and then subclass UITableViewCell for each different type of cells, and write supporting classes for those cells? Meaning if you have a Settings style table with 4 sections, all different types of cells, you will load 4 nibs into the table and import 4 class files? Programmatically set the frame, views, textfields and tag them for later access?
The answer(s) to this is probably subjective, but I'd like to know what you experts consider the most elegant approach to this common problem.
The easiest way to do this is to simply add your controls during the tableView:cellForRowAtIndexPath: method.
I also recommend this to help corral your code:
A technique for using UITableView and retaining your sanity
I would rather set most of the settings that I can in Interface Builder, instead of writing a whole bunch of code to make the visual/layout just right. As you can imagine, it will take quite a few rounds of "modify - build - test" in the iPhone Simulator to get this special table view laid out the way you want it.
I feel it's probably a bit easier to do all of these rough visual changes in IB, then load all of the custom UITableViewCell dynamically via their identifiers in code. You could then do one final round of tweaking on this code, if something that you want is not doable in IB.
Three20 library (extracted from Facebook iPhone app) has a set of ready-made cells that contain various controls.
(Not sure you want to use them, however. Three20 suffers from “not-invented-here” a little bit and tries to subclass and extend everything, so adding it adds quite a bit of a mess to your project. But at least you can use it as an example.)
P.S. Your question inspired me to open a “What are your favourite UITableView / UITableViewCell tricks?” thread on Stack Overflow, check it out for more tips.