Custom input view controller - objective-c

Is it possible to use UIInputViewController subclass as input view on iOS 9? I've tried setting inputViewController property but no custom view controller shows up when my text field becomes a first responder.
#interface InputViewController : UIInputViewController
#end
#implementation InputViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.translatesAutoresizingMaskIntoConstraints = NO;
[self.inputView addSubview:datePicker];
[datePicker.leadingAnchor constraintEqualToAnchor:self.inputView.leadingAnchor].active = YES;
[datePicker.trailingAnchor constraintEqualToAnchor:self.inputView.trailingAnchor].active = YES;
[datePicker.topAnchor constraintEqualToAnchor:self.inputView.topAnchor].active = YES;
[datePicker.bottomAnchor constraintEqualToAnchor:self.inputView.bottomAnchor].active = YES;
}
#end
#interface TextField: UITextField
#property (nonatomic, readwrite, strong) UIInputViewController *inputViewController;
#end
#implementation TextField
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.textField.inputViewController = [[InputViewController alloc] init];
}
#end

Turned out the missing piece was:
self.view.translatesAutoresizingMaskIntoConstraints = NO;
Very frustrating that UIInputViewController does not do this automatically.

Related

What are the best practices for refactoring methods in Objective-C

How can I get this kind of method refactored better?
This is just a sample in my objective-c project, and I am trying to do it all programmatically
Im not sure what the best practices would be, create a protocol? an extension? or refactor further down to additional methods?
- (void)viewDidLoad {
[super viewDidLoad];
// Label to be changed
label = [[UILabel alloc]init];
label.text = #"Changed with code!";
[self.view addSubview:label];
// Label Constraints
label.translatesAutoresizingMaskIntoConstraints = NO;
[label.topAnchor constraintEqualToAnchor: self.view.safeAreaLayoutGuide.topAnchor constant:50].active = YES;
[label.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:20].active = YES;
[label.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-20].active = YES;
}
As an example you could create a UIView subclass that creates the label and makes the layout.
#interface MyView: UIView
#property (nonatomic, strong, readonly) UILabel *label;
#end
#interface ViewController: UIViewController
#property (nonatomic, strong, readonly) MyView *myView;
#end
#implementation MyView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_label = [[UILabel alloc] initWithFrame:CGRectZero];
_label.translatesAutoresizingMaskIntoConstraints = NO;
UILayoutGuide *safeAreaLayoutGuide = self.safeAreaLayoutGuide;
[NSLayoutConstraint activateConstraints:#[
[label.topAnchor constraintEqualToAnchor: safeAreaLayoutGuide.topAnchor constant:50],
[label.leadingAnchor constraintEqualToAnchor:safeAreaLayoutGuide.leadingAnchor constant:20],
[label.trailingAnchor constraintEqualToAnchor:safeAreaLayoutGuide.trailingAnchor constant:-20]
]];
}
return self;
}
#end
#implementation MyViewController
- (void)loadView {
self.view = [[MyView alloc] initWithFrame:CGRectZero];
}
- (MyView *)myView {
return (id)self.view; // it makes view to load regardless which
// property do you use – `view` or `myView`
}
- (void)viewDidLoad {
[super viewDidLoad];
self.myView.label.text = #"Changed with code!";
}
#end

Xcode: How do I change UIPageControl value with swipe gesture?

