General question about iPhone programming - iphone

I have a question regarding nibs and how detail views are created in professional apps. I want to make an app that loads different uitextfields for each nib that is selected from a table. These textfields contain some logic that is different from each. I wanted to ask if it's possible to make one nib and change the data from thatto match all these scenarios. I'm unsure how this is done and how nib management can be done by arrays. Thanks and I hope I was clear enough :)

I can only speak myself but I've moved away from nibs. When you get complex layouts that have elements disappearing and reappearing your nib/s become unmanageable. You can do a better job of keeping elements tidy and manageable in code as well as a slightly faster App (not much but its a nice bonus).
EDIT: As a very basic example just remove any details of a nib and if you class is a UIViewController subclass do this:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50,50,150,30);
label.text = #"Hello World";
[self.view addSubview:label];
[label release];
Very basic but hopefully this will get you on your way to developing without nibs. Note: Nibs aren't bad and if its a basic view use them but if you are having complex views you will find nibs becoming unmanageable.

I found this article on Cocoa With Love to be really interesting in regardless to performance of nibs vs code.

IB / Nibs are useful for "getting started" and quick prototyping. However like #Rudiger mentions it's useful only in simple, static layouts. Usually it's only a matter of time before you'll run into limitations and find yourself having to write real code.

Related

How does UINavigationController keep track of multiple UIViewControllers?

I have developed an application that uses UINavigationController to handle multiple instances of the same UIViewController, and it is working great. The UIViewControllers that I am using, however, are using a lot of images in a sometimes very big UITableView as loaded from the server, so I am beginning to be more conscience of performance and memory.
What happens to a UIViewController that isn't at the top of the stack? If I drill down through a few views, that all have images, whenever I return to the view, the UINavigationController presents the view without any loading, so I'm wondering if those views on the stack are in any way potentially hogging lots of valuable resources? Such as memory?
What is the best way to handle that situation? Is there anything I should know about that I apparently don't?
Thanks!
This is, actually, explained in the documentation for iOS. Check XCode>Organiser>Documentation>iOS, there is a nice drawing explaining how the UINavigationController stack works, that should be better than words.
However, in a nutshell, you have viewDidLoad and viewWillAppear (and their opposites) methods that serve to alleviate your fears. They should be used to create/delete any "memory hogging" parts of your code that you don't need "right now". However, as far as I know, you don't have control over what iOS will decide is necessary to flush or not, if it's controlled directly by UINavigationController.

Encapsulation of logic and interface on iPhone SDK

I assume this is going to be a very basic question, but maybe somebody can help me. I've come to iPhone SDK from a C# .NET background.
I would like to know if there is some mechanism similar to what is called in ASP.NET "UserControl" which encapsulates logic and interface. It would be desirable to launch "events" too.
I'm trying to design something like a common header for the entire application, which shows different types of buttons depending of the view where it is placed.
Normally Objective C will support only single Inheritance.We can achieve multiple inheritance
through Delegates called as protocols(user defined).i think it will help you when you google based on this(user defined protocols in iphone sdk).
First of all thanks for your contribution. I realized that I was looking for something different: The views (yeah, I know there were here since the beginning).
I've realized that when I allocate one of my controllers by default it tries to load the xib with the same name. Therefore, I can design the view on the interface builder and then load it on another view as a subview (that's similar to usercontrol concept).
How to make the view adjust to the desired size?:
Controller *controller = [[Controller alloc] initWithNibName:nil bundle:nil];
controller.view.frame = CGRectMake(100, 100, 200, 200);
[self.view addSubview:controller.view];
The only missing here is how to comunicate the view with the subview, but I supose that can be made with a reference to the parent.
Thanks a lot
(PS: I'm going to check the answer as correct just for close the thread. I don't know if this procedure is the best or has enough quality)

First iPhone Multiview App - Some Guidance

