MVC. Setting data in View - ios

View does not know about the model. I have custom view:
#interface CustomView : UIView
#property UIImageView *imageView;
#property UILabel *labelView;
#property UILabel *dateLabelView;
#property UIImageView *badgeView;
...
#end
Set data in ViewController:
-(void)viewDidLoad
{
[super viewDidLoad];
...
//Install data from model in view
self.customView.labelView.text = self.model.title;
self.customView.badgeView.hidden = self.model.isBadge;
self.customView.dateLabelView.text = [self formatDate:self.model.createDate];
...
}
How to use CustomView in other ViewControllers, without having to copy code and or creating the following method in the class CustomView:
- (void)setData:(id)data;
because View does not know about the model.

Related

Initialising view controller with IBOutlets to custom views

I am trying to find a way to initialise a view controller which has IBOutlets to a custom view that I have created in a XIB.
Here is the code where I initialise my class:
MyContentViewController *pageContentViewController = [[MyContentViewController alloc] init];
self.pageContent = pageContentViewController;
[pageContentViewController view];
MyContentViewController has the following properties:
#interface MyContentViewController : UIViewController
#property (nonatomic, weak) IBOutlet MyContentView *topLeftView;
#property (nonatomic, weak) IBOutlet MyContentView *topRightView;
#property (nonatomic, weak) IBOutlet MyContentView *bottomLeftView;
#property (nonatomic, weak) IBOutlet MyContentView *bottomRightView;
In MyContentViewController xib I have 4 views which I have set as MyContentView and have hooked the IBOutlet's above to the views in the storyboard.
The custom view is defined as following:
#import <UIKit/UIKit.h>
#interface MyContentView : UIView
#property (nonatomic, strong) IBOutlet UILabel *labelView;
#end
However when I run the application, I get the 4 views I have added in the MyContentViewController xib. However none of them display the UILabel from the custom UIView.
I have added the following in MyContentView:
- (void)awakeFromNib {
NSLog(#"VIEW AWAKE");
}
This get printed out so the views are being loaded. However how can I get them to display using the 4 IBOutlets.
Here is a picture of the app running with the view. There is no labels on the 4 views:
I see that your "MyContentView" has a nib of it's own. Loading a custom UIView class which has a nib layout from another nib is a bit more complex.
I think this blog post contains the answer

Unable to show child view (iOS view container)

In my iOS application, I have a main View Controller with three buttons, which work like a tab bar: when I click one of the buttons, a new view controller is invoked.
I tried to implement this via container view containers, so I tried following this guide (http://www.thinkandbuild.it/working-with-custom-container-view-controllers/) and invoke the presentDetailController method in the viewDidLoad of the main controller.
Actually, no views are showed: someone can help me figuring out why? Thanks.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *btnOne;
#property (weak, nonatomic) IBOutlet UIButton *btnTwo;
#property (weak, nonatomic) IBOutlet UIButton *btnThree;
#property (weak, nonatomic) IBOutlet UIView *detailView;
- (IBAction)click:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "FirstViewController.h"
#interface ViewController ()
#property UIViewController *currentDetailViewController;
#end
#implementation ViewController
#synthesize btnOne, btnTwo, btnThree;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
FirstViewController *fvc = [[FirstViewController alloc]initWithString:#"I'm the first Controller!"];
[self presentDetailController:fvc];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)click:(id)sender
{
// button selection stuff
[self addDetailController:sender];
}
- (void)presentDetailController:(UIViewController*)detailVC{
//0. Remove the current Detail View Controller showed
if(self.currentDetailViewController){
[self removeCurrentDetailViewController];
}
//1. Add the detail controller as child of the container
[self addChildViewController:detailVC];
//2. Define the detail controller's view size
detailVC.view.frame = [self frameForDetailController];
//3. Add the Detail controller's view to the Container's detail view and save a reference to the detail View Controller
[self.detailView addSubview:detailVC.view];
self.currentDetailViewController = detailVC;
//4. Complete the add flow calling the function didMoveToParentViewController
[detailVC didMoveToParentViewController:self];
}
- (void)removeCurrentDetailViewController{
//1. Call the willMoveToParentViewController with nil
// This is the last method where your detailViewController can perform some operations before neing removed
[self.currentDetailViewController willMoveToParentViewController:nil];
//2. Remove the DetailViewController's view from the Container
[self.currentDetailViewController.view removeFromSuperview];
//3. Update the hierarchy"
// Automatically the method didMoveToParentViewController: will be called on the detailViewController)
[self.currentDetailViewController removeFromParentViewController];
}
- (CGRect)frameForDetailController{
// newFrame's height should be currentFrame's height minus buttons' height
CGRect detailFrame = CGRectMake(0, 0, self.detailView.bounds.size.width, self.detailView.bounds.size.height-self.btnOne.frame.size.height);
return detailFrame;
}
- (void)addDetailController:(id)sender {
FirstViewController *detailVC = [[FirstViewController alloc]initWithString:#"First button clicked"];
[self presentDetailController:detailVC];
}
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface FirstViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UIButton *btnOne;
#property (weak, nonatomic) IBOutlet UIButton *btnTwo;
#property (weak, nonatomic) IBOutlet UIButton *btnThree;
- (id)initWithString:(NSString*)string;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController (){
NSString *text;
}
#end
#implementation FirstViewController
- (id)initWithString:(NSString*)string {
self = [super init];
if(self){
text = string;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = text;
}
#end
As part of creating FirstViewController, you are calling [super init] which produces a bare UIViewController. From your diagram, it seems as if you want to load a FirstViewController from your storyboard instead.
I suggest a sequence where you create your controller using instantiateViewControllerWithIdentifier:, then set a string property in the controller that you want to use as the label, and finally assign the string to the label when the controller's view loads.

managing iboutlets in base view controller

Every UIViewController of my app is using the UITextField delegates, like:
- (void)textFieldDidBeginEditing:(UITextField*)textField {
self.responder = textField;
}
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
double elementYPosition = self.responder.frame.origin.y;
double elementHeight = self.responder.frame.size.height;
double scrollYPosition = self.scrollView.contentOffset.y;
/* some logic */
}
Now I'm trying to create a base view controller, so I can inherit use it all around, reusing the methods. The responder property in the base view controller works just fine, because the UITextField delegate set its value, but the scrollview is a IBOutlet, and I'm not really sure how to design this base class:
#import "ViewControllerBase.h"
#interface ViewControllerBase ()
#property (weak, nonatomic) UIView* responder;
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView; /* ??? */
#end
#implementation ViewControllerBase
-- methods
#end
In the subclass header:
#property (weak, nonatomic) UIScrollView *scrollView;
In the subclass load method:
self.scrollView = (UIScrollView *)self.view.subviews[0];
But it only works because my view controllers are always in the following format:
UIViewController (self)
UIView (self.view)
UIScrollView (self.view.subviews[0])
UILabel
UIElement
UIElement
UIElement

iOS 5 create custom UIButton reusable component with .XIB

I'm newbie in the iOS development and I'm working in a projecte that it uses iOS5 and Storyboarding. I would like to create a reusable component, like a button, with a custom view (inside the button there will be some images and labels, it will be a big button), to create some of them in the same view of a Storyboard.
So I've created a XIB file (ItemClothes.xib) with a UIButton and inside of it some UIImagesViews and a UILabel. Then I've created a subclass of UIButton (UIItemClothes.h and UIItemClothes.m), with properties for UIImageViews and UILabel components.
UIItemClothes.h
#import <UIKit/UIKit.h>
#import "SCClothes.h"
#interface UIItemClothes : UIButton
#property (nonatomic, strong) IBOutlet UIImageView *imageClothes;
#property (nonatomic, strong) IBOutlet UIActivityIndicatorView *loadingImage;
#property (nonatomic, strong) IBOutlet UIImageView *seasonIconClothes;
#property (nonatomic, strong) IBOutlet UIImageView *categoryIconClothes;
#property (nonatomic, strong) NSString *idClothes;
#property (strong, nonatomic) IBOutlet UILabel *lblProva;
#end
UIItemClothes.m
#import "UIItemClothes.h"
#implementation UIItemClothes
#synthesize imageClothes = _imageClothes;
#synthesize loadingImage = _loadingImage;
#synthesize seasonIconClothes = _seasonIconClothes;
#synthesize categoryIconClothes = _categoryIconClothes;
#synthesize idClothes = _idClothes;
#synthesize lblProva = _lblProva;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:#"ItemClothes" owner:self options:nil] objectAtIndex:0]];
}
return self;
}
#end
Then in the .XIB file I've set the class of UIButton as UIItemClothes, and make the relationships between XIB's UI components and my class properties.
So, after that, in the Storyboard, in the ViewController of one view I've written this code:
UIItemClothes *item = [[UIItemClothes alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 200.0)];
item.lblProva.text = #"test!";
[item.categoryIconClothes setImage:iconCategory];
item.seasonIconClothes.image = iconSeason;
[cell addSubview:item];
As you see, this component will be inside a TableViewCell, and the idea is to put more components (UIItemClothes) inside of it.
The problem is that the component is drawed but any outlet is set as I do in the code above.
Can anyone help me?
Thanks!
well, the problem has been resolved... Instead of having a custom subclass of UIButton, there will be needed a ViewController with all Outlets. Then in the other ViewController (StoryBoard) is initialized this new ViewController

Loading / creating views from NIB for GeoLocation - IOS and MapKit

I have two classes - MapView and MapController. The main idea is to make View a shared object in MVC pattern.
MapView has IBOutlet "mapView" for MKMapView located in MapNib.xib
MapController contains property "mapView" referencing to class MapView
Then i try to set some properties of MKMapView from controller and it does not react on this anyway. For example i try in MapController :
self.mapView.mapView.showUserLocation = YES; // does not show blue point ...
MapView Class :
#interface MapView : UIViewController
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
...
//UINib *view = [UINib nibWithNibName:#"MapView" bundle:nil];
//[view instantiateWithOwner:self options:nil];
#end
MapController Class :
#interface MapController : UIViewController<
CLLocationManagerDelegate,
MKMapViewDelegate>
#property (nonatomic, retain) MapModel *mapModel;
#property (nonatomic, retain) MapView *mapView;
...
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView = [[[MapView alloc] init] autorelease];
self.mapView.mapView.showsUserLocation = YES;
} #end
I tried to make MapView a subclass of UIView, UINib, UIViewcontroller, tried to load NIB directly using UINib::nibWithNibName, UIViewController::initWithNibName, UIViewController::loadNibNamed - it does not matter ... i can see the map but blue point is not shown anyway ... why???
Only one combination works for me - to name NIB the same way as controller (MapController.xib) and add outlet for MKMapView as controller property ... it seems like it is impossible to load NIB / View in one class and use it in another, am i right?
Somehow this works fine :
#interface MapController : UIViewController
#property (nonatomic, retain) IBOutlet MKMapView *mapView; // NIB was renamed to MapController.xib
...
#end
And then in controller :
self.mapView.showUserLocation = YES; // now this shows blue dot ... why???
Thanks, Art
IBOutlets do not need to be created. The NIB creates them and assigns them to your vars, your are overwriting it by allocing and initing a new mapview and saving it to that variable

Resources