I have a quick question I was hoping you guys could help me answer. Right now I have a UIPageControl in a storyboard which changes an image depending on what dot you are on, however, as of now you have to press on the dot to change through the dots/images, how can I change through the images/dots by swiping?
Here is my code for my .h
#import <UIKit/UIKit.h>
#interface PageViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *dssview;
- (IBAction)changephoto:(UIPageControl *)sender;
#end
Here is my code for my .m
#import "PageViewController.h"
#interface PageViewController ()
#end
#implementation PageViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)changephoto:(UIPageControl *)sender {
_dssview.image = [UIImage imageNamed:
[NSString stringWithFormat:#"%d.jpg",sender.currentPage+1]];
}
#end
Any help would be greatly appreciated.
Thanks
You can add UISwipeGestureRecognizer to your view and in the selector method of UISwipeGestureRecognizer based on the direction update the UIPageControl object, either increment the current page or decrement.
You can refer the below code.
Adding swipe gesture to the view controller
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipe:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipe:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRight];
Swipe gesture selector
- (void)swipe:(UISwipeGestureRecognizer *)swipeRecogniser
{
if ([swipeRecogniser direction] == UISwipeGestureRecognizerDirectionLeft)
{
self.pageControl.currentPage -=1;
}
else if ([swipeRecogniser direction] == UISwipeGestureRecognizerDirectionRight)
{
self.pageControl.currentPage +=1;
}
_dssview.image = [UIImage imageNamed:
[NSString stringWithFormat:#"%d.jpg",self.pageControl.currentPage]];
}
Add an outlet to the UIPageControl in the .h file
#interface PageViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *dssview;
#property (strong, nonatomic) IBOutlet UIPageControl *pageControl;
- (IBAction)changephoto:(UIPageControl *)sender;
#end

iOS / Objective-C: UIView delegates not called

i´ve got a uiview in a scrollview which is in a viewcontroller and it seems that the delegates are not called because i added them to the uiview.
Is it possible to solve this problem? (I want to keep the delegates in the uiview because it seems to be cleaner code)
Maik
EDIT:
in .h file:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface RHCHuntingReportViewPageTwo : UIView <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#end
in .m file:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *pin=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
pin.image = [UIImage imageNamed:#"map_pin.png"];
pin.draggable = NO;
pin.canShowCallout = YES;
return pin;
}
I added the delegate and outlet correctly in storyboard.
edit 2:
in .m file:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
RHCAnnotation *annotation = [[RHCAnnotation alloc] init];
annotation.title = #"title";
annotation.subtitle = #"subtitle";
annotation.image = [UIImage imageNamed:#"map_tipp.png"];
annotation.coordinate = CLLocationCoordinate2DMake(57.242465, 2.533579);
mapView.region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 250, 250);
[mapView addAnnotation:annotation];
}
return self;
}

How to send array to subview and then print into label?