I'm wanting to make a multiview app with 5-6 different screens and a data source to store user information. I've never made a multiview app before, and I have a good idea on how to start, but I'd like to hear some recommendations on "structuring" your app to properly support this.
A very simple analogy could be going about making a background color on a website... You could either use an image of a solid color or simply use the background-color style. Both get the job done, but using the style is a bit easier/more efficient.
I just want to make sure I'm starting off on the right foot. Should I keep all my functions in one class' .m/.h file? What's the best/efficient way to go about different screens?
Thanks, and I'll definitely try to help others out once I get a much better grasp on Objective-C and Xcode.
If you are new to the iPhone/iPad I highly recommend you check out the CS193P lectures, they are also avaliale on itunes. They give a good overview of iPhone programing and how things are done in Objective-C / Cocoa Touch. It will get anyone started in the right direction.
As to your specific question. Just start coding. In 6 months you'll realize eveything you wrote is cr*p and needs to be rewritten anyways, but doing it is the only way you'll realize what you wrote is cr*p so...
Some suggestions, specific to multi-viewed apps (which almost every app is) and I'm sure someone else can expand on this...
Learn (as much as possible) to code interactions between different views and viewcontrollers (vs using interface builder). The twitter app for example doesn't use Interface Builder at all.
If you use IB, don't dump everything into one .xib. Learn how to break them up. One .xib per viewcontroller should be it. I never use the IB UITabBarController or IB UINavigationController, those get initilized and used in code only.
Absolutly learn MVC (Model view controller).
The Apple documentation is often a good place to start for most things. Try here first. Hope this helps and good luck!
I used to use a UINavigationController. I created it as a singleton and accessed it statically so I could push and pop controllers easily (theres a reasonably good tutorial here). This is quite lightweight and theres enough documentation to get going with it quickly.
However the best approach I've used is the Three20 framework's TTNavigator. In a nutshell its a beefed up UINavigator that lets you push a new view onto the screen by calling an internal URL:
//(In your app delegate)
//Start up the navigator
TTNavigator* navigator = [TTNavigator navigator];
navigator.persistenceMode = TTNavigatorPersistenceModeTop;
//Map url's to controllers
TTURLMap* map = navigator.URLMap;
[map from:#"*" toViewController:[TTWebController class]];
[map from:#"ac://search" toViewController:[SearchViewController class]];
[map from:#"ac://results/(initToView:)" toViewController:[ResultsViewController class]];
Then to navigate to a controller:
[[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:#"ac://results/searchResults/"] applyAnimated:YES]];
Whats also cool is that calling that #"ac://results/" the way we have above passes in the param #"searchResults" to the init method of the ResultsViewController ("initToView:") as we defined in the mapper
All the best!

Is it possible to build an iphone view WITHOUT using Interface Builder?

So Interface Builder does things to save time but what if I want to do without it ? In C# all code generated is clear and understandable, in interface builder this is hidden so I'd like at least during learning phase do things from scratch: any sample code to do so ?
Seems Apple makes things very hard so as you cannot easily use alternative to Xcode :)
http://cocoawithlove.com/2009/02/interprocess-communication-snooping.html
Yes, you can build a view without IB. Just allocate and initialize a view or a control and set its properties, e.g.:
UITextField *tf= [[UITextField alloc] initWithFrame: CGRectMake(24.5, 65, 270, 30)];
tf.delegate = self;
tf.textAlignment = UITextAlignmentCenter;
tf.autocorrectionType = UITextAutocorrectionTypeNo;
tf.autocapitalizationType = UITextAutocapitalizationTypeNone;
[self.view addSubview: tf];
But IB does not hide any generated code from you because it doesn't generate any code at all. Instead, it creates object instances and serializes them into a XIB or NIB file.
Interface Builder doesn't work in the same way as Visual Studio. It doesn't generate code, instead it generates "raw" object instances. In this sense it's not possible to see the code because there is no code generated.
One option nib2objc to convert your interfaces to code, though I'm not sure how readable that would be. As noted above, this is not the code that would be executed by your iPhone.
This blog post shows you how to get started with a nibless iPhone project.
And you might want to look at this SO question to learn about creating views (e.g. a UIButton in this case) programmatically.
Interface builder doesn't generate code to build a UI object. It creates a compressed xib data object which the iOS runtime "uncompresses" (does some housecleaning) into your pre-built object.
The paradigm is to actually think of you objects as objects in their own right, and not just the results of code execution. e.g. what you would end up with if you could "Make it so." without writing any code.

Can you swap the NIB file for a UIViewController that's already on-screen?

For instance:
Create a new UIVC using initWithNibName, using "nib-v1"
Display it, e.g. using [(UINavigationController) nav pushViewController: myVC]
Change the NIB that myVC is using to "nib-v2"
So far as I can see, this is the "correct" approach to app-design for a lot of apps, when paging through information where you need two slightly different UI screens for the info being displayed.
For instance, most of your pages are text, but some of them have an image too (think of an RSS reader, where some RSS entries have text + image, some are text only).
I've dealt with this previously by having one NIB file with a second, invisible, named UIView instance that I layered over the top of the first one, and switched on/off depending on on context, using the "hidden" flag.
But this is clearly wrong, and wastes memory.
However, I cannot see an obvious way to "reload" the view from the NIB file. I'm guessing I want to somehow reproduce the magic that initWithNibName does?
I suspect this is possible, but I'm sure that if you do it "the wrong way" then the app will simply crash horribly.
You can always perform
[[NSBundle mainBundle] loadNibNamed:#"FileName" owner:viewController options:nil]];
but this will undoubtedly really mess things up, if you're not sure what you're doing, especially if view is connected in both of those nibs
You should redesign your view controller hierarchy to swap between two different controllers that load from two different nib files.
Alternately, you can have the controller manage swapping views that it loads from different files that are unrelated to it's nibName. In that case, you can load them in the above manner. And you will want to have their outlets (to, for example, subviewOne and subviewTwo) connected in different nibs.
You should check out the UINib class to see if it does what you want. It will allow you to load a nib file and keep it in memory.
But just to clarify: Do you want to modify the nib file itself? Or do you want to modify the contents of the nib file when it has been loaded into memory?
Off the top of my head, the first would be quite difficult (you can't modify the original file, since it is part of application bundle...maybe you copy it to Documents folder and write your own coder/decoder?) The second is easier, but I am not sure what the reason would be? Why not just modify the viewController/view after it has been loaded (in awakeFromNib, for example) and, if you want those changes to persist, save those changes to file afterwards.
In short, I don't know exactly what you would like to do, but the chances seem high to me there might be a better way to do it.
I agree with Rob, but if you really want to mess with swapping nib's (which is bad as it can easily lead to dangling pointers and the like), you could maybe load the view from the new nib with NSBundle's - (NSArray *)loadNibNamed:(NSString *)name owner:(id)owner options:(NSDictionary *)options method and do the view swapping yourself.
You should rather use different view controllers for different types of content. If they only differ slightly, you can still consider creating one base class and subclassing the different variations.
You shouldn't change what NIB file a UIViewController uses. Attaching the NIB to the UIViewController should be a one-time event. The hidden views are fine; they're certainly not clearly wrong. You can also programmatically add view elements after loading. If you're doing a lot of that, you can skip the NIB entirely and programmatically build the view in -loadView. Any of these are fine, but don't switch the NIB after initialization. I don't even recommend having multiple NIBs that you choose between for a given UIViewController class; it's just too confusing. Generally each NIB should map to a dedicated UIViewController class with a very similar (or identical) name.
In a related note, I recommend moving the name of the NIB into the UIViewController, as described in an earlier posting.
I came looking for an answer to the same problem, and ended up solving it like this:
UIViewController* ctrler = [[UIViewController alloc] initWithNibName:#"NewControllerNIB" bundle:nil];
// Replace previous controller with the new one
UINavigationController* nav = self.navigationController;
[nav popViewControllerAnimated:NO];
[nav pushViewController:ctrler animated:NO];
I'm not sure if it's possible the current controller gets deallocated before the call to push the new controller is executed, but so far it seems to work (until I just redesign the app with a better approach)