Global Functions Objective C - iphone

I am trying to write a global function however keep getting the error "No visible interface...." when i try and call it.
Popover.h
#import <Foundation/Foundation.h>
#interface Popover : NSObject{}
- (void)PopoverPlay;
#end
Popover.m
#import "Popover.h"
#implementation Popover
- (void)PopoverPlay{
NSLog(#"I Work");
}
#end
In View.m i am adding the import "Popover.h" but i cant get rid of the error message when i try and run.
#import "View.h"
#import <QuartzCore/QuartzCore.h>
#import "Popover.h"
#interface View ()
{
}
#end
#implementation View
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad{
[super viewDidLoad];
}
- (IBAction)ButtonPress {
[self PopoverPlay];
}
Any ideas
Thanks

The code you've shown is the declaration and definition of a class that contains a single instance method. To use it, you'll need to allocate an instance of Popover with code that looks something like:
#import "Popover.h"
//...
Popover *pop = [[Popover alloc] init];
[pop PopoverPlay];
//...
When people talk about "global functions" they don't usually mean instance methods (or even class methods), so I doubt this is quite what you're after. Perhaps you mean an actual function that you can call from other parts of your code? You'd do that the same way you do in C:
void foo(void);
void foo(void)
{
NSLog(#"This works");
}
If you add the prototype (first line) to a header file, you can use the function anywhere in any file that includes that header.
Update:
- (IBAction)ButtonPress {
[self PopoverPlay];
}
The problem here is that you're sending -PopoverPlay to self, but self in this case represents an instance of View. You need to send -PopoverPlay to an instance of the class that implements it, which is Popover. See my example above. (BTW, your interface and implementation don't match: one is PupilView and the other is View.)

To call the method you wrote, you need to do something like:
Popover *myPopover = [[Popover alloc] init];
[myPopover PopoverPlay];
What you have is an instance method. Because your method doesn't rely on any instance variables, you could make it a class method by changing the - to +:
+ (void)PopoverPlay;
and
+ (void)PopoverPlay{
Then you don't need to initialize a new Popover; you can just call:
[Popover PopoverPlay];

Related

event delegation

I have two uiviewcontroller: MainViewController and SecondaryViewControlle. In MainViewController I do:
[self.view addSubView:SecondaryViewControlle.view];
The SecondaryViewController is a button by pressing the function to be performed by a MainViewController. How to do?
You'd start by defining a protocol in your SecondViewControlle.h file, something like:
#protocol SecondViewControlleDelegate
- (void) doSomething
#end
You would also need to add a "delegate" ivar to your SecondViewControlle .h file. It would be the delegate line:
#interface SecondViewControlle : UIViewController
...
...
...
#property (nonatomic, assign) id delegate; // all you need to do is add this line inside your interface declarations
...
...
...
#end
Then, when you create / instantiate your SecondaryViewControlle from your MainViewController, make certain to add the MainViewController as the delegate like so:
SecondaryViewControlle.delegate = self;
[self.view addSubView:SecondaryViewControlle.view];
Now the "delegate" of your SecondaryViewControlle view controller points back to your MainViewController.
And when the button is pressed, you can simply do something like:
- (IBAction) buttonIsPressed: (id) sender
{
[delegate doSomething];
}
Now, I need to give you some advice here.
1 ) DO NOT use the class names as object names. Instead of having an object named "SecondViewControlle", name it something different (and start it with a lower case, which is Objective-C convention), something like "moreDetailVC".
2) I've told you how to do this with a delegate pattern, but this may not be the most appropriate way to do whatever it is that you're trying to do. After all, the MainViewController object (which should be renamed mainVC to differentiate the object from the class) is not on screen or visible so maybe there's a better place to put the functionality?
Option A
It's quicker, and easier, but lacks the maintainability, since there is no contract stating that SecondaryViewController needs to bother calling anything, and self.parentViewController could be any UIViewController.
Option B
The delegate pattern; this is my preference, it's obvious what's happening, what's required, and there's a nice solid contract that states, if you want to initialise me, give me a delegate.
Option C
If SecondaryViewController has to notify multiple objects, it would be quick to use the NSNotificationCenter, but as with Option A, there's no contract, should you need to notify many objects, you would need to remember to listen for notifications on those objects - since this is not the question, I won't go into detail, it's just here for the information
Option A
Within MainViewController.m, do something like so:
SecondaryViewController *viewcontroller = [[SecondaryViewController alloc] initWithNibName:#"SecondaryView" bundle:nil];
[self addChildViewController:viewcontroller];
//set viewcontroller.view frame
[self.view addSubview:viewcontroller.view];
[viewcontroller didMoveToParentViewController:self];
Inside MainViewController.h
-(void) performButtonClickAction;
Inside MainViewController.m:
-(void) performButtonClickAction {
//Do something constructive
}
and then inside the SecondaryViewController.m:
-(IBAction) buttonPressed:(id) sender {
[self.parentViewController performButtonClickAction];
}
Option B
Inside SecondaryViewController.h
#protocol SecondaryViewControllerDelegate <NSObject>
-(void) eventAFromViewController:(UIViewController *) viewController;
-(void) eventBFromViewController:(UIViewController *) viewController;
#end
#interface SecondaryViewController : UIViewController {
id<SecondaryViewControllerDelegate> delegate;
}
#property (assign, nonatomic) id<SecondaryViewControllerDelegate> delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<SecondaryViewControllerDelegate>) theDelegate;
#end
Inside SecondaryViewController.m
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<SecondaryViewControllerDelegate>) theDelegate
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.delegate = theDelegate;
}
return self;
}
-(IBAction) buttonPressed:(id) sender {
if( self.delegate != nil ) {
[_delegate eventAFromViewController:self];
}
else {
//No delegate
}
}

