Я впервые использовал решение Xilexio, но оно было медленным. Я в конечном итоге с помощью тегов. Вот мой код и приведенный в качестве примера.
@property (nonatomic) NSInteger currentFormField;
typedef NS_ENUM(NSInteger, IOUFormField) {
IOUFormFieldName,
IOUFormFieldAmount,
IOUFormFieldDescription,
IOUFormFieldDate
};
...
self.nameField.tag = IOUFormFieldName;
self.amountField.tag = IOUFormFieldAmount;
self.descriptionField.tag = IOUFormFieldDescription;
self.dateField.tag = IOUFormFieldDate;
-(void)keyboardWillShow:(NSNotification *)notification {
// Move the scroll view to a position where the user can see the top and bottom form fields
// For example, if the user is on the description field, they should be able to see the date field and the amount field.
// The keyboard rect value comes as a NSValue * (a wrapped NSRect) with origin and size.
// The origin is using screen coordinates which is pixel based so don't use it.
// Use the size. Seems like it is density based.
CGFloat viewableScreenHeight = self.view.frame.size.height - keyboardFrameBeginRect.size.height;
// When the user is on a form field, get the current form field y position to where the scroll view should move to
CGFloat currentFormFieldYPosition = 0;
switch (self.currentFormField) {
case IOUFormFieldName:
{
currentFormFieldYPosition = self.nameField.frame.origin.y;
// If the scroll view is at the bottom and the user taps on the name field, move the scroll view to the top.
// This is so that users can see the give/get segments.
[self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
break;
}
case IOUFormFieldAmount:
{
currentFormFieldYPosition = self.amountField.frame.origin.y;
break;
}
case IOUFormFieldDescription:
{
currentFormFieldYPosition = self.descriptionField.frame.origin.y;
break;
}
case IOUFormFieldDate:
{
currentFormFieldYPosition = self.dateField.frame.origin.y;
break;
}
default:
break;
}
// I want the current form field y position to be 100dp from the keyboard y position.
// 50dp for the current form field to be visible and another 50dp for the next form field so users can see it.
CGFloat leftoverTopHeight = viewableScreenHeight - 100;
// If the current form field y position is greater than the left over top height, that means that the current form field is hidden
// We make the calculations and then move the scroll view to the right position
if (currentFormFieldYPosition > leftoverTopHeight) {
CGFloat movedScreenPosition = currentFormFieldYPosition - leftoverTopHeight;
[self.scrollView setContentOffset:CGPointMake(0, movedScreenPosition) animated:YES];
}
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
switch (textField.tag) {
case IOUFormFieldName:
self.currentFormField = IOUFormFieldName;
break;
case IOUFormFieldAmount:
self.currentFormField = IOUFormFieldAmount;
break;
case IOUFormFieldDescription:
self.currentFormField = IOUFormFieldDescription;
break;
case IOUFormFieldDate:
self.currentFormField = IOUFormFieldDate;
default:
break;
}
return true;
}
Дайте мне знать, если у вас есть какие-либо вопросы, и я уточню. Обратите внимание, что комментарии для меня. Также обратите внимание, что некоторые коды или опущены для краткости.
Хорошо, вот решение этой проблемы.
Для отображения выноски используйте MKMapView
метод selectAnnotation: animated
.
У меня это не работает. Я подозреваю, что это ошибка в API MapKit.
См. Эту ссылку, чтобы получить подробную информацию о том, для кого это не работает: http://www.iphonedevsdk.com/forum/iphone-sdk-development/19740-trigger-mkannotationview-callout-bubble.html#post110447
--edit--
Ладно после того, как накрутил это какое-то время вот что мне удалось заставить работать:
for (id<MKAnnotation> currentAnnotation in mapView.annotations) {
if ([currentAnnotation isEqual:annotationToSelect]) {
[mapView selectAnnotation:currentAnnotation animated:FALSE];
}
}
Обратите внимание, это требует реализации - (BOOL) isEqual: (id) anObject
для вашего класса, реализующего протокол MKAnnotation.
Но есть уловка, чтобы заставить решение benvolioT работать, код
for (id<MKAnnotation> currentAnnotation in mapView.annotations) {
if ([currentAnnotation isEqual:annotationToSelect]) {
[mapView selectAnnotation:currentAnnotation animated:FALSE];
}
}
должен вызываться из - (void) mapViewDidFinishLoadingMap: (MKMapView *) mapView
и нигде больше.
Последовательность, в которой различные методы, такие как viewWillAppear
, viewDidAppear
из UIViewController
и - (void) mapViewDidFinishLoading *) mapView
вызывается по-разному между первой загрузкой карты с одним конкретным местоположением и последующими разами, когда карта отображается с тем же местоположением. Это немного сложно.
If you just want to open the callout for the last annotation you added, try this, works for me.
[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
из-за чего-то вроде кода, показанного Benvoliot, что я подозреваю, что в системе, когда я использовал Sealannotation: Анимация: Метод, он не послужил выношению, я догадался, что причина была, потому что она уже выбрана, и избегало попросить MAPVIVE перерисовать вызыву на карте, используя название аннотации и субтитров.
Итак, решение было просто отменито тому, чтобы сначала было отменито, и повторно выбрать его.
E.g: Во-первых, мне нужно было сделать это в сенсорном методе Apple (I.e. Как перетащить AnnotationView), чтобы скрыть вызывую. (Просто используя Annotation.canshowannotation = ни один не работает, поскольку я подозреваю, что ему нужно перерисовать. Деселектанотайтонет вызывает необходимое действие. Также отменившись в одиночку не делал этого трюка, выяснил только один раз и получил перерисовку. Это Был подсказкой, который он получил автоматически повторно).
annotationView.canShowAnnotation = NO;
[mapView deselectAnnotation:annotation animated:YES];
Затем, просто используя код ниже в затронутом способе, не вернул вызываемость (аннотация была автоматически выбрана системой к тому времени, и, по-видимому, предварительно перерисование вызовов никогда не оказывает occrrs):
annotationView.canShowAnnotation = YES;
[mapView selectAnnotation:annotation animated:YES];
решение было :
annotationView.canShowAnnotation = YES;
[mapView deselectAnnotation:annotation animated:YES];
[mapView selectAnnotation:annotation animated:YES];
Это просто выкупило отзыву, по-видимому, повторно инициировало процесс перерисования вызове MapView.
Строго говоря, я должен определить, является ли аннотация текущей аннотацией или нет (выбрано, что я знаю, это есть) и независимо от того, на самом деле вызывается или нет (которые я не знаю) и решите перерисовать его соответственно , это было бы лучше. Я, однако, еще не нашел метод обнаружения выносов, и пытался сделать это, сам всего немного ненужным на этом этапе.
Ответ Стива Ши ясно дал мне понять, что selectAnnotation необходимо вызывать из метода mapViewDidFinishLoadingMap. К сожалению, я не могу проголосовать, но хочу поблагодарить.