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?
Related
I have tried MKTikcerView , DMScrollingTicker and also made a Custom TickerView but , I am not satisfied with that all. All of them when comes to end string displays blank space.They are have not continuous objects displaying.I also use UITableView to show ticker objects by transforming it to horizontal.But there was also a problem that is some of the cells displaying blank.
The main objective is that , I want a ticker view like pull down shutterStock in iphone.It has continuous and updated objects and very smooth scrolling.
screenshot is given below:
Anyone help me please!
Thanks..!
I have add some improvement in my custom tickerView that displays view objects.Here is the files:
StockTicker.h and StockTicker.m .By using these files you can create continuous object displaying on tickerView and can update data easily.
You can use these files just like UITableView.It has its delegates to pass numberOfView to display on ticker and view that will display at particular index.
Using its delegates as:
#pragma mark- UITickerView delegate method
- (NSInteger)numberOfRowsintickerView:(StockTiker *)tickerView
{
return [objectArray count];
}
- (id)tickerView:(StockTiker*)tickerView cellForRowAtIndex:(int)index
{
return [objectArray objectAtIndex:index];
}
here objectArray is array of UILabels.
You can download SampleProject.
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).
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 a WebView, and I want to call a view in Objective-C from JavaScript. Does someone know how I can do this?
I have this code in my ViewController:
- (BOOL)webView:(UIWebView *)webView2
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:#":"];
if ([components count] > 1 &&
[(NSString *)[components objectAtIndex:0] isEqualToString:#"myapp"]) {
if([(NSString *)[components objectAtIndex:1] isEqualToString:#"myfunction"])
{
NSLog([components objectAtIndex:2]); [[Airship shared] displayStoreFront]; //<- This is the code to open the Store
NSLog([components objectAtIndex:3]); // param2
// Call your method in Objective-C method using the above...
}
return NO;
}
return YES; // Return YES to make sure regular navigation works as expected.
}
And in Javascript:
function store(event)
{
document.location = "myapp:" + "myfunction:" + param1 + ":" + param2;
}
But nothing happens.
The standard workaround for UIWebView is to set a UIWebViewDelegate, and implement the method webView:shouldStartLoadWithRequest:navigationType:. In your JavaScript code, navigate to some fake URL that encodes the information you want to pass to your app, like, say:
window.location = "fake://myApp/something_happened:param1:param2:param3";
In your delegate method, look for these fake URLs, extract the information you need, take whatever action is appropriate, and return NO to cancel the navigation. It's probably best if you defer any lengthy processing using some flavor of performSelector.
The window.location method of calling objective c from JS isn't recommended. One example of problems: if you make two immediate consecutive calls one is ignored (since you can't change location too quickly) - try it yourself..
I recommend the following alternative approach:
function execute(url)
{
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", url);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
You call the execute function repeatedly and since each call executes in its own iframe, they should not be ignored when called quickly.
Credits to this guy.
Obliviux,
Your code seems to be perfect.
The reason for the problem is that you must have missed to map the delegate.
Either
Connect the delegate of the webView to the file owner in the .xib file
or
Use webView.delegate = self;
in your viewDidLoad.
Thanks
Like people said here, you have to use the method webView:shouldStartLoadWithRequest:navigationType: from the UIWebviewDelegate.
This api http://code.google.com/p/jsbridge-to-cocoa/ does it for you. It is very lightweight. You can pass images, strings and arrays from javascript to objective-C.
I had an issue with this approach: I wanted to send several messages to the iphone device, but it seemed that they were "overlaped" as they could not process all of them sequentially.
Example: when executing this code:
window.location = "app://action/foo";
window.location = "app://action/bar";
The action foo was never executed.
What I had to do was the following:
waitingForMessage = false;
function MsgProcessed(){
waitingForMessage = false;
}
function SyncLaunchURL(url){
if (waitingForMessage){
setTimeout(function(){SyncLaunchURL(url)},100);
}else{
window.location = url
waitingForMessage = true;
}
}
SyncLaunchURL("app://action/foo");
SyncLaunchURL("app://action/bar");
With this approach, the iphone has to call MsgProcessed() after processing the call. This way works for me, and maybe helps someone with the same problem!
Assuming you're doing an app, you can look at how PhoneGap implements that (or even use it). It's a library that supports back-and-forth communication between JS and OBJ-C. There are other libraries and solutions, as well.
If you're talking about a web app (something the user gets to from Mobile Safari), you can't get to Objective-C from there.
Check this one - understanding XMLHttpRequest responses using this (or other javascript) functions?, it's using objective C to call ajax js function, and get the response after it's done, you know the trick is that webview will be triggered when you change the location in javascript, so you can check the location to know its your javascript call or the real request.
Although this is a very old question now, it keeps getting returned by Google and there is a good answer now: the WebScripting informal protocol. It allows you to expose an objective C object to Javascript.
http://developer.apple.com/library/safari/documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html#//apple_ref/doc/uid/30001215-BBCBFJCD
-(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 ]
}