application wide function - iphone

I want to know Can I define any function application wide ? like say I need a function that gives me dynamic height of label. Where and how can define this function so that I can use it in any numbers of files ?
Also looking for good code of calculating the dynamic height of label based on text. I tried many codes from web sites but that made me confused.
Thanks..

You can create a global function by creating a .h/.m pair of files, but without declaring Objective-C classes in them.
Instead you can utilize C-style functions, like so:
//Foo.h
CGFloat GetHeight(UIView *view);
//Foo.m
CGFloat GetHeight(UIView *view) {
return view.frame.size.height;
}
Then you can include the header file in your pch file to have it included everywhere.
However I think it's more appropriate in many cases to use Category Methods instead. A category method "attaches" methods to a class.
//UIView+MyAdditions.h
#interface UIView (MyAddittions)
- (CGFloat)height;
#end
//UIView+MyAdditions.m
#implementation UIView (MyAdditions)
- (CGFloat)height {
return self.frame.size.height;
}
#end
Then you can just use it like [myView height] as long as the .h file is included at the top (or globally).

You can write a function either in Appdelegate or a static method in a custom NSObject class which has an argument NSString. And based on the length of NSString you can set the height and return the height from the method which can be used by the class that calls this method.

Usually I import such classes in the prefix header (this includes categories on objects I use application-wide). All imports in the prefix header are application wide. The prefix header in an iOS projects looks like this by default:
appName_Prefix.pch

How about making a category extending the interface of UILabel by a method returning the height of the label?
Alternatively (however, not that elegant) is to make a singleton class containing the static methods you need.

Related

How to Use Objective-C Categories

