I have a Navigation View Controller and many of it's child VCs have maps. And if I go down navigating through n views, I'll have always n-1 maps allocated in memory.
My idea is to deallocate a map every time the view controller disappears, and reallocate it when it appears again.
However, they were laid out using a storyboard, and their frames change depending on the devices orientation because I'm using constraints. This way, when the VC is loaded for the first time, it appears as on the storyboard. But when I deallocate it and I have to reallocate, I don't know how to set the frame correctly, or how to add the constraints properly.
What is the best way to do this?
You'll need to read up on creating constraints programmatically. You can use the debugger to log the constraints on your map view before deallocating it, and then write code to recreate those constraints when you add the map back in.
You have to read the property like user location and other attribute and save it before setting to nil and when you comes back check this object in viewWillAppear like
if(!mapView) {
allocate here and set the saved values
}
Related
I would like to update my UILabel on click the button of ContainerView contains table ViewController. When I try to do this UILabel's outlets reference shows nil value exception. I am using Swift3 with Xcode8
Most probably the problem you are seeing is due to the fact that the view that owns this label on another view controller is still not loaded.
This happens often, basically because views owned by a view controller are instantiated in a lazy manner, this means that they are loaded only when required.
To fix that before setting the value on the label, just preload the view by doing something like.
_ = another_viewcontroller_instance.view
In this way you are forcing the destination view controller to load the view and creating all the necessary connection on the xib.
Even if this fix works, this is not a good way to deal with this kind of pattern (sending info from a VC to another), but since you didn't gave us any further detail this is the only solution I have.
I got a MKMapView on a ViewController in Storyboard and set constraints for it. The thing is, that i want to use one single instance (which i created programatically) on multiple ViewControllers (it is the same ViewController multiple times --> on a PageViewController).
My question is if this is working or do i have to set the constraints for the mapView programatically. If so, i don't know how to set them properly in code for my MapView, could someone help there?
Need to give it a TopSpace to the last SubView and a BottomSpace to Container. Leading and Trailing Space set to 0.
Working with Swift.
i want to use one single instance (which i created programatically) on multiple ViewControllers (it is the same ViewController multiple times --> on a PageViewController).
You can't. The same instance of a UIView cannot appear in multiple superviews. This is basically for the same reason that you cannot be in two places at once.
Instead, as one view controller's view goes away, capture the center and span of its map view and pass that info along to the next view controller, so that its map view reproduces what the user was seeing previously.
I'm quite new to IOS so I'm sorry if my question is obvious.
I have set a ViewController's view in storyboard which contains other subviews.
In viewWillAppear I update these subviews depending on the object I passed to this ViewController. This object can have nil attributes and in this case I want to remove these subviews.
What is the right place to remove these subviews and is there a difference in terms of efficiency?
viewDidLoad
viewWillAppear
or viewWillLayoutSubviews ?
and will the constraints set to these removed objects also be removed?
Thx
The constraints will definitely be removed. However, it is possible to save the constraints in an array and add them back again in the future.
I would suggest making changes to the views( orientation, visibility, geometry ) in the viewWillLayoutSubviews method. You wouldn't want to do anything expensive in the ViewWillAppear method, because at that point the view is ready to be displayed to the user and it could impact how quickly the view appears to load for the user.
If you are using Storyboard and ARC do not worry about removing your views, conversely, if you are very interested to keep your memory under very tight control then do not use Storyboard and remove ARC.
What you refer to subviews are not subviews, the methods you listed are not UIView methods, and instead are UIViewController methods. However, if you have UIView objects that you are trying to remove, then those will also be handled for you. If you want more tight control, then declare them as public ivars, wrap them in #autoreleasepool {}, and set to nil in viewWillDisappear: or other method, or via delegate or notification pattern. It's relative to what you are doing and your conditions.
I am creating a simple little popup view, similar to the popup that appears when you push the volume buttons. I would like to display an instance of that popup view in different view controllers. I have been pondering a couple approaches, but I would like to know what is the best approach, taking into account MVC, complexity, and otherwise 'good' practices.
Currently, I am creating and displaying this UIView from within my UIViewController. I justified that approach since it's really a small view and I do a lot of work with it to modify its behavior in that VC, so that code was already going to be in the VC. Essentially, I make a frame, set the background, apply corner radius, add text to it, apply motion effects, then make it fade in then later fade out. I could copy and paste the code into my other VCs but that's obviously a bad approach.
I could create a subclass of UIView and I'm sure I could use drawRect to draw it, but I'm not sure exactly how to add that view to the VC exactly in the middle, unless I drag out a view to my VCs and change its class. But if I do that I can do most everything in Interface Builder anyways, which would be preferred especially if I can use Auto Layout to always keep it centered. But, I'd need to copy and paste that UIView into each VC and hide it - that doesn't sound good.
I could create a subclass of UIView and instead of drawing with drawRect, implement a method that creates the UIView and returns it. Then in the VCs I just call that method and add the view it returns as a subview. I've never done this, and I'm not sure if that's an appropriate approach.
What is a plausible approach to implementing such a view that can be thrown on screen from any of my VCs? Thanks!
Note that this view should always be the same size, in the center of the screen, not tied to any specific VC. It should remain on screen unaffected by transitions and such. It closely mimics the Volume popup.
I would like to display that same popup in multiple view controllers.
I expect that you mean you'd like to have separate instances of that same class in multiple view controllers. A given view can have only one superview, so it can't exist in more than one view at a time.
I'm not sure exactly how to add that view to the VC exactly in the middle
It's easy to center a view in its superview. To center horizontally, subtract the width of the view from the width of the parent. Divide the result by 2. That's your X coordinate. Same goes for the Y coordinate, except that you'd obviously use the heights.
An even easier method is to create a point by dividing the superview's width and height each by 2. Set your view's center property to that point.
What is a plausible approach to implementing such a view that can be thrown on screen from any of my VCs?
Don't try to reuse the same view. There's no need for that, and trying to pass it around between controllers will really complicate your code. Just have any controller that needs to display your popup create its own copy.
Remember, views are the interface to the data that's stored in your model -- they can display that data or let you interact with the model, but they shouldn't store app state themselves. Given that, there's no reason that you'd need to use the very same view in more than one view controller. As long as your pop up gets its data from the right place, you can have as many instances of it as you like.
If your popup really is separate from the content of any of your view controllers, another possible strategy is to use view controller containment. You can create one view controller that handles just the "app-wide" stuff, like this popup, and have it load and unload the various other view controllers as it's children. I'd caution against trying this, though -- it's probably more complicated than you need and surely more complicated than you should attempt right now given that you seem to still be getting your sea legs.
It sounds like MBProgressHUD is what you're looking for. FFCircularProgressView might also help.
I am wondering what happens if a single instance of a UIView object gets added as a subview of multiple other views simultaneously.
If UIView:removeFromSubview: gets called then does it get removed from all superviews or just the currently displayed one?
For background:
I have a status-bar like view object that needs to be displayed within several different other views (each other view is managed by its own view controller).
[i.e. a) the user is in one view, b) something happens to make the status-bar-like view appear, c) the user switches to another view d)the status bar is still visible in the new view e) the status bar expires after a time and disappears from site. And so on]
Initially I implemented this by adding/removing it as required as a subview of the window, and this was managed by a singleton.
However due to some complications with some animations I have instead added it as a subview of each of the main view's for each of the view controllers.
Note that there are not multiple copies
When the view needs to be removed I am calling its removeFromSuperview:, and everything is all working perfectly.
However I am wondering what the situation is regarding the removal of the view, is it being fully removed or is there something else I need to do?
For example the view might get added to N view controller's views by calling addSubview as required (it will only get added to each view controller if that view controller actually launches)
However when it is being removed I am only calling removeFromSuperview: for the view of currently loaded view controller, not all view controllers it might have been added to.
Next time I navigate to one of these other view controllers it displays fine without the view being there, even though I didn't explicitly call removeFromSuperView.
As I said everything is working as it is, however at the back of my mind I feel there might be something missing?
Hope this was understandable.
You can only have it added to one view. Documentation is your friend!
(void)addSubview:(UIView *)view:
Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview.
From my point of view, having to add a same view to different parent views (and more important, from different view controllers) is an indication that something is wrong on the design...
However, if you really (really) need so, I had always thought that a view instance could have one and only one parent view... Moreover, you can access it by [myView superview] message, which gives you a UIView instance instead of an array... It may auto remove from its old parent before adding to a new superview?
About the design, what about creating it each time you need a new one and have a singleton to manage their status/logic?
Good luck with that!