Trying to play with the annotation and bubble callout on mkmapview - iphone

I am developing an application in iphone which deals with maps. I have many annotations. I need different images to be loaded in the callout bubble.It mean user can edit the callout it may be image and He also type text on callout bubble .How can I give give multiple action on the callout bubble .
And most important think is that this annotation must drop on the map after clicking the save button. For Example I have two class (mapview And photoview),And in photoView i have three button (chooshphoto,takephoto,usephoto)when user take photo or browse for photo and he want use this photo.When he click on usephoto button the annotation must drop after that.And display onthe mapView.

The second half of your question isn't very clear but I'll try and answer the first.
The only real customisation you can apply to the callout view for an MKAnnotation is to set the Title, subtitle labels and the left/right calloutAccessoryViews. You can set the latter to images or callOutAccessoryViewIndicators, or another UIView but it can't be taller than 32 pixels.
MKAnnontationView documentation
That's really about it I'm afraid. For anything more advanced than that, you'll have to create a custom implementation. This blog post should be helpful, I plan on building something similar myself.
MKPinAnnontationView can be set to drop on the map as you describe so as long as you're happy with the Pin image for the annontation view itself, you can simply set it's animatesDrop property to YES and it will animate onto the map when it's added.
MKPinAnnontationView documentation
EDIT: I think this is what you want;-
In your mapView controller, define a property to hold the object you want to animate.
#interface MyMapViewController {
Photo *photoToAnimate;
}
#property (nonatomic, retain) Photo *photoToAnimate;
#end
Then in your implementation file, add the following to ViewDidAppear
-(void)ViewDidAppear {
...
if (photoToAnimate) {
[mapView addAnnotation:photoToAnimate];
self.photoToAnimate = nil; // reset it for the next time
}
...
}
Then in your PhotoViewController, simply set the property on the button press
-(void)usePhotoAction {
...
mapViewController.photoToAnimate = photo;
...
}
At least that's the really simple hacky way of what I was trying to describe in the comments. ViewDidAppear will fire when the MapView re-appears and it will add the pin to itself accordingly. If you need to add more than one pin, use an array to store them and iterate through the array.
There might be better patterns for this but in short, your MapView needs to get hold of the object you want to drop somehow and then not actually do anything with it until ViewDidAppear is called.

Related

How to populate an image in UITableViewCell even if user scroll the table

