Clearing "may not respond" warnings for UIView and UIViewController - iphone

In an iPad app, I'm using a custom subclass of UIView with UIViewController. Here's the view header:
#interface pdfView : UIView {
CGPDFDocumentRef doc;
}
-(void)setDoc:(CGPDFDocumentRef)newDoc;
#end
And here's the controller header:
#interface iPadPDFTestViewController : UIViewController {
CGPDFDocumentRef doc;
}
- (void)loadPDF;
#end
Part of the controller implementation:
- (void)viewDidLoad {
[super viewDidLoad];
[self loadPDF];
[self.view setDoc:doc];
}
In Interface Builder, I've set the view object to use the class pdfView.
At compilation, [self.view setDoc:doc]; gives the warning "'UIView' may not respond to '--setDoc'." I'm guessing that this warning appears because the compiler thinks it's looking at UIView (which does not implement the setDoc method) instead of pdfView. But why does it think that? And how can I tell it what class it's really looking at, so as to clear the warning?

The compiler only knows what the code defines, and a UIViewController defines it's view property as a UIView, which is why you're seeing warnings.
You can avoid warnings by casting the view to your PDFView: (PDFView *)self.view;
To make this simpler implement a basic getter method
- (PDFView *)view {
return (PDFView *)self.view;
}
Also, just as a side note, you should really name your classes so they start with atleast one uppercase char, and ideally a prefix (i.e. PDFView, ideally MYPDFView (where MY is a custom prefix)).

Related

viewDidLoad in UITextView subclass?

