how to access a variable from another nib file in ios - ios

I have two view controller files which is InputViewController and CurrencyViewController. I want to access the variable declared in InputView inside CurrencyView. It is designed in Empty Application Project.

You can declare the variable globally in AppDelegate & then can access in both viewController.
The changes made in the variable will reflect in both controllers.
Make the variable as a property of AppDelegate.h class
eg. #property (strong, nonatomic) NSString *Var;
& synthesize it in AppDelegate.m
#synthesize Var;
declare "AppDelegate * appDelegate" in both Controllers.h & then in controller.m in viewDidLoad write appDelegate=[[UIApplication sharedApplication]delegate];
now the variable can accessible using appDelegate.var anywhere in your code of both ViewController & changes are also reflected in both.
Hope this will work more efficiently for your need.

Related

__weak IBOutlet ivars need release and/or bad practice?

I am using XCode 5.1.1, targeting iOS 7.0.
When creating outlets from my storyboard using the Assistant editor. I notice I have a few choices to create properties or ivars. The one I have been using is dragging directly to my *.m #implementation and it creates code like:
#implementation AudioViewController
{
__weak IBOutlet UILabel *posLabel;
__weak IBOutlet UILabel *durationLabel;
__weak IBOutlet UIButton *playButton;
}
I have no need to access these outside of this class, so this seems convenient, but I am wondering if there are any "gotchas" to this method vs creating properties, especially in regards to memory management. I read on other stack answers that you must create (weak) properties or I will have to [release] manually. I am wondering if this __weak takes care of that in this context?
Thanks!
Creating properties and instance variables with the same modifier is mostly analogous. When you are using ARC, you do not have to release strong properties or instance variables - they will be released when the object is deallocated. Interface element outlets are usually created as weak, because they are retained by the view hierarchy. You should be careful; if you intend to remove the elements from the view hierarchy at some point, you should change the modifier to strong to ensure they are retained by the view controller. Top-level outlets should also be created as strong to make sure they are retained after nib load.

programatiically creating views strong properties