Protocols and accessing another class's methods

So I'm fairly new to objective-c and am trying to wrap my head around protocols. I'll use an example to illustrate my question.
Suppose I have a "Calculate" class that performs various methods. I also have "Class1" and "Class2" that perform the same methods in "Calculate".
Now from my understanding I can use protocols to access methods from "Calculate" without the need for inheritance (Therefore saving the need to replicate the same code in Class1 and Class2).
My understanding is also that I have to implement the protocols in Class1 and Class2, therefore I'd have to type out those methods anyways. So whats the point of protocols?
I want to use the methods of "Calculate" without making it a superclass of Class1 and Class2. So I started exploring protocols, I've read the documentation but I still don't understand how this is being achieved. If some one can explain protocols in layman's it would be appreciated.
Inheritance would allow you to not have to duplicate code. Protocols (what other programming languages call interfaces) implement a Can-Do structure of OOP. Meaning when a class implements a protocol, that class is saying that it can do a certain set of methods. It is still up to that class to implement the method as they see fit.
Here is a developer reference from Apple:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html
A protocol is a set of method declarations. It's main purpose is to allow flexible relationships between classes.
Let's say I want a variety of classes to send out logging messages but I don't want them responsible for knowing what happens to the messages after they're sent. I create a Logger protocol that is then implemented by a ConsoleWriter class and a DiskWriter class. The class wanting to send the message doesn't know or care which one it's talking to; it just talks to something it knows as id<Logger>.
I don't know with what types of languages you have experience. But an Object-C protocol is very much like an Interface in .NET. It's purpose is to define a contract (interface, footprint, etc.) so that the actual "Type" of the object is not necessary to be known, but just what it can do.
That being said you can define a protocol "MyProtocol.h" that has a few properties and methods. Then you can implement this protocol on a class. You will not need to add the members of the protocol in the header of the class, but simply need to write the concrete implementation in the implementation.
What this does is allow you to reference object by their defined interface and not their type. So you can use the id type instead of the actual class type.
Hope this helps.
Protocols are almost like a portable header file. They describe methods that can or should be implemented by any class that conforms to the protocol. This is different from inheritance where a subclass automatically implements the methods of its super class and those methods can optionally be overridden on a subclass by subclass basis.
I suspect that you have some OOP background so I won't go too much into subclassing other than to say a subclass is very often a specialized or more specific version of the super class. In other words: every subclass is a kind of its superclass, but every superclass is not necessarily a type of subclass.
Protocols in ObjC are often used in delegate patterns where ClassA needs to know that ClassB can perform some kind of action. Here's an example:
// ClassA.h
#import "ClassB.h"
#interface ClassA <ClassBProtocol>
// Some variables
#end
// ClassA.m
#implementation ClassA
- (id)init {
if ( (self = [super init]) ) {
ClassB *classB = [[ClassB alloc] init]; // Create an instance of ClassB
classB.delegate = self; // Set ourself as the delegate which means we want ClassB to tell us what to do
}
return self;
}
// Introduced by ClassBProtocol
- (void)doSomethingCoolWithString:(NSString *)string {
// Do something here, it's up to ClassA what to do
}
#end
// ClassB.h
#protocol ClassBProtocol <NSObject>
- (void)doSomethingCoolWithString:(NSString *)string;
#end
#interface ClassB
#property (nonatomic, weak) id <ClassBProtocol>delegate;
// Some variables
#end
//ClassB.m
#implementation ClassB
#synthesize delegate;
- (id)init {
if ( (self = [super init]) ) {
if (delegate && [delegate respondsToSelector:#selector(doSomethingCoolWithString:)]) {
[delegate doSomethingCoolWithString:#"A String"];
}
}
return self;
}
#end
Below Example for Simple Protocol & Property:
---> ViewController.h File
#import <UIKit/UIKit.h>
#import "MyVC.h"
#interface ViewController : UIViewController<MyVCProtocol>
{
IBOutlet UILabel *label;
IBOutlet UIButton *btnPush;
MyVC *vc;
}
-(IBAction)Buttonclicked;
#end
---> ViewController.m File
#import "ViewController.h"
#implementation ViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(IBAction)Buttonclicked
{
vc = [[MyVC alloc]initWithNibName:#"MyVC" bundle:nil];
vc.delegate=self;
[self.navigationController pushViewController:vc animated:YES];
}
-(void)GetText:(NSString *)text
{
label.textAlignment=UITextAlignmentCenter;
label.text=text;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
---> MyVC.h File
#import <UIKit/UIKit.h>
#protocol MyVCProtocol <NSObject>
-(void)GetText:(NSString *)text;
#end
#interface MyVC : UIViewController
{
IBOutlet UITextField *m_TextField;
IBOutlet UIButton *m_Button;
id <MyVCProtocol> delegate;
}
#property(nonatomic, retain)id <MyVCProtocol> delegate;
-(IBAction)ButtonClicked;
#end
---> MyVC.m File
#import "MyVC.h"
#implementation MyVC
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(IBAction)ButtonClicked
{
[delegate GetText:m_TextField.text];
[self.navigationController popViewControllerAnimated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end

Subclassing MKOVerlay View- canDrawMapRect not called

I am attempting to subclass MKOverlayView to create a custom overlay. I understand that in order to do this, one must override the following two methods
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context;
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale;
My question arrises from the latter method. For some reason, when I override it in my MKOverlayView subclass, it does not get called. According to documentation, it should be called before tiles are rendered and if it returns YES, then drawMapRect is called. I was hoping that someone could look at the following code and see if they can figure out why this method is not being called. Is it meant to be enabled/called manually somewhere?
Interestingly enough, drawMapRect does get called, it's only canDrawMapRect that does not. Am I misinterpreting the functionality of canDrawMapRect or is something wrong in my code?
HeatMapOverlay.h
#import <MapKit/MapKit.h>
#import <Foundation/Foundation.h>
#interface HeatMapOverlayView : MKOverlayView{
...variables...
}
#end
HeatMapOverlay.m
#import "HeatMapOverlayView.h"
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/QuartzCore.h>
#implementation HeatMapOverlayView
#synthesize points, heat, QualityIndex;
- (id)initWithOverlay:(id<MKOverlay>)overlay {
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale{
...complete check...
return NO;
}
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext (CGContextRef)context{
...draw overlay...
}
Thank you!
Try changing this line:
self = [super init];
to this to use the proper initializer for an MKOverlayView:
self = [super initWithOverlay:overlay];

Initialization of controls in custom uiview

I've created a custom uiview in IB and set the class for it.
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface myView : UIControl {
IBOutlet UITextView *textView;
}
#end
#import "myView.h"
#implementation myView
- (void)commonInit
{
[textView setText:#"lajsdfklasdfjl"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
{
[self commonInit];
}
return self;
}
-(id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
[self commonInit];
}
return self;
}
#end
I put a textview with text on this view in IB and linked it to IBOutlet IUTextView *textView.
When I drag this custom view on my UIViewController (from classes tab in IB's library) the view is empty.
- (id)initWithCoder:(NSCoder *)aDecoder is calling but the textView is null.
What is wrong? Thanks
As far as I remember, the hierarchy is not properly set up in init, as the properties can only be set after init has finished.
You want to use
-(void)awakeFromNib
{
[super awakeFromNib];
[self commonInit];
}
instead and remove the initWithCoder: thing altogether.
As a side note, you should let your class names begin with upper case letters.
There should be nothing stopping you from using a custom UIViewController which has methods built in for initializing or deallocating the UIView that it contains. I found this to be a simpler solution. For example, you can set up your custom UIViewController using a nib with a UIView, then make sure your File's Owner is set to the custom class.
You can then remove the following 3 instance methods
- (void)commonInit
- (id)initWithCoder:(NSCoder *)aDecoder
- (id)initWithFrame:(CGRect)frame
and in your custom UIViewController class use initWithNibName as below
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.view.frame = CGRectMake(0, 44, self.view.frame.size.width, self.view.frame.size.height);
}
return self;
}
This initWithNibName instance method will be called automatically when you alloc your custom UIViewController class like this
CustomUIViewController *vc = [[CustomUIViewController alloc] init];
Put a break point in initWithNibName and you will see it called.

Invoke methods declared in protocol from the class implementation

I've created a protocol named RecDelegate that's consisted of a method "- (void) doSmtng".
The protocol is defined in rec.h just before the rec interface declaration.
When I create a new application and adopt the RecDelegate to the new appDelegate, I can implement my own doSmtng, as needed to be.
What I don't understand is how can I invoke the doSmtng method from the rec.m (implementation of the class in which the protocol is defined...) - Meaning, how can I "Fire" the doSmtng in such a way that the new appDelegate's implementation will be triggered.
Hope what I said is relatively clear ... ;)
Thanks,
Guy.
There are two controllers below showing how to trigger an event from one to the other.
Wherever there is a comment "//HERE", it indicates there is delegation-related code.
SENDER OF DELEGATE
SecondViewController.h
#import <UIKit/UIKit.h>
#protocol SecondDelegate <NSObject> // HERE
#optional
-(void)MessageReceived:(NSString *)msg;
#end
#interface SecondViewController : UIViewController {
id<SecondDelegate> secondDelegate; // HERE
}
#property (assign) id<SecondDelegate> secondDelegate; // HERE
-(IBAction)trigger:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
#synthesize secondDelegate; // HERE
-(IBAction)trigger:(id)sender {
if (self.secondDelegate != NULL && [self.secondDelegate respondsToSelector:#selector(MessageReceived:)]) { // HERE
[secondDelegate MessageReceived:#"my message"];
}
}
RECEIVER OF DELEGATE
FirstViewController.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h" // HERE
#interface FirstViewController : UINavigationController <SecondDelegate> // HERE
-(void)MessageReceived:(NSString*)msg; // HERE
#end
FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
#implementation FirstViewController
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
[self.view setBackgroundColor:[UIColor greenColor]];
SecondViewController *second = [[SecondViewController alloc] init];
[self pushViewController:second animated:YES];
second.secondDelegate = self; // HERE
[second release];
}
return self;
}
-(void)MessageReceived:(NSString *)msg { // HERE
int y = 0; // HERE IT IS !
}
You need to tell your Rec object that it should treat your AppDelegate as its delegate:
[rec setDelegate:appDelegate];
This could be done via Interface Builder or just after the Rec object is created.
Then, when the Rec object sends the delegate message to its delegate, the receiver will be your AppDelegate instance:
[[self delegate] doSmtng];
If the message the Rec object is sending to its delegate were an optional protocol message, it would instead be sent like this:
if ([[self delegate] respondsToSelector:#selector(optionalProtocolMethod)]) {
[[self delegate] optionalProtocolMethod];
}
The delegate will usually be declared something like:
#property(assign, nonatomic) id<RecDelegate> delegate;
Because it is not retained, in -dealloc, the Rec object only needs to nil it out, not release it:
delegate = nil;
Another way to do something like that is using NSNotificationCenter
in your RecDelegate init method add:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doSmtng) name:#"someNotification" object:nil];
and in any another place / any class call
[[NSNotificationCenter defaultCenter] postNotificationName:#"someNotification" object:nil];