Cocoa/Objective-C noob here.
I'm working on a simple app to learn some more about iOS development, and am struggling to see how my subclass of UITextView has it's viewDidLoad method called.
I am subclassing UITextView to CMTextView.
Using storyboard, I have a CMTextView in the window.
In CMTextView.m, I have the following:
#import "CMTextView.h"
#interface UITextView ()
- (id)styleString;
#end
#implementation CMTextView
- (id)styleString {
return [[super styleString] stringByAppendingString:#"; line-height: 1.1em"];
}
- (void)viewDidLoad {
NSLog(#"LOADED!"); // not doing anything...
}
I'm not doing anything fancy to add this as a subview of my window, but I thought the storyboard did that for me?
Does anyone have any advice?
The above answers are correct if you manually initialize the UITextView. If loading them from a nib, you need to override the -awakeFromNib method.
-(void)awakeFromNib
{
[super awakeFromNib]; // Don't forget to call super
//Do more intitialization here
}
If you want to handle the resizing also override the -layoutSubviews method
viewDidLoad is a method in UIViewController not UIView/UITextView
if you want to do any initialize then put it in initWithFrame:
viewDidLoad is a UIViewController method (see here).
UIKit ensures that viewDidLoad is called at appropriate times when you instantiate a view controller's view, but it has no role to play in a UIView like UITextView.
Usually, you prepare your view at initWithFrame time.
A view can never have the method viewDidLoad.
Some methods are tethered only to the viewcontroller and viewDidLoad is one of them.
The method constructors for views would be
-(id)init;
-(id)initWithFrame;

What is the meaning of this type cast?

SomeView.h
#interface SomeView : UIScrollView <UIScrollViewDelegate>
- (void)setPage:(int)page;
#end
SomeViewController.h
#interface SomeViewController : UIViewController
#end
SomeViewController.m
#import "SomeView.h"
#import "SomeViewController.h"
- (void)viewDidLoad
{
[super viewDidLoad];
[(SomeView *)self.view setPage:1];
}
What is the meaning of (SomeView *)self.view?
In the real code, it seems doing the magic of inheriting the functionalities from SomeView to self.view ...
Reference: The original source code.
First of all your question doesn't apply out of the context of the original source.
Controller's view there is set explicitly by IB in the storyboard. That means that self.view is set to a custom SomeView class, but the compiler doesn't know that! That's why it is casted.
So it looks like a plain UIView to the compiler but in reality is a SomeView that needs access to its methods (so we tell the compiler 'don't worry this is a SomeView, go on and treat it like this'). I hope that this makes sense.
PS. You'll have to download the actual project to see what is really going on since the answer is to be found in the storyboard
since self.view is a UIView you will need to cast it to your SomeView
So,
SomeView *someView = self.view; will give you a warning
So you cast it
SomeView *someView = (SomeView *)self.view;
Its not magic, its just casts the UIView to SomeView, self.view is defined as UIView
But its an instance of SomeView class, so inorder to use SomeView functions you will need to cast it
This is actually a typecasting from self.view to SomeView to access functionality of SomeView.
As your view controller already loads SomeView, but self.view will return an instance of UIView, that's why it is needed to typecast this to avoid warnings.
[(SomeView *)self.view setPage:1];
that means your self.view is type of SomeveView
SomeView *someVw = [[SomeView alloc]init];
self.view = someVw;

How to correctly integrate InAppSettingsKit with Storyboard in a TabBar?

I have been trying for a while now, but I can't figure out how to integrate InAppSettingsKit in an App, that uses Storyboard and a TabBar.
I've got my tab bar defined in a Storyboard, now I want one tab to have this InAppSettingsKit as the root view. Is this possible after all?
Thanks everyone.
Well, after trying various things, I figured out, that my problem actually was, that I put all the IASK-stuff into a static library (and I had no Settings Bundle). After moving all the code and nibs to the same project as the MainStoryboard, it worked by adding a TableView Controller to my storyboard and settings its custom class to IASKAppSettingsViewController.
Alternatively, if you want button handlers and other custom code, do following:
Create a class derived from UITableViewController
Modify the header file to derive from IASKAppSettingsViewController
<IASKSettingsDelegate> Remove all methods but the initWithCoder and the
settingsViewControllerDidEnd protocol (or make calls to super). This
is so that the default UITableVC code doesn't override IASK
functionality. Be sure to stick self.delegate = self; into the
initWithCoder to get the buttons to work.
//SettingsViewController.h
#import "IASKAppSettingsViewController.h"
#interface SettingsViewController : IASKAppSettingsViewController <IASKSettingsDelegate>
#end
//SettingsViewController.m
// ...
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delegate = self;
}
return self;
}
#pragma mark -
#pragma mark IASKAppSettingsViewControllerDelegate protocol
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Set custom class of the table view in storyboard to
your class

UIViewController auto rotate not working

I have found quite a lot on this subject but I just can't figure it out. Any help would be massively appreciated!
I have an app set up with a UITabBarController. Within one of the tabs, I am showing a UITableView which is using a UINavigationController to allow for hierarchy. All the tables rotate just fine when the orientation is changed, until I get to what is effectively the final view in the hierarchy.
The final view is not a UITableView, just a basic UIView. But I can not get this page to rotate successfully! I have remade the view from with the absolute basics required and it still doesn't want to work! The code is below but it is currently pretty much a standard template with nothing in it now.
Also, I am not using InterfaceBuilder, and shouldAutorotateToInterfaceOrientation is on all views. This is the only one I am having problems with.
SomeView.h
#import <UIKit/UIKit.h>
#interface SomeView : UIViewController
{
NSString *someID;
NSString *someName;
}
#property(nonatomic,retain) NSString *someID;
#property(nonatomic,retain) NSString *someName;
#end
SomeView.m
#import "SomeView.h"
#import "AppDelegate.h"
#implementation SomeView
#synthesize someID, someName;
-(void)loadView
{
}
-(void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewDidUnload
{
[super viewDidUnload];
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
NSLog(#"willAnimateRotationToInterfaceOrientation");
}
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)dealloc
{
[super dealloc];
}
#end
UPDATE 10th Nov 2011
I'm still having this issue, however looking through documents and bits this seems to be my problem (http://developer.apple.com/library/ios/#qa/qa1688/_index.html)
The view controller's UIView property is embedded inside UIWindow but alongside an additional view controller.
You may find a situation where shouldAutorotateToInterfaceOrientation is called once at startup for a given view controller but is never called again when the device is rotated. Because view controllers are tightly bound to the views they manage, they are also part of the responder chain used to handle events. View controllers are themselves descendants of the UIResponder class and are inserted into the responder chain between the managed view and its superview. So it is common practice to have one primary view controller in your application as part of the responder chain. You would typically add one primary view controller such as a UINavigationController, UITabBarController or a generic UIViewController to your UIWindow. For example, this is done by calling:
[myWindow addSubview:primaryViewController.view];
If you add an additional view controller's UIView property to UIWindow (at the same level as your primary view controller) via the following:
[myWindow addSubview:anotherController.view];
this additional view controller will not receive rotation events and will never rotate. Only the first view controller added to UIWindow will rotate.
My UITabBarController stopped to autorotate, when I added a new navigationController to it with a tableViewController and didn't notice, that my custom navigation controller's shouldAutorotateToInterfaceOrientation returns YES only for one orientation. The solution is to check shouldAutorotateToInterfaceOrientation function in each Controller inside TabBarController.
May be it will help to somebody.
And I have figured it out...
I was looking at the code which pushes the UIViewController onto the stack and I had not fully initied the UIViewController.

iphone sdk - calling a method of view's superview's viewcontroller

hello how can i call in the current view, a method implemented in the viewcontroller of the current view's superview?
can you help me please.
thanx
Typically this is done through delegates.
Have your view interface define a protocol and a reference to some delegate. Then have your parent viewcontroller implement this protocol.
Then the parent would do this:
someView.fooDelegate = self;
then the view would do something like this:
if(self.fooDelegate != nil) {
if([fooDelegate respondsToSelector:...]) {
[fooDelegate performSelector:...];
}
}
This is not compiled, but I think you get the gist.
You can add a function -(void)initWithView:(EchiquierDisplayView *)aSuperview or something like that, define a reference in your
#interface pieceDraggableImageView : UIImageView {
CGPoint startLocation;
CGPoint startLocationInView;
EchiquierDisplayView *theSuperview;
}
#property (nonatomic, retain) EchiquierDisplayView *theSuperview;
-(void)correctDestinationPosition;
-(void)initWithView:(EchiquierDisplayView *)aSuperview;
...
-(void)askSuperview;
#end
#implementation pieceDraggableImageView
...
-(void)initWithView:(EchiquierDisplayView *)aSuperview
{
theSuperview = aSuperview;
}
...
-(void) correctDestinationPosition
{
[theSuperview correctIt];
}
Now be sure to implement the function correctIt in your superview.
Hopefully i understood your question right...
UIViews have no knowledge of their view controllers. You will need to create a custom UIView subclass that maintains a reference to one (or potentially more than one) view controller, although doing so introduces further coupling between UIView and UIViewController.
You should consider implementing the method in the superview's or view's class rather than implementing it in a view controller.
Here is another way:
SuperviewsViewController *controller = self.superview.nextResponder;
if (controller && [controller isKindOfClass:[SuperviewsViewController class]])
{
[controller method];
}
It should work in most cases.
Apple's UIResponder Reference