Previously I've been creating my views with interface builder.
When creating views with storyboards or nibs I would connect my outlets. I understand that the outlets are creating a strong connection to the properties on the view.
If I am creating views programmatically should my properties be strong?
.h
#interface LoginViewController : UIViewController <UITextFieldDelegate>
#property (nonatomic, strong) UIView *loginView;
#property (nonatomic, strong) UITextField *usernameTextField;
#property (nonatomic, strong) UITextField *passwordTextField;
#property (nonatomic, strong) UIButton *signInButton;
#end
.m
#interface LoginViewController ()
#end
#implementation LoginViewController
- (void)initViewsAndLayout
{
_loginView = [[UIView alloc] init];
_loginView.frame = self.view.bounds;
[self.view addSubview:_loginView];
//...
}
#end
A few things:
Your code isn't using the properties you defined
Don't put the private properties in the .h file
Don't state that your class conforms to the UITextFieldDelegate protocol in the .h file
As for whether the properties should be strong or weak I prefer strong but since you will be adding each of these properties (views) to the view controller's view, it would be fine to make them weak since there will always be a reference to them as long as the view controller is alive.
Your .h should just be:
#interface LoginViewController : UIViewController
#end
Your .m should be (assuming you do want to use the properties):
#interface LoginViewController () <UITextFieldDelegate>
#property (nonatomic, strong) UIView *loginView;
#property (nonatomic, strong) UITextField *usernameTextField;
#property (nonatomic, strong) UITextField *passwordTextField;
#property (nonatomic, strong) UIButton *signInButton;
#end
#implementation LoginViewController
- (void)initViewsAndLayout
{
self.loginView = [[UIView alloc] init];
self.loginView.frame = self.view.bounds;
[self.view addSubview:self.loginView];
//...
}
#end
When you use the strong attribute, you are basically writing retain, as in, you want Objective-C to allocate memory for the property and hold it until it is released.
That is all strong means.
This is only necessary if you are using ARC (though you can still use retain in ARC). If not, use retain.
"If I am creating views programmatically should my properties be strong?"
If they are objects and not primitives, then yes.
I recommend you to make properties with strong attribute if you want to create it manually not to use xib or storyboard.
As your code in initViewsAndLayout, if you always create a subview and add it to a view of a viewcontroller simultaneously in same method scope, there is no problem even if you use weak or assign attribute. addSubview will increase a reference count of the subview. But, I don't think it's such a good habit because all of us could make a mistake.
Therefore, you had better make a property of UIView with strong attribute.
You asked:
If I am creating views programmatically should my properties be strong?
Two part answer:
The view controller should definite maintain a strong reference to its top level view.
When not using NIBs or storyboards at all and doing everything programmatically, the root view is instantiated in loadView and generally stored in a retain/strong property. UIViewController already has a view property that bears the retain memory semantics, thats generally used. (For more information about programmatically created views, see the Creating a View Programmatically section in the Resource Management in View Controllers chapter of the View Controller Programming Guide for iOS)
(If you're not creating the root view in loadView and are instead instantiating the root view with a NIB or storyboard and are only programmatically creating the subviews, don't worry about the above discussion, as the NIB/storyboard takes care of all of that for you.)
For the subviews, when you call addSubview, the view is retained by its parent view. It's unnecessary for the view controller to also maintain strong reference to it as well. You can, but it is not necessary.
In my mind, the view owns its subviews, not the view controller. If one of these subviews is removed from its parent view, I don't think the view controller should be retaining it and it doesn't seem like good design that I have to remember to nil the property in the view controller, too. Worse, if I remove a container view that has nested subviews, I don't want to have to manually keep track of setting all of those individual properties in the view controller that I have to nil, as well.
Don't get me wrong: You can use strong with the subviews if you want/need. But I think it's incorrect to imply that it's ill-advised to use weak.
As a simple rule of thumb,
Any view is always owned (maintained by strong reference) by its
superview, when they are added to the superview.
A top-level view is always owned (maintained by strong reference) by its VC.
Now, a view can be added to its superview in two different ways,
When a view is created from code and added to some superview using addSubview: method. (This is what your question suggest).
When the view hierarchy is loaded from a nib file. (Here also implicit addSubview: calls are made by UIKit to create the hierarchy) and thus subviews are retained by strong reference their respective superviews.
So in either cases views are implicitly retained by their superviews and thus never get disposed until/unless the top-level view gets disposed by itself. So declaring strong properties for subviews imposes another ownership on the subviews:
An implicit ownership by its superview, and
An explicitly ownership by the property.
So in general, declaring strong property for subviews are not required, however it has been created (from nib / by code).
However, under some special situation declaring strong properties for views might be required. For example, when a view should be removed and re-added to its superview, the view should be declared as strong. When such a view is removed from its superview, the superview releases its ownership as well. So if we need to maintain a strong reference of that view if we need to reassign the same view again to some superview. In that case, a strong property reference to the view becomes handy and it disallows the view to be released.
PS:
When creating views with storyboards or nibs I would connect my
outlets. I understand that the outlets are creating a strong
connection to the properties on the view.
I found that there's merely a misconception, in your question. When creating view from storyboard/nib, outlets does not create any so-called strong connection with the properties. IBOutlets only describe how a property loads a view. In case of an outlet property, the view pointed by the property is unarchived and loaded if it has not already been loaded. However, its retention still depends on the strong/weak property accessor.

mapView:regionDidChangeAnimated: never called

In the storyboard I have a Navigation Controller in Relationship with a View Controller.
The View Controller contains a MKMapView.
The View Controller is also set, in Identity Inspector -> Custom Class, to be a custom controller: MapViewController.
This is MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MarkerAnnotation.h"
#import "MarkerButton.h"
#import "MainMapView.h"
#interface MapViewController : UITableViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *localMapView;
#end
localMapView is linked to the MKMapView placed in the ViewController on the storyboard through "Referencing Outlets", and I'm using it already in the code on .m file for things like setting annotations or getting "bounds.origin".
Every time the user moves the map I need to run some lines to update the map.
So, I tried to implement mapView:regionDidChangeAnimated: on the .m file, but this is never called.
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSLog(#"Region changed");
}
I tried creating a custom subclass of MKMapView implementing on that class the method, but wasn't called either. (you can still see in the imports of .h file, MainMapView.h... I still haven't deleted the import)
Is there something I'm missing? Do I have to set some more connection between the map and the current class?
Otherwise, is there another way I can trigger an event every time the map moves?
When delegate methods don't get called, first thing to check is whether the object's delegate property is set or connected.
(Declaring that a class implements the delegate protocol in the .h file is not the same thing -- that just lets the compiler know what should be expected of the class code implementation so it can provide compile-time warnings.)
So in addition to the referencing outlet, you must also connect the map view's delegate outlet to File Owner or in code (generally in viewDidLoad) do mapView.delegate = self;.

