How can I use RMMapView in Interface Builder? - ios

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.

Related

Adding an IBOutlet to custom class

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:

Cannot create outlet connections to subviews in Interface Builder (Xcode 5)

I know this appears to be a duplicate of some other questions, but the answers are not working for me.
I have created a single view app.
In the storyboard I added a subview to my main view.
I have a label on my main view and another label on my subview.
I have created a class of type UIView and added it as the custom class for the subview.
I can ctrl-drag my label on my main view to the main view controller class. But when I try to ctrl-drag my label on my subview to my custom class, I cannot get the connection to occur.
I have even typed the property information and tried to make the connection manually to no avail.
Things have changed a bit in the latest version of Xcode's Interface Builder. Can somebody tell me what I am missing? There is literally no code here. I am just testing trying to connect outlets to a subview with a custom class.
The first image shows that I have set up the custom class and added a property but I cannot make the connection.
The second image shows the main view label is connected in the main view's controller.
The third image shows that there are no outlet connections for the subview's label.
You can manually write the IBOutlet property declaration in the #interface of the custom view subclass, and assuming you've defined the base class of your subview in IB, then you can drag from the outlet circle in the code back to the control in the scene.
Or, as you point out, Warren Burton suggested both this technique and another in his answer to this other question, Can't Wire to Subview in IB.
The issue has to do with the File Owner of the View Controller. It is probably set up as being IOViewController, thus you can only make property connections in that .h file.
What you can do, is create another .nib file for the subview and put the subview in there. Then in that .nib file, make the file owner IOSubview. Property connections will work just fine there. Then just add the subview to your IOViewController programatically. Just remember to load the nib file from bundle first.
This is what I did (in Swift):
I Created a new ViewController (e.g. class MyViewController: UIViewController {})
In StoryBoard, I expanded the 'Scenes' (i.e. the tree view of all UI components) and selected 'MyViewController'
Using the 'identity inspector' I assigned the 'MyViewController' class (as oppose to the default UIViewController)
After that I was able to assign an action.
I suspect that for Obj-C it is similar process.
You don't create outlets in the subclass, you create the outlet on the view controller it is on. You need to #import the subclass into IDViewController.h and create an outlet there.
IDViewController.h
#import "IDSubclass.h"
...
#property (strong, nonatomic) IBOutlet IDSubclass *outletName;
Zoom your storyboard to 100%. If you zoom out, to say 50%, then the outlet connection won't work.

I can't create an outlet in Xcode 5

I am trying to link a create an IBOutlet for a UIWebView Element, however whenever I hold down control and drag from the Storyboard to the ViewController.h file, nothing happens and an outlet is not created. I already have an outlet in this file, however, I would like to create another one. Whenever I go to the view controller for the previous outlet and hold control and drag the element to the ViewController.h file a new outlet is created. Is there a setting that I have enabled that stops this shortcut from working. Is there another way to create an outlet for ios in Xcode 5.0.1 on Mac OSX 10?
Fixed issue. The class of the view controller was UIViewController not ViewController. This meant that the ViewController.h and .m files were not showing up under Automatic. Once changed I could view the ViewController.h and .m files and create outlets in them.
I recommend not using storyboard, while it is a lot easier to use, it doesn't let you do many things. To create a new outlet, go to where you want to create it (this will most likely be a header file) and then type: IBOutlet yourOutletType *yourOutletName so to create a UIWebView you would type:
IBOutlet UIWebView *myWebView
and to create an outlet, such as a UIImageView, you could type
IBOutlet UIImageView *imageView
just remember to hook it up in your .storyboard file.
Again, I recommend not using storyboard, it IS a lot easier, yet it really has lots of limitations

Dealloc of UIView subclass prevents running class methods

I've created a UIView subclass with a UIButton inside with target on tap inside.
The selector is implemented inside the UIView subclass and linked by Interface Builder.
But when I run addSubview in parent view controller tapping button will cause
performSelector:withObject:withObject:]: message sent to deallocated
instance
(I use ARC)
I added some console output in dealloc method and I see that right after viewDidLoad ends with addSubview of the UIView subclass, the sublass is deallocated.
How to prevent that sort of situation?
I tried #property(nonatomic, retain), adding instance to some global array...
But no luck.
I understand that ARC releses the object as there is no strong reference left but I couldn't force to prevent that situation.
Any help would be appreciated.
Creating a strong reference of your subview class in your View Controller class may help you solve the issue.
#property (strong , nonatomic) UIView *subclassName;
Are you storing reference of button (UIButton) you are trying to add as subview?
The problem was in linking NIB to Class.
I linked File owner to class instead of linking the UIView object.
Normally when there is working on nib with UIViewController, there is a need to link File Owner to UIViewController class.
But when working on UIView subclass the UIView object must be linked.

Should UIViews have properties?

Using proper MCV with Objective-C can a UIView subclass have #propertys?
i.e. in the .h file
#class MyViewSubclass;
#interface MyViewSubclass : UIView
#property (strong, nonatomic) UILabel *labelLabel;
#property (strong, nonatomic) UILabel *valueLabel;
#end
or should this be done in a UIViewController subclass?
Thanks in advance.
It is most common to subclass UIViewController to manage the labels, fields, images, and other views within a view hierarchy. However, if you are creating a reusable component view that will be used throughout your application, then it's perfectly appropriate to subclass UIView and add properties to your subclass.
From Apple's iOS App Programming Guide:
View controller objects manage the presentation of your app’s content on screen. A view controller manages a single view and its collection of subviews. When presented, the view controller makes its views visible by installing them in the app’s window.
The UIViewController class is the base class for all view controller objects. It provides default functionality for loading views, presenting them, rotating them in response to device rotations, and several other standard system behaviors. UIKit and other frameworks define additional view controller classes to implement standard system interfaces such as the image picker, tab bar interface, and navigation interface.
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AppArchitecture/AppArchitecture.html#//apple_ref/doc/uid/TP40007072-CH3-SW1
It's good for views to have properties, but don't mix model logic into a view. The properties in a view should describe how the property looks, not what the property holds. I would avoid having a property named valueLabel in a view.
An example of view property names is UITableViewCell. It has properties imageView, textLabel, and detailTextLabel.
It's perfectly reasonable for a UIView subclass to have properties. You might need them to implement layoutSubviews, for example.
It is perfectly reasonable, also if you want to create a reusable component that allows for interaction and better flexibility, take a look at UIControl (which is a subclass of UIView)

Resources