What is something you wish you had known sooner about the iPhone SDK? - objective-c

I'm interested in picking up some tips and tricks while learning about the SDK. What I am looking for something that you wish you had known getting started that would have benefited you now.

don't use a DOM parser, but a SAX parser. (Memory issues / speed).
if you use custom table cells, don't add too many views. (Slow scrolling issues)
if you add views to table cells, like labels, you may want to make their background opaque.
the generated table view code defeats the MVC paradigm. Think about your data model, and implement an UITableViewDataSource. Really.

One of the things I wish I knew at the very beginning was how to download data in a non-blocking way, specifically using NSURLConnection. The first versions of my apps suffered somewhat because I was using things like dataWithContentsOfURL:, which isn't a great idea on the iPhone, since you're never really sure what the network environment will be like for your users. To make it worse, I was testing over a fiber connection at home with an iPod touch, when a large number of my users were using Edge on their iPhones.

If you want to use SQLite, go with either Core Data (available in 3.0) or FMDatabase (Flying Meat). My first two apps, I wrote a customer wrapper and bound directly to SQLite. I am currently using FMDatabase with a new application and have found the experience much nicer.

In the case of a lot of developers, including Google, I'm sure they wish they knew their app would be rejected once complete.

CoreData Bindings is not supported on the phone.

Use the Clang Static Analyzer
http://clang-analyzer.llvm.org/
It's great for finding reference counting issues -- I have never seen a false positive.

Regarding the table view speed check out Loren Brichter's blog post http://blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview/

Related

How to use Core-Data best in complex Apps