Working over storyboard.
I've created View Controller (storyboard) and then in middle of content added subview from xib file.
I want to add xib (UIView) like as subview into ViewController and send object with data and print that data into label but I don't know how.
Here is my code.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIView *subView;
}
#property (strong, nonatomic) IBOutlet UIView *subView; //connected over IB
#end
ViewController.m
#import "OfferViewController.h"
#import "OfferLocation.h"
#interface OfferViewController ()
#end
#implementation OfferViewController
#synthesize subView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
OfferLocation *location = [[OfferLocation alloc] initWithFrame:CGRectZero];
[self.subView addSubview:location];
}
...
#end
and here is subview:
OfferLocation.h
#import <UIKit/UIKit.h>
#interface OfferLocation : UIView{
UIView *view;
UILabel *locationLabel;// here is that label taht I want to print into
}
#property (nonatomic, retain) IBOutlet UIView *view;// connected over IB
#property (nonatomic, retain) IBOutlet UILabel *locationLabel;
#end
OfferLocation.m
#import "OfferLocation.h"
#implementation OfferLocation
#synthesize view, locationLabel;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
locationLabel.text = #"some text"; //this is not working
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"OfferLocation" owner:self options:nil];
UIView *tempView = [subviewArray objectAtIndex:0];
[self addSubview:tempView];
}
return self;
}
subView never seems to be initialized and loaded to the view or presented. Therefore you cannot see it.
Try calling:
self.view = self.subView // or subView; // or [self.view addSubview:self.subView // or subview];
or something similiar
Then declare a UILabel and initialize it with whatever text you want and add it to subview:
UILabel *label = [[UILabel alloc] initWithString:#"StackOverflow rocks!"];
[self.subView addSubview:label];
// or [self.view addSubview:label];
Differing on how you set subView.
What is this data you want to set on label's text? If it is a data type use the specifiers in the string.
%i // for int
%# // for string or object adress
%c // for char
%f // for float
etc...

EXC_BAD_ACCESS when I change moviePlayer contentURL

In few words, my application is doing that :
1) My main view (RootViewController) has a buton when I tap on it, it displays the player (PlayerViewController) :
2) In my Player, I initialize the video I want to play
-> It's working good, my movie is display
My problem :
When I go back to my main view :
And I tap again on the button, I get a *Program received signal: “EXC_BAD_ACCESS”.*
If I comment self.player.contentURL = [self movieURL]; it's working, but when I let it, iI have this problem.
I read that it's due to null pointer or memory problem but I don't understand why it's working the first time and not the second time. I release my object in dealloc method.
Thanks for your help !
Bruno.
Here is my code :
Root View Controller
RootViewController.h
#import <UIKit/UIKit.h>
#import "PlayerViewController.h"
#interface RootViewController : UIViewController {
IBOutlet UIButton * myButton;
}
#property (nonatomic,retain) IBOutlet UIButton * myButton;
-(IBAction)displayPlayer:(id)sender;
- (void) returnToRoot: (PlayerViewController *) controller;
#end
RootViewController.m
#import "RootViewController.h"
#implementation RootViewController
#synthesize myButton;
-(IBAction)displayPlayer:(id)sender
{
PlayerViewController *playerViewController = [[PlayerViewController alloc] initWithNibName:#"PlayerViewController" bundle:nil];
playerViewController.delegate = self;
playerViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController: playerViewController animated: YES];
[playerViewController release];
}
- (void) returnToRoot: (PlayerViewController *) controller
{
[self dismissModalViewControllerAnimated: YES];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
Player View Controller
PlayerViewController.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MPMoviePlayerController.h>
#protocol PlayerViewControllerDelegate;
#interface PlayerViewController : UIViewController {
UIView *viewForMovie;
MPMoviePlayerController *player;
}
#property (nonatomic, assign) id <PlayerViewControllerDelegate> delegate;
#property (nonatomic, retain) IBOutlet UIView *viewForMovie;
#property (nonatomic, retain) MPMoviePlayerController *player;
- (NSURL *)movieURL;
-(IBAction)goBackToRoot:(id)sender;
#end
#protocol PlayerViewControllerDelegate
- (void) returnToRoot: (PlayerViewController *) controller;
#end
PlayerViewController.m
#import "PlayerViewController.h"
#implementation PlayerViewController
#synthesize player;
#synthesize viewForMovie;
#synthesize delegate;
- (void)dealloc {
[super dealloc];
[player release];
[viewForMovie release];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"viewDidLoad");
self.player = [[MPMoviePlayerController alloc] init];
[self.player autorelease];
self.player.view.frame = self.viewForMovie.bounds;
self.player.view.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
[self.viewForMovie addSubview:player.view];
self.player.contentURL = [self movieURL];
[self.player play];
}
-(NSURL *)movieURL
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath =
[bundle
pathForResource:#"myVideo"
ofType:#"mp4"];
if (moviePath) {
return [NSURL fileURLWithPath:moviePath];
} else {
return nil;
}
}
-(IBAction)goBackToRoot:(id)sender{
[self.delegate returnToRoot: self];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
#end
Problem
The second time I call "displayPlayer" I had the EXC_BAD_ACCESS
I solved it !!!
I look on the MPMoviePlayerController to see what kind of variable is contentURL
(NSURL *)contentURL
It means I have also to liberate it.
I do that in my dealloc method putting a nil value:
-(void) dealloc {
[super dealloc];
self.player.contentURL = nil;
[player release];
[viewForMovie release];
}
If I comment self.player.contentURL =
[self movieURL]; it's working, but
when I let it, iI have this problem.
In that case, how is contentURL declared? Does the #property definition include copy or retain?