Cannot remove a uiscrollview

I am working on an iPad app and i utilise a UISplitview for my program.
Now on the main detail view of my program i have a uiscrollview on which i add two labels.
UIScrollView *scroll=[[UIScrollView alloc]initWithFrame:CGRectMake(0,0, self.view.frame.size.width,self.view.frame.size.height)];
scroll.contentSize=CGSizeMake(320, 1600);
scroll.showsHorizontalScrollIndicator=YES;
scroll.backgroundColor=[UIColor clearColor];
[self.view addSubview:scroll];
This is the code i create on the first main page. Now imagine we push the second view, from that second view i can access everything by saying
[self.detailViewController.view addSubview:detailViewController.Image];
but when i try to add labels to the subview saying
[self.detailViewController.view.scoll...
but i cannot find the scroll object, BUT the background of the scroll set in the first view comes over in the second view. AND i cannot change the background of the first view.
I decided to make a second scrollview untop of the first (which works) but i much rather know how i can access the first view i created throughout the whole program since it would negate me having to waste space creating scroll views. but if i have to create all the views i need i want to be able to somehow delete or release them so the picture from scrollview one doesn't get transferred all the way too scrollview 3
Thank You
You have to create properties for all the variables that you want to access from other classes . So in your case
DetailsViewController.h
#interface DetailsViewController : UIViewController {
// class member variables here that can be accessed
// anywhere in your class (only in your class)
}
#property(nonatomic, strong)
//retain instead of strong if you are not using ARC or other types (weak, copy, readonly)
SomeClassThatYouHave *propertyThatCanBeAccessed
//declare here public instance methods
#end
In your DetailsViewController.m you will have:
#interface DetailsViewController (Private)
//declare private methods here or private properties
#end
#implementation DetailsViewController
#synthesize propertyThatCanBeAccessed;
//methods implementation here
#end
Now you can access the property of your DetailsViewController like detailsViewControllerInstance.propertyThatCanBeAccessed but you must alloc/init the instance.
Hope that this will give you an idea of class structure in the future.

ios AppDelegate property declarations

After reading some tutorials online, I've seen 2 different ways to declare properties.
I'm wondering if one is more correct than the other:
Option 1:
#import <UIKit/UIKit.h>
#interface AppDelegate : NSObject
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UITabBarController *mytabs;
#end
Option 2:
#import <UIKit/UIKit.h>
#interface AppDelegate : NSObject {
UIWindow *window;
UITabBarController *mytabs;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) UITabBarController *mytabs;
#end
The first option uses Automated Reference Counting (ARC); the second one does not. Neither one is "more correct" than the other - the first one is simply more modern. You should use ARC unless you have strong reasons not to (e.g. because of the need to support legacy code on legacy platforms).
Here is a link to learn more about ARC.
Option 1 has ARC enabled. Since iOS5 SDK it's the default option in Xcode.
strong means that the view controller will manage this variable
Here is a good ARC tutorial for iOS5.
Option 2 has Automatic Reference Counting disabled.
the view controller will retain (increase the retain count) when the variable is set
It used to be necessary to explicitly declare an instance variable to back each property. With the "modern" runtime, that's no longer required -- your #synthesize directive for the property will take care of creating the iVar if one doesn't already exist. Some people still keep the ivar declaration, either out of preference or just habit, and of course you'll see the ivars declared in older code. One benefit of doing it is that you can more easily see the values of your properties in the debugger.
The difference between using strong and retain is a matter of using ARC or not, respectively.

Resources