I've been playing around with iOS development and I'm getting to the stage where I want to create something beyond a simple app. However, I'm not confident that I understand how to partition an application correctly.
For the purposes of simplicity, imagine a (very) simple audio player application. Let's say there are two view controllers, accessible via a UITabBarController which is instantiated the main AppDelegate class.
Each of these view controllers has the following responsibility:
PlayerViewController - A sound player which plays the “current” audio sample when the user presses a button.
SelectorViewController - A sample selector, that uses a UIPickerView to display the available audio samples so that the user can select which sample they want to play.
So far, so good. However, what I don't quite understand is where I should store the data on the available samples, so that both of the views can find out information on the available samples, trigger a sample to play, etc.
As both view controllers need to access this “model level” information, would creating an “audio manager” singleton class be a sensible approach, or is there (much, much more likely I'm guessing) a better means of solving this problem that I'm overlooking.
Any pointers would be much appreciated.
I've used this pattern (Singleton data manager) several times in serious apps. It's quite straightforward, easy to understand, easy to use, although this pattern is despised by OOP purists.
If nobody tells you it's wrong to use a singleton, go ahead, just be sure to check Apple's documentation on the recommended implementation (there is a bunch of methods to overload).
Oh and BTW, Apple uses it a lot in the iOS SDK, so it's a common practice (see class methods beginning with 'shared').
UPDATE:
Another possibility is reusing an already existing singleton, the Application delegate for instance. It might feel cleaner, or not, it's more a matter of taste. It has the advantage of giving a clear "entry point" where you allocate/create/init your data manager.
If the source of your data is in a remote server and it comes to your app as an XML file, you can also get it whenever you want with a kind of source downloader class.
That way you don't have to care about keeping things in memory when they are not necessary. Just get it from the remote source, parse it and then release it.
Another way of achieving this more careful use of memory is to get your data from a sqlite database using Core Data. But some people thinks it is too much complicated for a simple app and prefer running queries by hand.
Related
I got a few questions about Objective-C structure. I think I can not figure out the entire structure.
Am setting up connection to the server. Using FacebookSDK and ASIHTTPRequest and SBJSon. I use almost in all classes. FacebookSDK appDelegate used to. I use the same functions is too. For example, take a different user profile.
Do I have to collect one class of functions of Request? How do I do?
In terms of performance, whether programmatically or xib files do I use?
Your performance is the most important. XIB files are almost always going to take you less time to create and debug. I guarantee you that talking to the server is going to take far more run time than loading objects from a .xib.
I developed an application for iphone, and made all my setters and getter, and handled sqlite3 database (select, insert, delete, update) in AppDelegate.m
I made AppDelegate Object and used all around my application, I felt that my application started to give strange errors, and heaviness, crash.
then I made another class as DataManagement, then I used it and rotate objects, now there is no error, nothing like crash,,,,
I want to know from you seniours that what is best way to handle getters and setters and database in iphone programming?
any other good way, so that application became now too much heavy at all,,,,
Reading about the Model-View-Controller pattern is a good starting point when learning about application design.
Apple provides a really good document in it's "Cocoa Core Competencies" series:
http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MVC.html
A general MVC description can be found in Wikipedia:
http://en.wikipedia.org/wiki/Model–view–controller
I'm sorry for being a bit harsh here, but it appears like you've not yet understood the basic concept of object oriented programming, if initially you tried to implement a whole application within your application delegate.
I don't think that telling you how to create accessors or how to use Core Data (I believe this is what you meant) will help you unless you've spend some time reading through some of the basics (although accessors are a part of the basic stuff).
As a start, I'd like to recommend reading this Guide about the Objective-C language and going through some basic tutorials and example projects.
So new to objective-c and iphone/ipad development. Trying to get my feet wet with a simple app to connect to one of our apis.
Right now I have a view with a user name and password input and button to submit. When it's clicked I grab those and try to authenticate against our server with a simple post call. I have that working using the NSURL stuff. I originally had it working by declaring the delegate methods for NSURLConnection in my view controller. Once I confirmed it was working properly I knew I needed to get that stuff out of there.
So I created a new class ApiLogin which has a method:
(void)authenticateWithUser:(NSString *)username andPassword:(NSString *)password
which does the post and then this object has the delegate methods declared and handles all that stuff. The next problem I ran in to was how to get any info back to the view controller. Since these were asynchronous calls I couldn't just have my method return data. So after some digging I tried out a solution that seemed to make sense. I created a custom delegate for my newly created class
(void)loginDidFinish:(NSString *)login
Which my view controller declares and uses. This worked perfectly.
So my question now is... am I going down a rabbit hole or is this good? I don't want to create a suite of classes or a class with children classes to handle server communication and data handling with a dozen of these delegate functions if that's bad form. Basically I'm asking, am I doing this right? Is there a better way? I feel like I've been given a new tool, and I see every problem as a chance to use that tool to solve it and don't want to make that mistake. Since I'm really new to iphone/ipad development and it's been a long time since I've done any serious C coding I feel a bit lost with some of this stuff.
That seems fine to me. The other solutions that come to mind would be to have your view controller observe a model object using Key-Value Observation and update accordingly, or to use an NSNotification when login is complete.
It's perfectly reasonable for your view controller to be the delegate for items it is controlling. I would only break it out and make it it's own class if you needed to use the same methods in several view controllers, and the delegate methods were very complicated.
You may find this link helpful, since it seems to be talking about a similar situation to yours where the author used delegates:
http://css.dzone.com/articles/do-not-publishcreating-your
Also, this Apple page might be a good read as well if you are curious about different ways in which objects can communicate with each other:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html
The best way to be confident that you are using the right strategy, beyond simply asking other people for confirmation, is to make sure you understand the definition and purpose behind delegation, and then analyze your code from that perspective to see if its a good fit for what you are trying to do. Excerpt from Wikipedia:
In software engineering, the
delegation pattern is a design pattern
in object-oriented programming where
an object, instead of performing one
of its stated tasks, delegates that
task to an associated helper object.
( http://en.wikipedia.org/wiki/Delegation_pattern )
Considering all that, I think you're on the right track with what you're currently doing.
If I have a tab bar app, and plan on using Core Location in different tabs, is there a good common place to put the code used to alloc/init the CLLocationManager, and get the updates once startUpdatingLocation is called? Or if it's going to be used in two different tabs, do I then just put it in the code for each tab? Just wondering what best practices are since I am new to programming. Thanks.
I don't agree with John, the AppDelegate is the "easy" way to do it, but not always the better.
I would do this with a singleton. You can look at Matt Gallagher's article on Singletons, AppDelegates and top-level data for reference.
if you notice you're duplicating what you've written, or faced with writing code which exists, consider creating an interface (object, set functions, etc.) to handle these tasks.
see DRY (do not repeat yourself). there will be a lot of duplicate functionality by the time you've written a few apps. it's best to write it once, and to write that correctly.
here are some high level guidelines:
don't put app-specific features in a common interface (instead, use a subclass shared by the 2 projects)
always keep your bases free of hacks (unless you're dealing with an issue in the system libraries). if clients (e.g., subclasses, callers) need a particular workaround or require a specific check, then it is better to make them handle it.
use assertions to ensure they use the interface as intended, check every argument, precondition/postcondition, the state of your object, etc..
keep your objects/interfaces very small and maintainable, with a clear purpose of their intended use. naturally, this will result in a higher number of objects.
avoid the urge to use singletons and static data; there's almost always a better way even if it's as simple as forcing clients to create an instance of your class.
create libraries with these interfaces, and divide them logically.
now that that's covered…
i'd begin by using (potentially multiple) instances of the objects you'll need. there is nothing in the documentation that states "you should not create multiple instances of the object".
if this is somehow inadequate in profiling, then consider using a shared object which relays messages to the objects (in your app) which need updates.
rationale: chances are, apple's already optimized the implementation, so you don't have to.
finally, i broke these guidelines in an app which required a ton of location requests, and displayed a ton of location information. the app used some static data behind an interface which stored the location manager and the location (among other things). so i ended up using static data with private (hidden) static data to reduce the memory and cpu demands in this case.
The App Delegate is a good, central place for such data. You can always get to the app delegate with [[UIApplication sharedApplication] delegate]
I'm a novice iphone developer, and just completed my first iphone app.
After provisioning my iphone for development, I noticed that the app used way too much memory, and that several memory leaks that were issuing from the app accessing the sqlite database in the app caused the app to crash often. After running instruments, I have decided that CORE DATA sounds like a better way to go: of course I still need to use the sqlite database that I have.
so my question is this: how easy would it be to adapt an already existing app to run on core data? My app basically shows 17,000 different mapView annotations in small amounts by county, though my database is very simple, just one giant spreadsheet basically.
in the App delegate, my app opens the Sqlite database, puts some of the data into a locations object with four attributes, and then makes an array of those objects.
the first view controller lets the user decide which county ( one of twelve or so) the user wishes to view, and then the last view controller uses a loop to add the selected locations to a mapView.
How should I modify my app in the previous paragraph so that it uses CoreData? Can you point me to any resources that I can use to achieve this (preferably not the Dev Center's CoreData tutorial; overly confusing and more complicated than i need right now)? or do I have to make an entirely new project in xcode and start from scratch?
Apologies for the indirect pontification, but ...
First, I'd say your assertion, "After running instruments, I have decided that CORE DATA sounds like a better way to go..." is flawed. Finding bugs and performance issues in your app doesn't automatically mean a different approach is better - it may only mean you need to fix your memory leaks and/or adjust your approach based on what your profiling shows.
The fact you say you still need to use an existing SQLite database doesn't automatically preclude using Core Data, but it does make your end solution significantly more complicated. If you can possibly get away with using either Core Data or SQLite entirely, that would by far be your best bet.
Also, Core Data is not a beginner (or, I'd argue, even an intermediate) Cocoa technology. It requires significant prerequisite knowledge to do anything more than very basic stuff without becoming hopelessly lost when the inevitable problem arrises. If you're too pressed to take the time to read the documentation and research the technology for now, you're probably better off just fixing the problems with your existing solution.
... and there's nothing wrong with your existing solution (using SQLite directly) at its most basic. The better question(s) to ask is (are) about the specific problems you're having with your current approach.
That said, if you want to adapt an existing iOS-based solution to use Core Data, you'll likely have an easier time of it than if you were targeting Mac OS. Create a basic Core-Data-Based iPhone app project and look at the code. The code to build the Core Data stack is in plain sight. The only other thing to remember is to add an xcdatamodel file like the one found in the empty project. If you've gotten far enough to interface with the SQLite library, you should have enough experience to see clearly how Core Data is used in a standard iOS app.
The steps you need to go to convert to Core Data:
- Develop data model (maybe graphically in xcode)
- Adopt your code to use core data instead, i.e. rewrite that module
- Read your old data and put it into core data
If you have it already running with sqllite, I'd stick with it. If it uses much too many memory, it's probably a bug on your part, or bad partitioning of the data you load into memory, and you want to address this one way or the other - although Core Data makes it maybe a bit easier to get it right.