{"id":26869514,"url":"https://github.com/jakemarsh/jmstaticcontenttableviewcontroller","last_synced_at":"2025-08-25T01:05:02.762Z","repository":{"id":56916292,"uuid":"2539652","full_name":"jakemarsh/JMStaticContentTableViewController","owner":"jakemarsh","description":"A subclass-able way to cleanly and neatly implement a table view controller much like those in Settings.app, with nice-looking fields to collect or display information, all using a simple and convienent block-based syntax.","archived":false,"fork":false,"pushed_at":"2015-10-18T09:29:21.000Z","size":441,"stargazers_count":242,"open_issues_count":4,"forks_count":44,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-08-23T05:37:23.739Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://deallocatedobjects.com/posts/create-static-content-screens-with-jmstaticcontenttableviewcontroller","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jakemarsh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-10-08T19:33:48.000Z","updated_at":"2025-07-29T22:18:45.000Z","dependencies_parsed_at":"2022-08-21T03:50:47.831Z","dependency_job_id":null,"html_url":"https://github.com/jakemarsh/JMStaticContentTableViewController","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/jakemarsh/JMStaticContentTableViewController","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakemarsh%2FJMStaticContentTableViewController","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakemarsh%2FJMStaticContentTableViewController/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakemarsh%2FJMStaticContentTableViewController/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakemarsh%2FJMStaticContentTableViewController/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jakemarsh","download_url":"https://codeload.github.com/jakemarsh/JMStaticContentTableViewController/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakemarsh%2FJMStaticContentTableViewController/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271989730,"owners_count":24854702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-31T06:17:36.852Z","updated_at":"2025-08-25T01:05:02.731Z","avatar_url":"https://github.com/jakemarsh.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv style=\"width:852px; height: 489px; position: relative; margin: 30px auto;\"\u003e \n\u003cimg style=\"position: relative; width: 852px; height: 489px; margin: 0;\" src=\"http://cl.ly/270g1q1e012L1l3n3H0u/GithubHeader.gif\" alt=\"JMStaticTableViewController\"/\u003e\n\u003c/div\u003e\n\nA `UITableViewController` subclass that allows you easily and simply display what I call \"static content\". An example of such content is what is found in iOS's built-in Settings application. Or a  simple \"About\" screen. Or a \"Login\" screen. Or any number of simple screens that might display or collect information.\n\nAll this is done using some really cool methods that use blocks. It also allows you to easily create `UITableViewControllers` that collection information.\n\nIt is very much a library in the making. It is quite functional and usable already, as you will see if you read on, however, there is a TON more that *could* be done with this library, I'd love to hear where everyone thinks it should go and how it could best be adapted to fit everyone's needs.\n\nThat being said, `JMStaticContentTableViewController` might not be for everyone, but if you've ever built a whole `UITableViewController` implementing full `UITableViewDataSource` and `UITableViewDelegate` methods, and so on, and so on, then you likely know how much time this library could save you. \n\nKeep reading for some awesome stuff.\n\n## Requirements\n\nYou'll need to build your project that is using `JMStaticContentTableViewController` with a compiler that supports Automatic Reference Counting. Your project does not have to use ARC to use this library. [Read More Here](#arc) \n\nAlso of note, `JMStaticContentTableViewController` supports iOS 5 and up.\n\n## Example Usage\n\n### Adding a section and a cell\n\nHere's a simple example of adding a section and a cell to your `UITableView`. You would likely write this code inside your `viewDidLoad` method inside your `JMStaticContentTableViewController` subclass.\n\nNote that you are passed in some very important objects, `JMStaticContentTableViewSection`, `JMStaticContentTableViewCell` and a `UITableViewCell`. You can configure the `UITableViewCell` exactly as you would normally. We also use the `JMStaticContentTableViewCell` object to setup things like `UITableViewCellStyle` and the reuse identifier.\n\n`JMStaticContentTableViewSection` also allows you to setup things like the section titles.\n\nAs you can see we also get a nice looking `whenSelected:` block, this allows to write code that will be run whenever our cell is tapped, a perfect place to, for example, push on a `UIViewController`.\n\n``` objective-c\n- (void) viewDidLoad {\n\t[super viewDidLoad];\n\n\t[self addSection:^(JMStaticContentTableViewSection *section, NSUInteger sectionIndex) {\n\t\t[section addCell:^(JMStaticContentTableViewCell *staticContentCell, UITableViewCell *cell, NSIndexPath *indexPath) {\n\t\t\tstaticContentCell.cellStyle = UITableViewCellStyleValue1;\n\t\t\tstaticContentCell.reuseIdentifier = @\"DetailTextCell\";\n\n\t\t\tcell.textLabel.text = NSLocalizedString(@\"Wi-Fi\", @\"Wi-Fi\");\n\t\t\tcell.detailTextLabel.text = NSLocalizedString(@\"T.A.R.D.I.S.\", @\"T.A.R.D.I.S.\");\n\t\t} whenSelected:^(NSIndexPath *indexPath) {\n\t\t\t[self.navigationController pushViewController:[[WifiViewController alloc] init] animated:YES];\n\t\t}];\n\t}];\n}\n```\n\n### Inserting A Cell At Runtime\n\nThis will behave just like `addCell:` above, except it will animate nicely into place.\n\n``` objective-c\n- (void) _someTaskFinished {\n\t[self insertCell:^(JMStaticContentTableViewCell *staticContentCell, UITableViewCell *cell, NSIndexPath *indexPath) {\n\t\tstaticContentCell.reuseIdentifier = @\"WifiNetworkCell\";\n\t\tstaticContentCell.tableViewCellSubclass = [WifiNetworkTableViewCell class];\n\n\t\tcell.textLabel.text = network.networkName;\n\t\tcell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;\n\t\t\n\t\tcell.indentationLevel = 2;\n\t\tcell.indentationWidth = 10.0;\n\t} whenSelected:^(NSIndexPath *indexPath) {\n\t\t// TODO\n\t} atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES];\n}\n\n```\n\n### Inserting Multiple Cells At Runtime\n\nSame as above, except here we're wrapping our work in calls to `beginUpdates` and `endUpdates`, again retaining all of our `UITableView`'s built in \"magic\" while still getting to use our nice, convienent syntax.\n\n``` objective-c\n// Somewhere else you'd probably load some data somehow,\n// then want to insert rows for the new items in that data.\n\n// Normal table view functionality is completely retained, for example,\n// here we're inserting a bunch of cells inside a beginUpdates/endUpdates block\n// so all our new cells will animate in simultaneously and look awesome.\n\n[self.tableView beginUpdates];\n\nfor(SomeModelObject *o in self.awesomeModelObjects) {\n\t[self insertCell:^(JMStaticContentTableViewCell *staticContentCell, UITableViewCell *cell, NSIndexPath *indexPath) {\n\t\tstaticContentCell.reuseIdentifier = @\"SomeCell\";\n\t\n\t\tcell.textLabel.text\n\t} atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES];\n}\n\n[self.tableView endUpdates];\n\t\n```\n### Animation\n\nAnytime you ask `JMStaticContentTableViewController` to animate the inserting or deleting of cells or sections, it will use the `UITableViewRowAnimation` style of `UITableViewRowAnimationAutomatic` under the hood, so all of your animations will look great. This style was added in iOS 5.\n\n## Example App\n\nSo for fun (and to aid me in developing the library, determine its needs) I started using `JMStaticTableViewController` to attempt to re-create the built-in iOS Settings application. This exists in a sort of \"half-finished\" state inside this repo.\n\nSome things to try in it are: \n\n* Wi-Fi, go into the Wi-Fi section and notice how the rows appear after \"searching for networks\" (this is obviously simulated). Also try disabling and re-enabling Wi-Fi. Notice how the rows appear and disappear with correct animations. \n\n* The Notifications section also demonstrates showing some content.\n\n* Cells that shouldn't be \"selectable\" (like cells containing `UISwitch` controls) aren't selectable.\n\n* Normal `UITableViewDelegate` methods still work, so implementing things like like adding a `UIActivityIndicatorView` next to a section title are no more or less complicated than before.\n\nIt is, like I mentioned, unfinished, meant mearly as a tool for you to checkout and get some perspective on how the library might be used in the \"real world\". More completion of the example as well as any other examples are very welcome, please feel free to submit pull requests.\n\n### Screenshots\n\n\u003ccenter\u003e\n\u003cimg src=\"http://cl.ly/IKD6/iOS%20Simulator%20Screen%20shot%20Jul%2025,%202012%207.08.00%20PM.png\" width=\"320\" /\u003e\u0026nbsp;\u0026nbsp;\n\u003cimg src=\"http://cl.ly/IKjt/iOS%20Simulator%20Screen%20shot%20Jul%2025,%202012%207.08.01%20PM.png\" width=\"320\" /\u003e\u0026nbsp;\u0026nbsp;\n\u003cimg src=\"http://cl.ly/IKkO/iOS%20Simulator%20Screen%20shot%20Jul%2025,%202012%207.08.02%20PM.png\" width=\"320\" /\u003e\u0026nbsp;\u0026nbsp;\n\u003cimg src=\"http://cl.ly/IKcB/iOS%20Simulator%20Screen%20shot%20Jul%2025,%202012%207.08.04%20PM.png\" width=\"320\" /\u003e\u0026nbsp;\u0026nbsp;\n\u003cimg src=\"http://cl.ly/IKMS/iOS%20Simulator%20Screen%20shot%20Jul%2025,%202012%207.08.07%20PM.png\" width=\"320\" /\u003e\n\u003c/center\u003e\n\n\n## iOS Version Compatability\n\n`JMStaticContentTableViewController` supports iOS 5 and up.\n\n## Adding To Your Project\n\n### CocoaPods (The New Easy Way)\n\nIf you are using [CocoaPods](http://cocoapods.org) then just add this line to your `Podfile`:\n\n``` ruby\ndependency 'JMStaticContentTableViewController'\n```\n\nNow run `pod install` to install the dependency.\n\n### Manually (The Old Hard Way)\n\n[Download](https://github.com/jakemarsh/JMStaticContentTableViewController/zipball/master) the source files or add it as a [git submodule](http://schacon.github.com/git/user-manual.html#submodules). Here's how to add it as a submodule:\n\n    $ cd YourProject\n    $ git submodule add https://github.com/jakemarsh/JMStaticContentTableViewController.git Vendor/JMStaticContentTableViewController\n\nAdd all of the files inside the folder named \"JMStaticContentTableViewController\" to your project.\n\n### ARC\n\n`JMStaticContentTableViewController` uses [Automatic Reference Counting (ARC)](http://clang.llvm.org/docs/AutomaticReferenceCounting.html). You should be using ARC too, it's the future. If your project doesn't use ARC, you will need to set the `-fobjc-arc compiler` flag on all of the `JMStaticContentTableViewController` source files. To do this in Xcode, go to your active target and select the \"Build Phases\" tab. In the \"Compiler Flags\" column, set `-fobjc-arc` for each of the `JMStaticContentTableViewController` source files.\n\n### \"This Library is Bad, and You Should Feel Bad\"\n\n\u003ccenter\u003e\u003cimg src=\"http://cl.ly/Oun7/Unknown.jpeg\" title=\"This Library is Bad, and You Should Feel Bad\" /\u003e\u003c/center\u003e\n\nThis is my first try at building a system like this for this purpose, there are already a ton of things I plan on \"fixing\", improving, and re-doing. I wouldn't really be a good developer if I didn't hate all my code once I was done would ? ;)\n\nI'm totally open to suggestions/fixes/hate mail/etc just let me know in a pull request, issue or even on twitter, I'm [@jakemarsh](http://twitter.com/jakemarsh).\n\nThat being said, this is a very opinionated library. It makes assumptions and defines conventions that might not fit perfectly with everyone's codebase or app. If you are one of those people, please feel free to submit a pull request so we can talk about it and maybe get some of your desired changes worked in.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakemarsh%2Fjmstaticcontenttableviewcontroller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjakemarsh%2Fjmstaticcontenttableviewcontroller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakemarsh%2Fjmstaticcontenttableviewcontroller/lists"}