I am a Mac App Dev and have some questions about how to use Core-Data correctly.
I have multiple TableViews and they are all playing around with the same data (which I want to save persistently with Core-Data). I know the central part of Core-Data which I have to work with - NSManagedObjectContext and I know how to create NSManagedObjects and save/edit/delete these in the persistent store.
But actually I'm wondering about how to organize all that together with multiple ViewControllers,Views,Tables,.. efficiently and without merge conflicts. I've read about some approaches for that: one was by passing the context down from the delegate through every layer of your code. Somebody else suggests to create a singleton-class, let's call it DatabaseManager, which holds the NSManagedObjectContext instance and you go and ask it from there. (I especially like this approach, don't know why.) Or just ask the delegate every time with [[NSApplication sharedApplication] delegate], does this have any disadvantages?
Okay, a lot of questions here but that was only about the How. Now I want to know about your recommendations of where I should actually do all interaction with the managedObjectsContext. (to be in compliance with MVC and don't mess up my code and make it more complicated than it has to be..)
Should I save stuff to Core-Data in my NSTableViewDelegate/-DataSource Classes directly or just fire up an Notification for someone else?
Should I implement some instance methods for my Model-Objects (like -(void)saveInstanceToDatabase,..) to encapsulate Core-Data-Interaction?
Ok thanks in advance for all the brave guys who read until this point and give me some kind of response :D I always appreciate code-examples!
After years of working with Core Data... I've come to the conclusion it's not very good. There are some serious flaws in it's design that can only be solved properly by abstracting the whole thing away.
I recommend implementing your own model for manage objects, which uses core data underneath but does not ever expose it.
Your views and controllers and application delegate and all of that should not ever touch core data at all. They should talk to a series of classes you create yourself, which has been custom tailored for your particular application.
That object layer can use core data underneath, or it might use something else like FMDB or NSCoding or even just plain old NSData objects (this is the fastest option, if you need extremely high performance with large amounts of data, especially when combined with features like NSDataReadingMappedIfSafe).
Start with Core Data. Look at the other options if you have problems. Having your own layer on top means you can easily abandon it in future. And many developers have chosen to move away from Core Data shortly after their app ships to the public. Often due to unsolvable bugs or performance issues.

Need general directions to the idea for 'Bookshelf' app - table or scroll?

I'm currently stack at creating an app.
Our requirement is to make "book viewer" app similar to the iBooks. Each of the book is just series of images (JPEG or PNG) and not a pdf. So it's more like an image viewer in a sense.
The main view is going to be like "horizontal tableview", which the user can scroll horizontally the covers of the books, click it to download and open the book (which led to another page view). The row for the cover should be at least two since there's two "type" is set for the books. This part is more like a "pulse-style" bookshelf with UI similar to this.
When I thought of how to implement this behaviour, I found the way with UITableView just as described here. However, as an objective-c beginner, it's little complicated for me to use this, and our requirement has also each "cell" must have multiple buttons to set each book as "favourite" or "downloaded" etc... and this could be more complicated if I choose to use the UITableView.
So I came to think of using UIScrollView to line up the book covers, embedding each cover as an UIImageView with buttons. But I really don't know if this is the right direction, sicne the UIScrollView has no "reload" function, and the requirement also stated that the user should be able to find the books by using "search bar" at the head of the bookshelf view.
As you can see, I'm completely confused and depressed because I don't know how can I achieve this. I searched around google and several answers here at stackoverflow suggest using AQGridView or EasyTableView. They are both great, but again too complicated to implement these into our requirement...
Which way, or how should I implement this dynamic "pulse-style" bookshelf like feature?
I think my question is a bit vague, but I'm also not clear what to ask here because I really don't know how to do this. The Android version of this app is already achieved this requirement with fairly simple and easy to understand codes (since I have some experience in Java), but for this Objective-C, everything seem needlessly complicated...
Any help would be appreciated.
Thank you.
<preachy>The fact is that you have made a mistake by trying to make this app with a complex interface full of non-standard UI components when you are “an objective-c beginner”. I understand that this may not have been your decision; it may have been forced on you by the guy that signs your paychecks. Nevertheless, it is not reasonable to expect that you can just implement this app before you've spent the time working through tutorials and reading documentation for the programming language and libraries required to build it. We all have to learn the alphabet before we can start writing limericks.</preachy>
That said, if your app can require iOS 6, and you can take the time to learn a bit of Objective-C and iOS programming, it sounds like this would be pretty easy using UICollectionView. Apple did a couple of sessions about this powerful new class at WWDC 2012. I recommend you watch the videos:
Session 205 - Introducing Collection Views
Session 219 - Advanced Collection Views and Building Custom Layouts
You can also easily find some tutorials about UICollectionView using your favorite search engine.
Take a look at Collection View's
You can even download some sample code to see how a grid layout can be accomplished.

iOS - updating user flow without app update

I'm looking at designing and building out a system that would allow A/B testing of different flows in an iOS app (e.g. registration flow, log-in flow, purchasing flow).
A system that comes to mind initially looks like:
app pings server, server responds giving list of resources (which could include some links to xib files)
if the user does not have those xibs on disk, download them and save them to disk
when the view controller is presented, load from the xib if it has been downloaded (else default to the one the app was shipped with)
Does anyone have any thoughts on this idea or any insights on this system?
NOTE: I am not trying to implement a system where I can add new features. Right now, I'm focusing on changing flows, like the text and views a user will see. I'm not looking into a discussion of whether this violates the App Store rules, but if you would like to do so - go for it!
This is possible, but I don't know if I would download XIBs to the device. Seems a little risky to me.
Apple did a talk at WWDC 2010 where they address this exact issue, and they recommend building the interface using (more or less) Plists or JSON to describe the UI elements and their functions, and building up the views dynamically. It's well worth watching as it brings up a lot of smaller issues that aren't immediately obvious, but it requires a developer account to access it).
This would be an interesting system to use. I wonder if one could write a shell script to replace the old binary of an app with a new one. I know it would probably be more complicated then just that, but it would be cool to do. I would definitely use this for in house apps, or personal tools. Its to bad the apple wouldn't allow it, unless someone could secretly slip it past them :-)
I say go for it. You seem to have a pretty good idea of what you want to do and how you want to do it. Changing the UI based on responses from a server isn't uncommon, but I guess downloading xib files from the server is. I don't see why it wouldn't work though and I don't think it would be rejected by Apple, but you never know.

Use SQLite, plist, or something else?

This is more of an opinion question than technical.
I am writing a basic app to get into UIKit, MapKit etc. I want to store some basic information such as location data, some strings etc, nothing crazy and not too many (several hundred). I wondered if I should go with SQLite or use plist files? I will release app updates, so don't want anything where data would be lost.
I'm leaning towards SQLite, but wanted to ask the opinion of people in the know first.
If you'd like to know more about the app to help make a decision, just holler. :)
You could use NSUserDefaults. They are simple to use and you can create them on the fly. If the user deletes the app, the prefs will be deleted, but if they simply install a new version on top, the prefs will remain.
A really good method to store persistent data on iOS devices is the Core Data framework. Check out this tutorial for a good introduction. There is also a good comparison here of the different data storage types. Hope that helps!

Good database library/ORM for cocoa development