When you implement a category of a class in a file, will all the instances of that class be of the category by default?
I'm new to Objective-C and I'm trying to make my uneditable UITextView non-selectable. I came across this answer using a category:
https://stackoverflow.com/a/8013538/1533240
Which has the following solution:
#implementation UITextView (DisableCopyPaste)
-(BOOL) canBecomeFirstResponder
{
return NO;
}
#end
I added the snippet to my code, but it doesn't seem to be working in that I can still select the text. My declaration of the UITextView is the usual:
titleLabel = [[UITextView alloc] initWithFrame:frame];
I tried changing the declaration to [DisableCopyPaste alloc] but that didn't seem to work.. haha.
Thanks!
You misunderstand the point of categories. Categories add methods to an existing class. They must never be used to override existing methods. Doing so is undefined behavior (technically only undefined in one case, but you can't predict that case, so you must assume it applies).
If you need to override methods, you must subclass, not use categories. See the top answer to the question you linked.
When you implement a category of a class in a file, will all the
instances of that class be of the category by default?
Yes. If you create a category, the methods in that category are added to the class. For example, if you create a category on NSString that returns the checksum of a string, you can use that method on any instance of NSString.
I added the snippet to my code, but it doesn't seem to be working in that I can still select the text.
Don't use categories to override existing methods.
For one thing, it's bad form. You're effectively changing the behavior of the class in a way that the author didn't expect. For another thing, you can't count on the override to work -- the order in which categories are added to classes isn't defined, so you never know if some other category might come along and replace the method that you tried to replace. It's simply not reliable. If you need to override methods, create a subclass instead.
What you need to do is to declare category in header .h file:
such as:
#interface UITextView (DisableCopyPaste)
-(BOOL) methodName
#end
then in .m define as
#implementation UITextView (DisableCopyPaste)
-(BOOL) methodName
{
return NO;
}
#end
You can do two thing,
You can write it in a class and import that to all classes you need this functionality.
Or write these lines eachs .h and .m (respectively) you need it.

how to give two different class reference to single UIView?

I want to implement two functionalities as color filling and view magnifying in my app. But the problem is that i can't be able to implement these two functionalities at same time. Because i have to specify two difference class reference for two functionalities to my UIView, which can't be possible.
In other words, I have one view and i have given class reference as UIView (for color function). But for magnify function , i have to give class reference as MagnifyingView to that view. So, it is not possible to implement these two functionalities at same time.
So how can i give UIView and ACMagnifyingView two different class reference to single UIView at different conditions?
How can i do this ?
Thanks.
Have you tried Categories? check this tutorial http://iphone-obsessed.blogspot.com.br/2010/05/tutorial-creating-class-categories-in.html
can you provide more information? maybe if you provide more info i could help you more
EDIT
How Categories work:
you have a UIView class and you want some methods to use that you repeat a lot. what do you do: you create a category of UIView and add this method to your category, like this:
file UIView+CustomView.h
#import <UIKit/UIKit.h>
#interface UIView (CustomView)
- (void)myCustomMethod;
#end
file UIView+CustomView.m
#import "UIView+CustomView.h"
#implementation UIView (CustomView)
- (void)myCustomMethod {
// Whatever you want to do with this UIView
}
#end
now, every time you need to use the myCustomMethod you just have to import UIView+CustomView.h and all UIView objects inside that class will have access to this method.
like this:
file MainViewController.m, header:
#import "UIView+CustomView.h"
file MainViewController.m, body, inside any method:
[myView myCustomMethod];
with this in mind i believe you could add your ACMagnifyingView as a subclass and this category to use your custom view

How to set up non-instantiated classes in Objective-C (Classes with just methods)

I'm looking to create a class in Objective-C for an iOS project that is focused on fetching data. I'm familiar with how classes normally work, setter and getter methods and variables. However, for this class since it's only performing a function (returning NSMutableArrays) I don't want to have to create an instance of the class to use the methods inside the class.
Any idea how I can do this neatly and efficiently?
This is a little bit atypical in Objective-C. Since classes in Objective-C can't actually have state beyond what is available to ordinary functions (i.e. there are no class variables), a class that's never instantiated is relatively useless in most cases. The normal design patterns for this kind of functionality are:
A singleton class (if you need lots of state)
A set of functions (if you don't)
You want to make class methods?
#interface Foo : NSObject {}
+(NSMutableArray*)someClassMethod:(id)params;
#end
...
#implementation Foo
+(NSMutableArray*)someClassMethod:(id)params {
// whatever implementation
return nil;
}
#end
...
NSMutableArray* array = [Foo someClassMethod:nil];
If you're only performing functions, and you don't need to support subclassing etc, why not just write them as C functions rather than a class with methods?
If this is just a class that performs some functions, you could write it as a C function.
In your header file --
NSMutableArray *functionThatReturnsMutableArray(NSObject *param1, NSString *param2);
In your implementation file --
NSMutableArray *functionThatReturnsMutableArray(NSObject *param1, NSString *param2)
{
...
return aMutableArray;
}
And that just include the .h file in your class that needs these functions and call them directly.
NSMutableArray *anArray = functionThatReturnsMutableArray(param1, param2);
Depending on what you are doing (the same NSString operations, UIView manipulations, etc), you could implement a category (I answered a question yesterday with the explanation below -- copied for your convenience ;).
Categories extend an existing class with additional methods or with your version of existing methods. For example, let's say you want to add a method that returns the first letter of a string to NSString. To do this you would create a category as follows:
Interface - JULString.h
#import NSString
#interface NSString (JULString)
-(NSString *) firstLetter;
#end
Implementation - The typical convention is that the filename of the category is the name of the class you are extending followed by “+” and the name of the category. In this case the file would be called NSString+JULString.m
#import "NSString+JULString.h"
#implementation NSString ( JULString )
- (NSString *)firstLetter
{
return [NSString stringWithFormat:#"%C", [self characterAtIndex:1]];
}
#end
The neat thing about categories is that now they extend the behavior of ANY instance of the class you are working with. In other words, any NSString in your application will have your new methods (provided that you import the proper header file of course). Beware though, as with great power comes great responsibility. Overwriting class using a category behaviors may lead to undesired effects, so be cautious.
A couple of links you may want to check are:
Apple's guide to Objective-C
Learn Objective-C
Note:
I don't have my Mac with me so I'm writing this code basically off the top of my head (and using some code from the sites above as a reminder). So I apologize in advance for any mistakes ;)

Objective-C sub-classing basics, how to add custom property;

I am having a issue subclassing MKPolygon.
I want to add a simple int tag property but I keep getting an instance of MKPolygon instead of my custom class, so calling setTag: causes an exception.
The problem is that MKPolygons are created using a class method: polygonWithCoordinates: count: and I dont know how to turn that into an instance of my class (which includes the tag property).
How would you go about adding a tag property to MKPolygon?
Thank you!
You should both use a category (as #Seva suggests) and objc_setAssociatedObject (as #hoha suggests).
#interface MKPolygon (TagExtensions)
#property (nonatomic) int tag;
#end
#implementation MKPolygon (TagExtensions)
static char tagKey;
- (void) setTag:(int)tag {
objc_setAssociatedObject( self, &tagKey, [NSNumber numberWithInt:tag], OBJC_ASSOCIATION_RETAIN );
}
- (int) tag {
return [objc_getAssociatedObject( self, &tagKey ) intValue];
}
#end
You may also want to look at Associative References section of the ObjC Guide, in addition to the API #hoha linked to.
Looks like developers of MKPolygon didn't make it inheritance friendly. If all you want is to add some tag to this instances you can
1) keep a map (NSDictionary or CFDictionary) from MKPolygon instance addresses to tags. This solution works well if all tags are required in the same class they are set.
2) use runtime to attach tag to polygons directly - objc_setAssociatedObject (Objective-C Runtime Reference)
I'm facing the same problem. A simple solution is to just use the Title property of the MKPolygon to save what you would save in Tag. At least in my case where I don't need an object reference but a simple number, it works
SpecialPolygon *polygon = [SpecialPolygon polygonWithCoordinates:count:];
[polygon setInt: 3];
The key is that by using the SpecialPolygon factory method instead of the MKPolygon one, you'll get the desired SpecialPolygon subclass.
Are you talking about MKPolygons created by your code, or elsewhere? If the former, just override the polygonWithStuff method. If the latter, consider a category over MKPolygon. Then all MKPolygons in your project will have a tag in them.
since it looks like the authors went out of their way to prevent you from subclassing (at least, that's one possible motivation for the public interface), consider using a form of composition:
http://en.wikipedia.org/wiki/Object_composition

Can I store a custom object inside a button in Objective-C?

In winforms/C# most all UI Controls have a .Tag tag, so like myButton.Tag = myObject; where the Tag property is an 'object' type so you can basically store any type of object. How might I accomplish this in Objective-C/Cocoa? do all UI elements have something like .Tag where I can store an NSObject or something? If so, can you please provide an example. Thanks so much!
Note: I did see the integer .Tag there, but I wanted an object tag. But I guess that doesn't exist. hoo well.
As Georg said, you can associate whatever object to another object using the Objective-C runtime, so you can associate an Object to a control if you really want.
But that is not really how a standard Cocoa program works. Instead, in Cocoa, the Model-View-Controller pattern and the Delegation are the standard idiom, and associating an object directly to a widget or a view is discouraged. Even for a very small program, you would at least create a Model-Controller (called usually the application delegate in the Cocoa jargon) which manages the data, and keep the view composed of the standard controls as is. Then the view and the model-controller interact via target/action and delegation.
Apple has a very nice discussion of design patterns prevalent in Cocoa, see here.
In general, when you move from one API(Winforms/C#) to another API(Cocoa/Objective-C), there are some similarities but also some differences. It is usually worth learning how things are done in that API, rather than trying to shoehorn what you're used to into a new situation. (Just to be clear, I'm not saying which API is inherently better; this discussion goes both ways!)
So, when you are in a situation:
To do X in API A, I know the idiom P works. I now want to do X in API B. How can I directly implement idiom P in API B?
I recommend you to ask
To do X in API B, what should I do? What's the idiom in API B?
instead.
NSControl does have a tag and related setTag: method. It's not used internally so you can store whatever you like in it - it only stores NSInteger values though.
All Cocoa controls inherit from NSControl.
There is the possibility to add a tag, it's an integer if I remember correctly.
This said, I'm pretty sure one never needs this functionality in Cocoa, because it just doesn't work this way.
If you really want to add information you might be interested in the runtime's ability to associate an object with another object.
CALayers have the ability to store arbitrary keys as part of their key-value coding machinery. Example:
CALayer *myLayer = [button layer];
// Storing a value
[layer setValue:#"World!" forKey:#"hello"];
// Retrieving a value
NSLog(#"Hello %#", [layer valueForKey:#"hello"]);
That being said, storing objects against user-interface elements violates the principle of the Model-View-Controller pattern; I would advise against it--a UIView or UIControl subclass would likely be better suited.
Yep. You can add your own property to all UIControls if you like.
Just add the following to your code.
#import <objc/runtime.h>
/* -------- The Following Code adds an objectData property for every UIControl ----------- */
#interface UIControl (UIControlAdditions)
#property (nonatomic, retain) id objectData;
#end
static char const * const ObjectDataKey = "MyObjectDataKey";
#implementation UIControl (UIControlAdditions)
#dynamic objectData;
-(id)objectData {
return objc_getAssociatedObject(self,ObjectDataKey);
}
- (void)setObjectData:(id)newObjectData {
objc_setAssociatedObject(self, ObjectDataKey, newObjectData, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
/* -------- The Above Code adds an objectData property for every UIControl ----------- */
Credits to Ole Begemann: http://oleb.net/blog/2011/05/faking-ivars-in-objc-categories-with-associative-references/