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;.
Related
I'm learning iOS and am new to the concept of IBOutlets - so I'm making a simple app in an attempt to learn how it works.
The problem:
I created an interface using a Storyboard and want to hook it up to an IBOutlet in my custom class ("TapCounter") in order to access (and be able to set) its text field. However when trying to hook my class' #property (nonatomic, weak, readwrite) IBOutlet UILabel* numberOfTapsTextField;
up to the UILabel in the Storyboard the line does not want to attach to the label.
Here is an image of the situation: http://gyazo.com/0050ef0a78772adcad214cdc4603f932 (Dragging a line from the hollow circle next to the #property to the label in the Storyboard does not snap to it).
I have not modified anything of the boilerplate code except for that I added #import "TapCounter.h" in viewController.m
This feels like it should be a very simple thing - but again; I am new to this.
EDIT
Have I got this idea wrong? Should all IBOutlets be in the viewController of a view (and simply be accessed by other custom classes)?
It work like this:
create a CustomView class
add a view in you storyBoard
set class for this custom view as CustomView in identity inspector cmd+opt+3
Create an IBOutlate of your component inside customView
Link those component with respective outlet
Refer Image:
I am using the Mapbox iOS SDK to show offline OpenStreetMaps data in my iOS app. I have successfully done this programatically, but now I would like to do this using the Interface Builder. To do so I have created a subclass of UIViewController with a .xib file and put a UIView into the main view of the xib. Then in the identity inspector I changed this view's Custom Class to RMMapView and put an IBOutlet into the header of of the UIViewController and connected it with the Custom RMMapView object in the xib.
#property (weak, nonatomic) IBOutlet RMMapView *mapView;
So far I think this should be correct. When I start the app the RMMapView is created in the nib and shows the default behavior, i.e. it shows a map with the "Example" watermarks. Therefore I need to set the appropriate tilesource, so far I did this in the viewDidLoad method of the ViewController, something like
RMMBTilesSource *tileSource = [[RMMBTilesSource alloc] initWithTileSetResource:#"mymap" ofType:#"mbtiles"];
followed by
[self.mapView setTileSource:tileSource]
or alternatively
[self.mapView addTileSource:tileSource]
However, even after these calls the mapView's RMTileSourcesContainer has still value nil and from what I can tell the set/addTileSource calls practically don't have an effect.
In my opinion the problem is that in RMMapView initWithCoder has not been overwritten and therefore the RMMapView is not initialized properly through the nib, most importantly the RMTileSourcesContainer is not initialized. Is this really the case ? Why has initWitCoder not been overwritten ? How should I go about using RMMapView in the Interface Builder ?
Thanks for your help!!
You want to try this in -viewWillAppear: or later, not -viewDidLoad. Due to the way the RMMapView is based on UIScrollView, the map view needs to added to a live view hierarchy before it can set its parameters.
If I start with the very minimalist UI implementation consisting of adding a single UIButton (with the corresponding IBOutlet) to the default view in the default storyboard and adding an action method to my controller class, then everything works correctly (i.e. my action gets invoked when I tap the button).
Now, if I simply include MediaPlayer/MediaPlayer.h to my view controller header file, like that:
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#interface Playing_Video_FilesViewController : UIViewController
#property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
#property (nonatomic, strong) IBOutlet UIButton *playButton;
#end
and add the MediaPlayer framework to the project, it crashes with the infamous "this class is not key value coding-compliant for the key playButton".
If I remove the MediaPlayer framework reference from the project, it stops to crash. If I instead remove the button but leave the MediaPlayer framework, it stops to crash as well.
Is there something else I should do to use MediaPlayer and a basic standard UI at the same time?
Edit:
I circumvented the problem by creating a .xib file instead of using the storyboard, like how it's done in the VideoPlayer sample application which doesn't use storyboards. Same code, but now it works.
I see this whenever I have an outlet or action that is no longer hooked up properly.
1.) Open storyboard
2.) Select playButton
3.) Remove all outlets and actions from this item
4.) Remove plugs from your class that were previously attached (especially in dealloc)
5.) Create new outlet and control-drag from the storyboard to your class. Good to go.
-A little overkill but gets the job done for me everytime.
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.
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.