I am developing a cocoa application that will be making heavy use of both web services and a standard dbms (most likely MySQL) and I am wondering if anyone has a good option for a database library or ORM solution they have used. CoreData is not an option due to the need to support a standard DBMS and to be able to modify the data outside of the normal application operation.
I have found a number of possible options from new open source libraries:
http://github.com/aptiva/activerecord/tree/master
To writing my own wrapper for the C MySQL api.
Any advice is welcome,
Thanks!
Paul
We faced a similar question when we first started work on Checkout, our solution was to code the entire app in Python, using PyObjC.  Checkout 1 had an sqlite backend, Checkout 2 has a postgres backend.
There are a couple of really mature and powerful ORMs on the Pyton side, such as SQLObject, which is pretty simple to work with (we used it for Checkout 1.0) and SQLAlchemy, which is more powerful but a bit harder to wrap your brain around (we used it for Checkout 2.0).
One approach you could evaluate, is building the application in Objective-C, but writing the data model and database connectivity/adminstration code in Python. You can use PyObjC to create a plugin bundle from this code, that you then load into your app  That's more or less the approach we took for Checkout Server, which uses a Foundation command-line tool to administer a postgres server and the databases in it, this CLI tool in turn loads in a Python plugin bundle that has all of the actual database code in it.  End-users mostly interact with the database through a System Preferences pane, that has no clue what the database looks like, but instead uses the command-line tool to interact with it.
Loading a plugin is simple:
NSBundle *pluginBundle = [NSBundle bundleWithPath:pluginPath];
[pluginBundle load];
You will probably need to create .h files for the classes in your bundle that you want to have access to from your Obj-C code.
You might also want to check out the BaseTen framework. It is a Core Data-like framework (in fact, it can import Core Data models), but works with PostgreSQL (though not MySQL, as far as I know). It includes some very nice features such as schema discovery at run time. It also includes an NSArrayController subclass that automatically handles locking and synchronizing across multiple users, so you can continue to make use of Apples Key-value Binding in your UI.
I have personal experience with this particular problem. I even started down the road of writing my own wrapper for the C MySQL API.
The eventual conclusion was: Don't!
The solution that worked in my case was to communicate with the MySQL server via PHP. If you are familiar with web services, chances are that you know about PHP, so I don't won't go into loads of detail about that.
To read from the database:
The cocoa app sends a request for a URL on the server: http://theserver.com/app/get_values.php
The get_values.php script handles the database query, and returns the data in xml format
The cocoa app loads and parses the xml
To write to the database:
The cocoa app sends a more complex request to the server: http://theserver.com/app/put_values.php?name="john doe"&age=21&address=...
The put_values.php script parses the input and writes to the database
The beauty of this solution is that PHP is great for working with MySQL, and cocoa has some handy built-in classes for working with XML data.
edit: one more thing:
One of the key things you have to figure out with this approach is how much processing should be done on the server, and how much should be done in the app itself. Let cocoa do the things that cocoa is good at, and let PHP and MySQL do the things that they are good at.
You could write a generic PHP script to handle all queries: perform_query.php?querystring="SELECT * FROM .....", but that is hardly an optimal solution. Your best bet is several smaller PHP scripts that handle individual datasets for you. In my case, there was one to get the list of users, one to get the list of transactions, etc. Again, it all depends on what your app is going to do.
GDL2 is a nice example, based on EOF.
Instead of reinventing the wheel by writing your own communication wrapper to deal with MySQL from Cocoa, you could try the SMySQL framework (a.k.a. MCPKit), it was part of the CocoaMySQL application that evolved into the Sequel Pro project. It works with varying versions of MySQL, and seems to be quite robust.
If you need to understand how to incorporate it into your application, there's not much documentation around, but it has an easy to understand interface and you can see it working by looking at the source of Sequel Pro, which is downloadable from Google code.
There is also the CocoaMySQL-SBG fork of the CocoaMySQL project, but that seems to be out of date and I couldn't get it to build properly.
I've also implemented a simple object persistence framework based on sqlite, but it certainly wasn't trivial to do. I agree with eJames' conclusion- don't implement one yourself if you don't have to.
If you aren't committed to programming in Objective-C you might want to take a look at PyObjC which would allow you to program the database portion in Python. You can use the MySQLdb module for DB access and there are plenty of tutorials online for its use. It isn't hard to stuff the data back into Cocoa/CF classes and pass them back to your app.
The main caveat with PyObjC is that at the moment it doesn't work with Tiger.