JScarry
JScarry

Reputation: 1507

Does Objective-C have something like php's include_once call?

I've gone through the Stanford iOS course a few times and understand all the examples they used. And I've read lots of the docs and a dozen or so examples from the Apple site, but I'm missing the strategy for reusing code—which is supposed to be a feature of object oriented languages.

I've got a chunk of code that puts a recording button and playback button on the screen. The code associated with the buttons is just for display. A selector in on button handles the recording, storage, and playback. I'd like to have three sets of these buttons on the screen. In PHP I'd just put the 50 lines of code in an include file and in javascript I'd probably write a function to display them. In the object world, I'm at a loss as to what the best approach would be.

Would I use a UIView class and if so how do I get the view to show up on the stage? I could use a Default Objective C class like I do for scorekeeping but then I have the same question about how to get the buttons onto the stage.

Thanks for the comments, but the #import directive isn't anything like include_once in PHP.

There are at least three ways include_once can be used.

The simplest way is to use it to include text on multiple pages of a site or sites. For example, you might have an hours.inc file that has the office hours and tech support numbers. You could then include this file on the contacts, support, and about pages of the site. If you change the hours you change them in one file.

Related to the first use would be a file that has global variables for the site. e.g. $company_name = "Our Company". $company_phone = "800-555-1212", etc.

This file would be used in conjunction with header.inc and footer.inc. In this use it is more like what some languages call macro substitution.

But the most powerful use of PHP includes is to generate code based on some input. On many of my sites I have one PHP include file that generates dozens of product pages based on product ID. The page itself has just a few lines,
require_once('set_variables.inc.php');
require_once('./header.inc');
$page = mysql_real_escape_string($_GET['p']);
if (file_exists("pages/$include_page") ) {
require_once("pages/$include_page");
} else {
require_once("pages/missing.inc");
}
require_once('./footer.inc');
I can read this page and know exactly what is going on. I'm having trouble keeping track of what's happening in my views when they get to be 800 lines long.
This is such an incredibly useful feature of the language that I can't imagine that it's not part of Objective C. What I can't figure out is how to do it. I'm sure it involves creating classes of some sort that hold the code to reuse, but none of the examples I've looked at do this.

So what I'm looking for is a hint at how Objecive-C implements this PHP functionality:
$number_of_button_sets = 3;
inlcude_once('buttons');

Upvotes: 0

Views: 272

Answers (4)

JScarry
JScarry

Reputation: 1507

The short answer is "That's not how you do things in iOS".

You could mimic the code replacement functionality of PHP includes by using #defines. If you wanted to you could write code just like you do in PHP and pull repetitive portions into #defines. Put them into {ProjectName}-Prefix.pch and they will be automatically available to all of your classes.

What you want to do is restructure your code so that it uses the Model-View-Controller pattern. Pull model-related code out of the main view and put it into a series of classes. Same with view-related code. Sometimes that's all you need to do and sometimes it gets more complicated.

For example, in my quiz titles I have a preference pane where users can choose which category or categories they want to be quizzed on and the degree of difficulty. When the game first initializes I need to set the default preferences in NSUserDefaults. I created a class for the code and invoke it using

PreferencesInitialization *prefs =[[PreferencesInitialization alloc] init];
[prefs initializePreferences];

The code snippet above acts just like a PHP include and runs the code when it is called.

That works fine if the code in question has no interaction with the current view or data. In the quiz game I put scoring buttons at the bottom of the screen in a toolbar. I pulled all of the code out of the view and put it into a class. I call the class like I did above. Except that the class knows nothing about the environment it is running in. So I need to pass everything it needs to know about to it.

self.scoringToolbar = [[ScoringToolbar alloc] initWithScoreKeeper:self.scoreKeeper parentView:self.view];

This is where it gets a bit tricky, it needs to know about the current instance of the scoreKeeper (the class that tallies the results) and the current view. In order to place the toolbar at the bottom of the screen scoringToolbar uses the self.view information to calculate positions. All of the self.view calculations are changed to self.parentView. e.g.

CGSize windowSize =  self.parentView.frame.size;

The scoringToolbar is completely self-contained so once it has its initial parameters it runs on its own. The view controller can get information from it by invoking its methods.

The third type of interaction is where the view controller tells the object to do something, say play a sound, and the target tells the view controller when it is done. The way they do that is with the use of delegates. I pulled the recording and playback portion of the game out of the main view and put it into a class. Just like the scoringToolbar it needs to know about the current view.

self.recordPlay = [[RecordPlay alloc] initWithParentView:self.view ];
[self.recordPlay setDelegate:self];

Tell the recordPlay class to play a sound with a playSound method.

[self.recordPlay playWord:targetSnd];

By setting up the view controller as a delegate of recordPlay it can be notified when the sound is finished playing and respond accordingly.

In recordPlay call

[self.delegate soundFinishedPlaying:self.soundToPlay];

This calls the soundFinishedPlaying method in the view controller and it does whatever is appropriate. Like telling the picture class to highlight a picture or the recordPlay class to play the next sound.

Delegates turn out to be key to the Model-View-Controller pattern. In my game, the controller asks the wordList class for a word using a method in wordList. If there aren't any words, the wordList delegate lets the controller know and the controller launches the preferencesPane. When an picture is clicked on, the pictureView class tells the controller and the controller decides which sound to play. Then it tells the recordPlay class which sound to play.

Classes don't communicate with each other—in fact they don't even know about each other. The controller is an intermediary and it tells everyone else what to do.

I suppose this is obvious to someone with an object-oriented background, but it took me a year to figure out. I've rewritten my game to use these concepts and its much easier to manage. By swapping out classes I can reuse the basic structure in several similar games.

Hope his helps someone else.

Upvotes: 1

Jim
Jim

Reputation: 73966

PHP's include_once is just a mechanism for including one file in another. The direct analogue of this in Objective-C is #import. However you seem to be talking about re-use of interface code, which is a very different concept.

If all you want is an item on the screen, you can subclass UIControl or UIView. You can then use these wherever you would normally use those types of objects - you can drag a UIView onto a nib and then change the class to your custom class, or you can directly instantiate it in code and add it as a subview to one of your existing views.

You will need to #import the header file for your subclass in any code files where you use it.

Upvotes: 1

Hot Licks
Hot Licks

Reputation: 47749

You can write the code to put up any control you like (within reason), put the code in a function, and invoke that function multiple times to display multiple copies of the control.

Upvotes: 0

NSResponder
NSResponder

Reputation: 16861

Objective-C has the #import directive.

Upvotes: 6

Related Questions