I Have a very long view controller.m which I'm trying to split into separate files to keep it organised.
I know I can create separate .m .h files and separate them but in doing so I am ending up in loops (which I Understand since the MapController.m is initialising the viewcontroller again causing viewDidLoad to be triggered and repeat.
I have a Map I want to create in my MapController.m
-(void)setMapSettings{
NSLog(#"test");
viewController = [[ViewController alloc] init];
SKMapView *mapView = [[SKMapView alloc] initWithFrame:CGRectMake( 0.0f, 0.0f, CGRectGetWidth(viewController.view.frame), CGRectGetHeight(viewController.view.frame) )];
}
I want to add the above SKMapView to a UIView called mapViewContainer in my viewController.h
ViewController.m:
- (void)viewDidLoad {
mapsViewController = [[MapController alloc] init];
[mapsViewController setMapSettings];
}
Doing this creates a loop resulting in a crash. I know the answer is probably dead simple and I'm just being stupid, but I've spent hours finding a solution and I can't figure it out. Any idea's how I'm suppose to be able to do the above without looping, and without initialising the map views I require all in the ViewController.m?
You say that you are splitting the view controller by taking out code from it, but as far as I understand this has resulted in creating a second viewcontroller (either this, or "MapController" isn't the right naming).
Anyways, as you already mentioned the crash is definitely caused by that alloc/init loop: you should reengineer your code to have just one of the two objects instantiating the other.
(please bear in mind that if you are doing that to access one object from the other, you're doing it wrong: alloc/init creates a new instance of that class every time it is called, it does not give you a pointer to an existing one)
Related
My app has a search view(search bar) which is used all over the app. I don't want to create duplicated code so I created a view controller called MySearchViewController to handle the search job, then I created a singleton object in AppDelegate. In every view controller, I added my search view like this:
- (void)viewDidLoad
{
MySearchViewController* search = [AppDelegate searchViewController];
[self.view addSubView:search.view];
}
My questions, Is it a good way? It's a singleton so it can be added to many views. Do I need to remove the view from last view before adding to current view?
Understand that you are mixing some concepts that are not necessarily related: avoid duplicated code and Singletons.
Wikipedia says this about singletons:
In software engineering, the singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects. The term comes from the mathematical concept of a singleton.
The most important characteristic of a singleton (in my humble opinion) is that the object is instantiated only once and every single place in your application will use the same instance. Well, to use your search feature everywhere and avoid duplicated code you don't need the search view to be instantiated only once, maybe the data that comes with it, but not the view itself.
Two better ways of achieving this:
1 - You can create a ViewController with your search and just embed this on the other views using a Container View, you can use blocks or a delegate protocol to communicate between your controller and the view that is embedding it.
2 - You can create a Parent class of the ViewController that will include the search bar, like a SearchViewController and all the other viewControllers that needs the same feature will inherit from it.
The singleton could be useful if you are planing to share the same search data and text between all the ViewControllers of the application, but it would be a singleton only with these information, the UISearchBar and all other view elements should not be part of the singleton.
Ideally, you should instantiate a fresh instance of MySearchViewController every time when you want to add it to another view to avoid problems.
Do I need to remove the view from last view before adding to current view?
Its not required to remove it from previous super view because whenever you add this singleton MySearchViewController's view to some other view, it will automatically gets removed from last super view and now its super view is your new view where you have added it.
If you want to add a view from a different view controller, your view controller has to be that view controller's parent view controller:
- (void)viewDidLoad
{
MySearchViewController* search = [AppDelegate searchViewController];
[self addChildViewController:search];
[self.view addSubView:search.view];
}
also, make sure that when the search.view is added, it is already initialised.
Why you do not use NSObject class ?, i do not know your requirement , but if you want to store latest updated value in whole project(in execution) then you should use the singleton, but if you do not want to store value (i mean one result for whole project) then you should use NSObject derived Class. advantage is singleton consumes memory so memory will be wasted. NSObject class will be reusable and only allocated when it is required and then ARC will take care of all things. If you want to know how to create NSObject and use of it then you can give me reply.
Here is some code to load a XIB as part of a custom object with the object gets initialized.
Why are you not creating custom search component for search?
you can use this component all over the app.
also this is not creating duplicat code.
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[[[NSBundle mainBundle] loadNibNamed:#"SearchView" owner:self options:nil] objectAtIndex:0];
[self addSubview:self.view];
self.frame = self.view.frame;
}
return self;
}
Please check below code. Hope this is work for you.
- (void)viewDidLoad
{
if ([self.view viewWithTag:123456]) {
[[self.view viewWithTag:123456] removeFromSuperview];
}
MySearchViewController* search = [AppDelegate searchViewController];
search.view.tag = 123456; // give a any random tag to view
[self.view addSubView:search.view];
[self addChildViewController:search];
}
Please make sure given tag is not assign to other object except search.view in self.view.
Thanks
I have an app, with a lot of views and subviews.
In my app delegate, I open a subview each time I receive a notification.
I made a lot of tests :
- the notifications are always received well.
- the subview is always well created, it's never at nil.
But after a notification or two, the subviews do not show again, even if they exist and are well created in memory.
I think I am doing something wrong with the memory and I probably misunderstood something with the view hierarchy.
Here is the code that create and add the subview :
AppDelegate.h
#property (retain, nonatomic) ViewControllerNewOrder *sub;
AppDelegate.m
sub = [[ViewControllerDriverNewOrder alloc] init];
sub = [mainStoryboard instantiateViewControllerWithIdentifier:#"ViewControllerNewOrder"];
sub.view.frame = self.initialViewController.view.bounds;
[self.initialViewController.view addSubview:sub.view];
Thank you for your time and your help !
The following line saved my life :
[self.window.rootViewController.view.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
Then I added the method removeFromSuperView to all the views I needed to clear.
Of course, you will need, like me, to think about where you place this line.
Thanks ;)
Im struggling to solve in a very clean way a problematic involving memory overload (management).
Im having a serie of view that include other views, in my project I have a situation like this:
MainView
|_PageView
|_CustomButton
soo far soo good, easy as a cake. CustomButton have a delegate (protocol) in it for some reasons, so we have in PageView a "for cycle" that creates N CustomButtons, set the delegate as self in PageView (PageVew extend CustomButtonDelegate) and release the buttons afer attaching them like
{
CustomButton *customButton_ = [[CustomButton alloc] initWithFrame:CGRectMake(100.0,50+(i*55.0),200.0);
customButton.delegate = self;
[self addSubView:customButton_];
[customButton_ release];
}
soo far soo good again. Button will be press, PageView get the protocol method, do some code and voilĂ , done. One problem is that at one point, MainView must remove PageView, so In a method I call
[pageView_ removeFromSuperview];
[pageView release], pageView_ = nil;
pageView_ = [PageView alloc] initWithFrame.....];
and I recreate the object with other data to display.
I noticed that PageView never gets release and removed from the memory because its retainCount is exactly how many CustomButton I created inside PageView and assign the delegate to self plus one of course. My question is, what is the cleanest way to remove safely all the objects and be able to remove PageView too, free the memory (because Im loading a quite large amount of data to display in it) ?
Right now i'm doing:
Create in PageView a NSMutableArray, that I CustomButton the objects in
it, and before to remove PageView, I cycle it and set the delegate = nil and then release
each object, after I release the NSMutableArray (called "holder").
But the problem is that if I want to add more objects of different types with other protocols, adding to this array, can lead to other problems of retaining the objects.
Where do I lack guys, knowledge so I need to study more (quite sure I can say) or do I need to approach with another OOD?
Thank you guys, im going overload with this problem and my brain is stuck in a close road. :)
Looks like your CustomButton's delegate is a retain property of CustomButton. Delegate should be an assign property, not retain nor copy. See here.
This is my first post and I am admittedly over my head, but I do need some help.
I downloaded Apple's KMLViewer example to look at overlays in maps. After getting it to work, as part of my "investigation," I then added the line
map = [[MKMapView alloc] initWithFrame:self.view.frame];
right after the line
[super viewDidLoad];
I know I didn't have too, but I had another project that required programmatically creating a MKMapView and I wanted to verify the approach on a simpler, working program.
The result was the KMLViewer compiled and executed with no errors, but no longer showed the overlays created by the kml files. If the line was removed, the overlays showed up again.
What am I missing?
Thanks in advance for any help.
The map variable in KMLViewer is declared as an IBOutlet and is connected to the MKMapView in the xib. By re-creating it, the new instance is no longer connected to the one in the xib.
The overlays are probably not showing because:
the delegate on the new instance is not set (so viewForOverlay, etc. won't get called)
the new map isn't added as a subview
So if you added the following two lines after the alloc+init, it should start working again:
map.delegate = self;
[self.view addSubview:map];
However, the MKMapView in the xib will still be there underneath the new map instance.
I'm new to iPhone dev and need some help with adding subViews.
I have a reusable object that I made that is stored in a separate .h .m and xib file.
I would like to use this object in my main project's view controller. I have included the header and the assignment of the object generates no errors. I am able to load the object into my main project but can only do things with it inside my viewDidLoad method. I intend to have a few of these objects on my screen and am looking fora solution that is more robust then just hard wiring up multiple copies of the shape object.
As soon as I try to access the object outside of the viewDidLoad it produces a variable unknown error - first use in this function.
Here is my viewDidLoad method:
shapeViewController *shapeView = [[shapeViewController alloc] initWithNibName:#"shapeViewController" bundle:nil];
[self.view addSubview: shapeView.view];
// This is the problem line
// This code works changes the display on the shape object
[shapeView updateDisplay:#"123456"];
---- but the same code outside of the viewDidLoad generates the error.
So to sum up, everything works except when I try to access the shapeView object in the rest of the methods.
Thanks in advance
You need to declare the shapeView instance in your interface, not just inside one function. Then the code in the function becomes just an initialization.
So, in your .h file, inside the #interface you write the declaration:
shapeViewController *shapeView;
And in your viewDidLoad, you will initialize what you declared before:
shapeView = [[shapeViewController alloc] initWithNibName:#"shapeViewController" bundle:nil];
[self.view addSubview:shapeView.view];
Now you can use shapeView in your entire class.