iPhone : pushing on UIViewController from where it pushed - iphone

I've two UIViewControllers say ViewController_A and ViewController_B
My flow is, AViewController_A ---> BViewController_B ---> CViewController_A
For A, B and C navigations I have the following situation,
A - In ViewController_A I've 100 of records which are in UITableViewCell, user select any one, and it will pushed to ViewController_B which will showing that selected record from ViewController_A.
B - Will show selected data from ViewController_A, and having Back button to go back (I can pop). Another thing, have a UIButton, If user tap this, it will again showing ViewController_A but with only that single record
C - Either we'll pop from ViewController_B then there's no issue, but I again want to push, so I need to #import ViewController_A in ViewController_B (as I've already imported ViewController_B in ViewController_A so I can't reimport ViewController_A in ViewController_B, right?) will create collision for those UIViewControllers.
What should be the better way to solve the problem in C, one suggestion is to make another `ViewController_D like and show the same as in ViewController_A but I think its not proper way, as I've already UI and coded for the functionality.
Suggestion needed. Let me know if you've any doubt!

What I understand is you have trouble with #import directive ?
I guess you are importing header in the .h file ? If so, do an #import in the .m file; and in the .h you should use #class YouViewControllerA.
Ex with AViewController:
.h
#class BViewController
#interface AViewController : UIViewController
{
//Your attributes here
}
#end
.m
#import "BViewController.h"
#implementation AViewController
//Some AViewController methods here
#end
Do this for both AViewController and BViewController and it should work.
EDIT : #import directives are designed to avoid recursive error, so anyway you shouldn't get error.
If you know a bit of preprocessing, the #import do the following (automatically) :
#ifndef TOTO_HEADER
#define TOTO_HEADER
//your methods here
#endif
More explanation :
When you write #import "toto.h" , at compile time the compiler will do the following check :
Is the preprocessoring variable "TOTO_HEADER" defined ? (this corresponding to the line ifndef "TOTO_HEADER")
If it isn't we define it (this is the #define "TOTO_HEADER" line) AND we "include" the methods and functions.
If it has been already defined, no need to include the methods (since they already get included).
This way we prevent header file from being included if they were already included. (and by extension it should not make any recursive error).
In other words : #import ensures that a header file is only included once so that you never have a problem with recursive includes.

one solution could be this-
First save the selected value in NSUserDefaults, and then take a bool when you click on the UIButton in viewController B.
Then push a segue to ViewController A and check the value of Bool there.
If its true then only print the value of NSUserDefaults else print the whole set of 100 records.

Related

In interface file: when to use forward declaration for custom class as opposed to just including its header?

I have subclass of UIViewController called FullScreenViewController which has a property of type ImageScrollView which is subclassed UIScrollView object. The implementation and interface look as follows:
FullScreenViewController.h
#import <UIKit/UIKit.h>
#class ImageScrollView;
#interface FullScreenViewController : UIViewController
{
ImageScrollView *_scrollView;
}
#property(nonatomic, retain) ImageScrollView *scrollView;
#end
FullScreenViewController.m
#import "FullScreenViewController.h"
#import "ImageScrollView.h"
#implementation FullScreenViewController
#synthesize scrollView = _scrollView;
...
#end
now I subclass FullScreenViewController, and I try to access any properties from the ImageScrollView property and I keep getting the error message: "Property cannot be found". When I add ImageScrollView.h to the subclass, it works, but I'm not understanding this. I've already added ImageScrollView.h in FullScreenViewController, why should I have to add it again?
UPDATE: Rather than using a forward class declaration, I've included ImageScrollView.h in FullScreenViewController.h. I'm a little confused as to why I've ever use a forward declaration versus just including the .h file?
The reason you need to add it is you only have a #class declaration in your FullScreenViewController.h file. That only declares variable of type ImageScrollView* as pointers to object of class ImageScrollView. It does not give you access to the properties of ImageScrollView. To get access to methods and properties specific to ImageScrollView, you need to include the #interface declaration of ImageScrollView, which I assume is in your ImageScrollView.h file.
Given the header:
#interface FullScreenViewController : UIViewController
{
ImageScrollView *_scrollView;
}
#property(nonatomic, retain) ImageScrollView *scrollView;
#end
a forward declaration #class ImageScrollView is all that's needed. This tells the compiler that there is an objc class named ImageScrollView.
Of course, with a forward declaration, the interface is not visible where you need to use it unless you also #import ImageScrollView where you use it.
now I subclass FullScreenViewController, and I try to access any properties from the ImageScrollView property and I keep getting the error message: "Property cannot be found". When I add ImageScrollView.h to the subclass, it works, but I'm not understanding this. I've already added ImageScrollView.h in FullScreenViewController, why should I have to add it again?
ImageScrollView's declaration is not visible to the subclass FullScreenViewControllerSubclass. ImageScrollView.h is visible only where #imported. FullScreenViewController.m is not visible to FullScreenViewControllerSubclass.m. Therefore, you must write another #import in FullScreenViewControllerSubclass.m to use ImageScrollView there.
UPDATE: Rather than using a forward class declaration, I've included ImageScrollView.h in FullScreenViewController.h. I'm a little confused as to why I've ever use a forward declaration versus just including the .h file?
Use forwards for fast build times and sane, controlled dependency structures. This is a very time consuming problem to undo. And this problem gets much worse as the size of your programs and libraries increase:
Would you prefer a change to a header in a medium sized project to require recompilation of 50 sources with an average preprocessed input of 150,000 lines per translation, or would you favor that change to affect 6 sources with an average preprocessed input of 40,000 lines per translation? The difference here is that small change takes the incremental rebuild from seconds to minutes to complete, depending on how you have structured your dependencies and imports.
Have you tried accessing it using the alias _scrollView or scrollView.you should access it using _scrollView and see if u have imported the file in .m or .h as #class won't suffice.

How can I use an IBOutlet from another Class file into a different .m file?

MyGems.h
#import <UIKit/UIKit.h>
#interface MyGems : UIViewController {
IBOutlet UIImageView *lock1;
Collect.m
#import "Collect.h"
#import "MyGems.h"
#implementation Collect
- (IBAction) unlock {
if (lock1.hidden = NO) {
ruby.hidden = NO;
}
I get 4 errors, can someone please help? It seems to simple, but is confusing me.
You should almost never do this. The view controller (MyGems, which should be named something like MyGemsViewController) is responsible for managing this view. Other classes should not reach in and modify its IBOutlets. Doing so will cause you significant problems when the view managed by MyGems unloads and lock1 surprisingly becomes nil.
It's unclear what Collect is in this case; I assume it is another view controller? I'm not clear why unlock isn't a method on MyGemsViewController.
Also note that this code is incorrect, and should be throwing warnings at you telling you it's incorrect:
if (lock1.hidden = NO) {
This assigns NO to lock1.hidden. You meant to use ==, but you should never test against NO this way. You should do it this way:
if (! lock1.hidden) {
You must be careful of testing booleans against YES and NO. There are many true values that do not equal YES.
You need to make sure you have a reference to lock1 in your Collect class, most likely you will want to achieve this by having a reference to the Collect class in MyGems and then moving this view logic back into MyGems rather than in your Collect model class

Headers #import versus #class [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
#class vs. #import
In the .h file you can add a class to be seen(dont know what the correct terminolgy for this is) by using
#import "SomeClass.h"
or instead use
#class SomeClass;
I've tried both methods and they both worked. Whats the difference? Should I be using one of the methods and not the other? What is best practice?
#import includes the content of the header in the source.
Thus, every declaration which is in the imported header is also imported.
#class only declares to the compiler that the given class exists, but does not import the header itself. It is called a forward declaration, as you only declares to the compiler that the class exists before defining it in details (telling which methods it implements and so on)
Consequences:
When using #import in your .m file, if the header is modified, it will trigger the recompilation of the .m file that #import it on next compilation. Instead, if you use #class, your .m does not depend on the header and if the header is modified, the .m file is not recompiled.
Using #class also avoid cross-imports, e.g. if the class A references class B and class B references class A, then you can't #import "A.h" in B.h and #import B.h in A.h in the same time (it would be an "import infinite loop")
Using #class only declare that a class exists and does not tell the compiler which methods the class responds to.
This is why usually the best practice is to forward-declare the class using #class A in the header (.h) files that references class A, just so that the compiler knows that "A" is a known class but doesn't need to know more, and #import "A.h" in the implementation (.m) file so that you can call methods on the objet of class A in your source file.
In addition to avoid import loops, this will also avoid to recompile files if they don't need to, and thus reduce your compile time.
The only exceptions are when the declaration of your class inherits another class, or when it declares that it conforms to a given #protocol (like delegate protocols and so on), because in this particular case, the compiler needs you to #import the whole definition of the parent class or #protocol (to know if your class correctly conforms to this given protocol).
MyClassA.h
// Tells the compiler that "MyClassB" is a class, that we will define later
#class MyClassB; // no need to #import the whole class, we don't need to know the whole definition at this stage
#interface MyClassA : NSObject {
MyClassB* someB; // ok, the compiler knows that MyClassB is a class, that's all it needs to know so far
}
-(void)sayHello;
-(void)makeBTalk;
#end
MyClassB.h
#class MyClassA; // forward declaration here too
// anyway we couldn't #import "MyClassA.h" here AND #import "MyClassB.h" in MyClassA.h as it would create an unsolvable import loop for the compiler
#interface MyClassB : NSObject {
MyClassA* someA; // ok, the compiler knows that MyClassA is a class, that's all it needs to know so far
}
-(void)talk;
-(void)makeABePolite;
#end
MyClassA.m
// import MyClassB so that we know the whole definition of MyClassB, including the methods it declares
#import "MyClassB.h" // thus we here know the "-talk" method of MyClassB and we are able to call it
#implementation MyClassA
-(void)sayHello { NSLog(#"A says Hello"); }
-(void)makeBTalk {
[someB talk];
// we can call the 'talk' method because we #imported the MyClassB header and knows this method exists
}
#end
MyClassB.m
// import MyClassA so that we know the methods it declares and can call them
#import "MyClassA.h"
#implementation MyClassB
-(void)talk { NSLog(#"B is talking"); }
-(void)makeABePolite {
[someA sayHello];
// we can call this because we #import MyClassA
}
#end
PS: Note that if this is a best practice, I know a lot of developers (including myself sometimes ^^) that #import the header it needs in their .h files, instead of only forward-declare it using #class... this is some bad habit — or because these developers doesn't know these subtleties — that you will unfortunately encounter in existing code anyway.
Using #class is called forward declaration. Since usually you don't need to know the specifics of the class in the .h file, this is usually all you need.
Forward declaration prevents you getting into a situation where you import a particular .h file, which says to import another .h file, which says to import the original .h file again, and so on.
The #class forward declaration allows you to have your interfaces behave like interfaces. Meaning: Declare your code.
But this doesn't mean that you can leave out the #import statement. You just moved the responsibility to the implementation to import and make use of it.
Basically it could be seen as an increase in performance as you're not importing any other headers inside your current header.
Important Note: This isn't the case when you're working with delegates.
If you're making use of delegates you always have to have the proper #import statements in place so that the compiler knows which delegate methods are to be implemented by that class.
You might also want to have a look at the following SO question: #class vs. #import

How can you conditionally include protocols during compiliation?

Is it possible to conditionally include a protocol? For example, below is some code that does not work, but should give you an idea what I'm referring to. I only want the interface AdWhirlDelegate to be included if ads are turned on.
// this works fine
#if ADS_SUPPORTED
#import "AdWhirlView.h"
#endif
// this does NOT work
#interface MyAppDelegate : NSObject <UIApplicationDelegate #if ADS_SUPPORTED ,AdWhirlDelegate #endif>
You could do:
#if ADS_SUPPORTED
#interface MyAppDelegate : NSObject <UIApplicationDelegate,AdWhirlDelegate>
#else
#interface MyAppDelegate : NSObject <UIApplicationDelegate>
#endif
...but then IB can get a little confused. See this answer, which presents an alternative to that.
That won't work
Repeat the interface declaration twice , one with the protocol and one without blocked inside the #if/#else/#endif structure
Preprocessor directives will only work in a non nested way like your header include.

when and where to put #class declarations

I am working on a project with several custom classes. I have a CardModel (NSObject) that has some integer properties to hold data, and a Deck (NSObject) that has an array to hold a bunch of CardModels and then a CardView (UIView) that has a CardModel as a property that I make when I select a CardModel from a Deck. And then I've got a bunch of UIViewControllers that I move around on a UINavigationController.
My question is about where and when to use the #class compiler directive.
If I subclass a UIViewController by making a new file and subclassing it, should I use the #class MyViewController in the header of MyViewController.h or .m and does it go in the header of the file that actually uses the controller (like when one controller is going to instantiate another controller type and push it to the stack). Or do I need to use it at all? Is it only required if I actually add new properties to my class beyond what's in the stock implementation? It seems like I'm putting #class all over the place just make sure I don't get errors but I don't fundamentally understand when I need it.
Thanks!
You use it in the .h to inform it about a custom class without including the .h for the custom class.
Example:
Two custom classes: Car and Wheel
Car.h
----------------
#interface Car : NSObject {
}
- (void)addWheel:(Wheel*)newWheel;
#end
Car.h doesn't know about the class 'Wheel' so it would throw an error so you could import the Wheel.h like so:
Car.h
----------------
#import "Wheel.h"
#interface Car : NSObject {
}
- (void)addWheel:(Wheel*)newWheel;
#end
BUT you dont need to do this either. Car.h doesn't need to know anything about the Wheel class, it just needs to know it exists. So what you use is the #class to just say that "Hey, this class exists. Take my word for it."
Car.h
----------------
#class Wheel;
#interface Car : NSObject {
}
- (void)addWheel:(Wheel*)newWheel;
#end
Then inside of the Car.m, when you actually need to know about the Wheel class (properties, methods, etc) you should import the Wheel.h there.
The #class directive is used when you need a header to know about a class but you don't want to import the class's header file; e.g., when you need to avoid circular dependencies.