-(void) alertView: ( UIAlertView *) alertView
clickedButtonAtIndex: ( NSInteger ) buttonIndex {
// do stuff
// if you want the alert to close, just call [ alertView release ]
}
Can someone explain this method? I'm used to methods that are like "-(IBAction)buttonPress:(id)sender" but this one has three. What do each of those mean?
MethodName : ReturnedType : InputType
is this right?
It's actually:
-(return type) methodName:(param1 type)param1 moreMethodName:(param2 type)param2
Etc, with as many parameters as you want. So that method is called alertView:clickedButtonAtIndex: -- it just has its parameters embedded. It's the equivalent, in a more "normal" language, of alertViewClickedButtonAtIndex(UIAlertView *alertView, NSInteger buttonIndex)
For a pretty good primer on Obj-C syntax, check out:
http://www.cocoadevcentral.com/d/learn_objectivec/
For info on that particular method, check out this document.
Objective-C methods with arguments:
A method with no arguments:
-(void)methodName;
Signature is methodName.
A method with 1 argument:
-(void)methodName:(ArgumentType *)anArgument;
Signature is methodName:.
A method with 2 arguments
-(void)methodName:(ArgumentType1 *)argument1 andArgumentType2:(ArgumentType2 *)argument2;
Signature is methodName:andArgumentType2:
So this is method is a method of 2 arguments: a UIAlertView object and an NSInteger (not an object, simply syntactic sugar for either an int or long depending on your system).
The UIAlertView is the alert view whose delegate has been set to the object of this class. It's usually set when the alert view is created.
The buttonIndex is the index of the button on the UIAlertView that the user touched. This method is called when that button is clicked. By default, nothing is done, and the alert simply vanishes.
You use this method if you want an alert with buttons to pop up, and, when the user clicks on one of the buttons, have the class that invoked the alert do something (possibly different things depending on which button was clicked).
It is a delegate protocol method implementation.
You can find some details about that pattern at iPhone Dev Central.
The class that implements that method acts as a delegate of an UIAlertView.
This way you can customize the behavior of an instance of a class without subclassing.
Its a method with two input arguments.
Similar to:
void someMethod(int i, int j){}
It always a good idea to pick up a book and get the basics right instead of learning in bit and pieces. Trust me :)
When writing my objective-C I prefer to format the method as follows as I think it makes the separation of return type and parameters clearer:
-(void) // return type
alertView:(UIAlertView *) alertView // param1
clickedButtonAtIndex:(NSInteger) buttonIndex // param2
{
// do stuff
// if you want the alert to close, just call [ alertView release ]
}
Related
I have a controller class in which i want to write the test case for the code which executed on the button click .In my testClass.m file i have following code from which i want to call the button from testClass.m . will this code work??
-(void)testcheckTheArrayForNull
{
viewController.temp=#"c";
viewController.buttonCount=1;
[viewController goButton:self];
STAssertNotNil(viewController.setUpArray,#"set up Array is not nil");
}
By this code will my control transfer to goButton???
I would say this could work, but you didn't provide code for goButton, setUpArray and I have no idea what temp or buttonCount do - so just guessing.
I have a button that's created via a NIB file. I've derived a class from UIButton, replaced the class name in the NIB file.
Now my button displays with no background. The text is there, the text font and color are right, and it reacts to taps as expected, but it's as if the background is transparent. In the NIB, it's not transparent - I did not change any of the properties other than the class name.
The subclass is trivial - it overrides nothing (for now). Please, what am I doing wrong?
The reason I need a subclass of UIButton is because I want to be able, under certain circumstances, to drag text from the button to elsewhere. If there's an alternative way to handle drag and drop in a UIKit provided view, I'm willing to hear.
Check the states of the button in your NIB file.
It's possible that you are looking at the "active" state or something rather than the more common UICONTROLSTATENORMAL.
Honestly not sure what's wrong with the subclass, but the 'Net (including SO) is full of cautionary tales about subclassing UIButton, and how you shouldn't.
So I'll go with method swizzling on the four touch processing methods. The following function replaces the provided method of a button with my implementation (taken from the MyButton class), while saving the old one in the system button class under a different selector:
//Does NOT look at superclasses
static bool MethodInClass(Class c, SEL sel)
{
unsigned n,i ;
Method *m = class_copyMethodList(c, &n);
for(i=0;i<n;i++)
{
if(sel_isEqual(method_getName(m[i]), sel))
return true;
}
return false;
}
static void MountMethod(Class &buc, SEL SrcSel, SEL SaveSlotSel)
{
IMP OldImp = [buc instanceMethodForSelector:SrcSel];
IMP NewImp = [[MyButton class] instanceMethodForSelector:SrcSel];
if(OldImp && NewImp)
{
//Save the old implementation. Might conflict if the technique is used
//independently on many classes in the same hierarchy
Method SaveMe = class_getInstanceMethod(buc, SaveSlotSel);
if(SaveMe == NULL)
class_addMethod(buc, SaveSlotSel, OldImp, "v#:##");
else
method_setImplementation(SaveMe, OldImp);
//Note: the method's original implemenation might've been in the base class
if(MethodInClass(buc, SrcSel))
{
Method SrcMe = class_getInstanceMethod(buc, SrcSel);
if(SrcMe)
method_setImplementation(SrcMe, NewImp);
}
else //Add an override in the current class
class_addMethod(buc, SrcSel, NewImp, "v#:##");
}
}
And call it so:
Class buc = [bu class];
MountMethod(buc, #selector(touchesBegan:withEvent:), #selector(MyButton_SavedTouchesBegan:withEvent:));
MountMethod(buc, #selector(touchesCancelled:withEvent:), #selector(MyButton_SavedTouchesCancelled:withEvent:));
MountMethod(buc, #selector(touchesEnded:withEvent:), #selector(MyButton_SavedTouchesEnded:withEvent:));
MountMethod(buc, #selector(touchesMoved:withEvent:), #selector(MyButton_SavedTouchesMoved:withEvent:));
This has the disadvantage of mounting the said methods for all buttons, not just for the ones desired. In the MyButton's implementation, there's an additional check if the drag-drop functionality is to be enabled for this particular button. For that I've used associated objects.
One fine point is that touchesXXX methods are implemented in the UIControl class, not in the UIButton. So my first, naive implementation of swizzling would replace the method in UIControl instead of the button class. The current implementation does not assume either way. Also, it makes no assumptions about the run-time class of buttons. Could be UIButton, could be anything (and in real iOS, it's UIRoundedRectButton).
This might be a ridiculous question but I can't find it asked yet here already.
Have a protocol delegate method defined:
- (void)myAddViewController:(MyAddViewController *)myAddViewController
loadGPS:(BOOL)gps loadCamera:(BOOL)camera;
which basically is to determine whether the GPS system is to be loaded or the camera should be loaded.
I call this method via:
[self.delegate myAddViewController:self loadGPS:YES loadCamera:NO];
// or alternatively
[self.delegate myAddViewController:self loadGPS:NO loadCamera:YES];
Inside my implemented method in the delegate we have:
- (void)myAddViewController:(MyAddViewController *)myAddViewController loadGPS:(BOOL)gps loadCamera:(BOOL)camera {
.... .... ...
if (gps) {
......
}
if (camera) {
// camera is ALWAYS nil and never seems to be set?!
.....
}
So why when I call the delegate method with Camera: YES is the camera var always nil? It seems like it is never recognizing my second var yet it doesn't mind compiling? :)
It seems like a waste to pass in two mutually exclusive boolean values to a method.
Perhaps you'd be better with two delegate methods:
[self.delegate myAddGPSViewController:self];
// or alternatively
[self.delegate myAddCameraViewController:self];
because when you're firing the delegate methods, you'll already know whether you want GPS or Camera anyway.
It might have,
declaring 'camera' variable again,
can you paste your method
- (void)myAddViewController:(MyAddViewController *)myAddViewController loadGPS:(BOOL)gps loadCamera:(BOOL)camera {
\here?
I'm looking for a non-hackish solution for this, so basically -inputView. The part that I'm not sure about is how to make it look like the regular keyboards, from the background to the keys. I realize that I could photoshop an apple keyboard, but this seems like it is a little hackish, especially if apple (probably not but still possible) decides to change the look of their keyboards. I know Numbers has done an excellent job of making extra keyboards that look like the standard system ones, and I would like to do it like those (although obviously they have access to the same resources that made the system keyboards, including possible private frameworks, etc.)
I used the following:
tenDigitKeyboard.m
-(IBAction)pressedKey:(UIButton *)sender
{
[delegate pressedKey:sender.tag];
}
where delegate is defined as `id delegate;
then in the delegate i do...
-(void)pressedKey:(NSInteger)key
{
NSString * bufferString = model.string;
if (key == -1) {//delete
model.string = [bufferString substringWithRange:NSMakeRange(0, [bufferString length]-1)];
}else{
//will need to change the following to lookup key value based on a lookup of the button.tag
model.string = [bufferString stringByAppendingFormat:#"%i",key];
}
[self update];//updates the view
}
I got the keyboard button artwork from: http://www.teehanlax.com/blog/iphone-gui-psd-v4/
Create a view controller and xib. The xib should have 1-9,0 and delete buttons mapped to IBOutlets in your controller. Store and retain the return value string as a property. You can add decimals, etc. if you wish. In the header, store an edition block closure with a property (or alternatively create a delegate or use notification).
#property (copy) void(^valueChangedBlock)(NSString* string);
On touch up, each button sends an event to a method like this:
- (IBAction) pressKey:(id)sender
{
NSString *toAppend;
// Instead of this switch you can store the values in a dictionary mapped by sender.
switch(sender)
{
case oneButton: toAppend=#"1"; break;
case twoButton: toAppend=#"2"; break;
...
}
returnValue = [returnValue appendString:toAppend];
valueChanged(returnValue);
}
Obviously the delete key should remove a character from the end of the string instead of appending. Other than creating the controller and adding this view as the inputView, you should add the valueChangedBlock and set it to update the text field. You may want to put a clear custom button over the text field set to make the field first responder so it doesn't appear as if the user can edit at any point in the string.
I have written a subclass of UIControl that tracks a number of gestures that are of interest to me. In the documentation for the UIControlEvents enumeration, it says that there is a range of event numbers called UIControlEventApplicationReserved that is "available for application use." Does this mean that I am free to use this range of numbers for my own custom events?
If so, can someone please tell me how to fire events? The obvious way I can think of to do it is this:
enum {
...
MyCustomEvent = 65,
...
};
...
UIEvent* customEvent;
...
for (id target in [self allTargets])
{
for (NSString* action in [self actionsForTarget:target forControlEvent:MyCustomEvent])
{
[self sendAction:NSSelectorFromString(action) to:target forEvent:customEvent];
}
}
Would that even work?
Okay, this is an old subject but I'm going to add my answer to this. I can't really tell for sure whether you can use this mask for your own application even though I suspect it.
But I can tell you for sure how to use it. For starter this value masks the bits at position 24, 25, 26 and 27. You should write an enum of your own that uses this bits only, for example:
enum {
MyPrimaryActionEvent = 1 << 24,
MySecondaryActionEvent = 1 << 25,
};
Once that is done you can register for these actions:
[myButton addTarget:self action:#selector(someAction:) forControlEvents: MyPrimaryActionEvent];
Every time the action MyPrimaryActionEvent is triggered, self will receive the message someAction:. Now how to trigger that action is up to the button itself. In your own UIControl subclass you can trigger the change as follow:
[self sendActionsForControlEvents:MyPrimaryActionEvent];
This will send all the actions to all the targets registered for MyPrimaryActionEvent event. And you're done.