I'll try to explain my self, I have ContactsViewController that shows a table view with a list of contacts (the model is an array of Contact objects), each cell display an image of a contact.
Currently what I do to populate the cell's UIImageView is this:
1. I override the Contact image property getter -
- (UIImage *)contactImage
{
if (!_contactImage) {
_contactImage = [[UIImage imageNamed:#"placeHolder.png"] retain];
[self asyncDownloadContactImageFromServer];
}
return _contactImage;
}
Then when I finish downloading the image I set it to the contactImage property and I post a ContactUpdatedImageNotification.
My ContactsViewController then get this notification and reload the cell of this contact, this will set the downloaded image to the cell's imageView.
The result of this is good async fetching of the images without blocking the UI while the user scroll the table view.
BUT there is something small that bothers me, when the a user scroll the table view and reveal new cells the new cell's image get download as expected but the cell's imageView is not updated with the new downloaded image till the user pick up his finger.
I supposed that I need to do something in another thread to make this effect, but I don't know how?
The image is not updated until the user stops scrolling due the code being executed in the default runloop, which gets delayed until scrolling finishes. This other question deals with the difference between the runloops, NSDefaultRunLoopMode vs NSRunLoopCommonModes and it precisely recommends not updating the images while scrolling since that can introduce jerkiness in the scrolling itself if you are not careful.
Also, now that you know about the existence of these runloop modes you will be able to find much more information about them in the xcode documentation or internet.
Hey Eyal visit following url...you will get answer and as well sample code...
tableview with different cell with different images
Hope this will help you...

How can I access various UIViews within a Nib, programmatically?

First, I am super-new to Objective-C/iOS development and, in fact, this question is for my first, test project. Also, I come from a C#/WinForms background so I'm coming into iOS development with certain pre-conceived notions of user interface design and application state. Please bear with me and help clear up my confusion.
I just created my first iOS application project which, consists of a Single View. I allowed Xcode to create all the files for me through the Single View project wizard. When it was finished, I opened my new applications, single UIView Nib file in the designer and I dropped three sliders onto the view.
The desired purpose of this application is very simple-- each slider corresponds to either the R, G or B values associated with the background color of my view.
I have figured out how to set the background of my view but I can not figure out how to access the values of each slider objects. Yes, I can hook-up and respond to an IBAction for each slider, but my plan is that each time a slider's value changes, I want the IBAction to call a refactored method that accesses the values of all three sliders and then set's the views Background Color based of the values associated with each one.
How can I access the values of my sliders? Specifically, how can I access the value of the sliders that I created by dragging and dropping them into the Nib designer window? I've seen code explaining how to programatically add a UISlider to your UIView and then access the value, but how do you access the value of a UISlider that's added to the Nib and, I assume, will be automatically "wired" in at compile time?
Hopefully this makes since? If I'm missing an intermediate step or critical concept, please let me know.
You create UISlider ivars/properties and make them IBOutlets:
#property (nonatomic, retain) IBOutlet UISlider* yourSlider;
You synthesize it in your .m file and the connect the IBOutlet in interface builder. The yourSlider pointer is then a reference to the object you connected it to. Note that it will only be loaded with the view of the UIViewController and therefore will be nil until viewDidLoad is called. You also must set it back to nil
self.yourSlider = nil;
in your viewDidUnload method (so that it is released). In Xcode 4 you have a convenient way of doing all the above steps in one action (see the "Interface Builder is Built-in" of What's new in XCode 4)
Similar to CTRL+dragging from the UISlider to the .m file to create the IBAction, you can CTRL+drag the UISlider from your .nib designer to the associated .h file and have it create a property for you. Then, from your .m file, you can access self.mySlider (or whatever you name the property).
There's a video on this page that shows binding to a UISlider specifically.
Another approach is to use the tag property of a view.
#property(nonatomic) NSInteger tag
- (UIView *)viewWithTag:(NSInteger)tag
You can set the tag property of a view in the interface builder and later reference that view in your controller.
UIView *myViewFromTag = [self.view viewWithTag:theNumberYouSetInIB];
In general, it's better to stick with IBOutlets. However, there are certain situations where it makes more sense to use tags.
Good luck!

How can I send characters to cursor position of UISearchBar?

I am trying to add a couple characters that are inconveniently located in the normal keyboard, and place them in a toolbar so that the user can use them just like normal keys.
Does anyone have a useable way to do this?
I found an article explaining how to do this by simulating a "Paste" operation, (remove pasteboard contents, replace with my character, paste into field, return original pasteboard contents) but my trouble is that I'm trying to do this with a UISearchBar, which seems to have no paste selector.
Update
I found a lead:
UIKIT_CLASS_AVAILABLE(2_0) #interface UISearchBar : UIView {
#private
UITextField *_searchField;
Since it is documented that there's a UITextField in a search bar, if I were to root through the searchbar's subviews and locate said text field, (assuming with 99% certainty that the text field has a delegate) would it make sense that I could "steal" the text field and make my class the delegate, then forward the messages to the original delegate once I'm done with them?
This is definitely tricky. UISearchBar doesn't give you inputAccessoryView and nor do you get selectedRange.
You can paste in a UISearchBar. If you want to get your tricky characters to the pasteboard, you could get a button to execute something such as:
[[UIPasteboard generalPasteboard] setString:#"[*]"];
and then get the user to use paste in the UISearchBar. Pretty awkward for the user though.
Rooting through the subviews to find the UITextField might work. If you do this, you'd need to grab the existing delegate and make yourself the delegate. Then your delegate would need to transmit messages on. The process is described in this stackoverflow question and answer. Potential challenges here: (a) the Apple implementation could change between iOS updates and even, though unlikely, change the delegate during the lifetime of the UISearchBar; (b) Apple might see this as using a private API and reject the app. (I don't have any hard evidence of (b), but it's something to consider.)
One approach might be to use the bookmark button. The UISearchBar delegate can detect this. You could use that to insert your special characters or offer up a menu of special character insertions. Of course, you won't know where the cursor is. But, depending on your use case, appending the special characters at the end might be OK. Perhaps this doesn't get you anything over a button on your interface that just appends something.
[[self searchBar] setText: [NSString stringWithFormat:#"%#[*]", [[self searchBar] text]]].)
Implementing your own search bar might be the best way to go as already suggested #hyperbole. I've done this successfully by adding a custom UITextField (with my own magnifying glass in the leftView slot etc.) and adding it as the titleView of my navigationBar. But, if I understand your question aright, that still won't be enough, as UITextField doesn't provide selectedRange and its delegate doesn't provide an equivalent of textViewDidChangeSelection:. You might have a go with a UITextView that is fixed to one line (with scrolling clamped down if required - it often seems to be).
Can't you simply set the text of the UISearchBar? Of course, the tricky part is to determine the cursor position. For that, you can register a UITapGestureRecognizer on the UISearchBar, determine the tap co-ordinates & calculate the cursor position using - (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode or its variants.
You may also have to register a UIPanGestureRecognizer, as the user can change the cursor position by tapping, dragging & then releasing the finger.
HTH,
Akshay

How to tell when MKMapView and visible MKAnnotationView are finished drawing?

I'm displaying a MKMapView with MKAnnotations some of which are selected and showing their Annotation.
I am trying to grab an image of the displayed map and annotations using the -renderInContext.
90% of the time the Map, MKPinAnnotationView's and selected annotations are correctly captured.
The other 10% of the time the image is missing something, usually the MKPinAnnotationViews or their annotations if selected.
I've added code to deal with the Map itself loading it's map data.
But I haven't been able to track down something that would indicate to me that all of the visible MKPinAnnotationView's have been drawn
and if selected their annotations displayed??
the closest hint I've come across is the addObserver, although I haven't figured out what could be observed that would tell me when all of the drawing is done.
Thoughts?
ok I'm an idiot...
I finally tracked down the problem. In my viewForAnnotation routine in the MKMapView Delegate protocol I wasn't correctly setting values for reused MKPinAnnotationView's.
So some of the time I would reuse a view that had .canShowCallout set to YES and other times I'd reuse a view that had .canShowCallout set to NO.
.<
Try using the MKMapViewDelegate didAddAnnotationViews method.
If in that method, the drawing is still not ready for your requirements, you could then in there call your capturing method with performSelector:withObject:afterDelay:.

How to change the color of UIBarButtonItem?

I have a UIToolbar, and then add two UIBarButtonItem to items of UIToolbar. How can I change the color of UIBarButtomItem? I did't find a API in the document.
see "Changing colors of UINavigationBarButtons"
EDIT: I remove the link because the domain is down...
The is the text from google cache:
Alright, here’s another quick tip. “How to change the colors of a button on a toolbar.” Of course, this can be applied to any toolbar but I am going to demonstrate the procedure on a UINavigationBar.
The above image only shows a couple of colors. In truth, you can make the button any color that you want. Fantastic! The code is really simple to do this as well. The first thing that we want to do is open the header file for whichever object will be turning a nav bar button a different color and declare the forward class UINavigationButton. You can get this class by either iterating through the subviews of the UINavigationBar, reading its subviews class names, or by class-dumping UIKit if you have a jailbroken device.
Place the following line before your interface declaration:
#class UINavigationButton;
Now, declare a new method in the header that we will use to actually change the button’s color.
- (void)changeNavigationButtonColorToColor:(UIColor *)newColor
Or something similar to the above line of code.
Now, open up your object’s implementation file and implement the above method. Anywhere in your file, add the following method:
- (void)changeNavigationButtonColorToColor:(UIColor *)newColor {
for (UIView *view in self.navigationController.navigationBar.subviews) {
NSLog(#"%#", [[view class] description]);
if ([[[view class] description] isEqualToString:#"UINavigationButton"]) {
[(UINavigationButton *)view setTintColor:newColor];
}
}
}
As you can see above, this is actually a lot easier than it first appears to be. What we first do is set up a for loop to iterate through the subviews of the UINavigationBar using NSFastEnumeration. We then output the class name of the subview, for future reference. IF the class name is UINavigationButton, then we’ve got our view. All we do is set the tintColor property if the UINavigationButton.
That’s it, we’re done!
Alternatively, if you want a wider scope, I’d suggest creating a new UINavigationBar category and placing the button color changing method in there. This was your method can be performed by any class that uses a UINavigationBar without having to recreate the same method over and over.
Remember, a back button and a navigation button are not the same thing. You will have to color the back button separately.
And as usual, here’s a link to a sample app that demonstrates this code: NavButtonColor.zip
UIBarButtomItem has limitation in customization so you can use UIButton in place of UIBarButtonItem it will gives you more customization.
For a solution that doesn't use a private API.
You can fake it by making a UISegmentedControl look like a UIBarButtonItem.
http://fredandrandall.com/blog/2011/03/31/how-to-change-the-color-of-a-uibarbuttonitem/