Ответ на этот вопрос оказывается очень простым, но его также сложно определить, если вы ищете неправильное место.
Прежде, чем мы добавим наших наблюдателей, нам нужно начать генерировать уведомления о воспроизведении:
musicPlayerController.beginGeneratingPlaybackNotifications()
NotificationCenter.default.addObserver(self,
selector: #selector(refreshView),
name: .MPMusicPlayerControllerPlaybackStateDidChange,
object: musicPlayerController)
NotificationCenter.default.addObserver(self,
selector: #selector(refreshView),
name: .MPMusicPlayerControllerNowPlayingItemDidChange,
object: musicPlayerController)
Нам также нужно помнить, чтобы завершить генерацию их, когда мы оставляем (освобождаем) вид:
deinit {
NotificationCenter.default.removeObserver(self, name: .MPMusicPlayerControllerPlaybackStateDidChange, object: nil)
NotificationCenter.default.removeObserver(self, name: .MPMusicPlayerControllerNowPlayingItemDidChange, object: nil)
musicPlayerController.endGeneratingPlaybackNotifications()
}
Путаница возникла из-за musicMediaPlayer, который возвращал несколько уведомлений даже без этого, что не указывало на тот факт, что мы не наблюдали все уведомления, которые были запущены.
Примечание: Стоит отметить, что на момент написания этой статьи обсуждался вопрос о необходимости ручного удаления наблюдателей - я включил его здесь для полноты ответа.
Вот старый предмет обсуждения , где я перечислил основные отличия и условия, в которых необходимо использовать каждый из этих методов. Я думаю, что можно найти полезным пройти обсуждение.
Для объяснения различий как относящиеся к отправленному примеру:
a. Когда Вы будете использовать RegisterStartupScript
, это представит Ваш сценарий после все элементы на странице (прямо перед конечным тэгом формы). Это позволяет сценарию звонить или элементы ссылочной страницы без возможности его не нахождение их в DOM Страницы.
Вот представленный источник страницы, когда Вы вызываете RegisterStartupScript
метод:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1"><title></title></head>
<body>
<form name="form1" method="post" action="StartupScript.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="someViewstategibberish" />
</div>
<div> <span id="lblDisplayDate">Label</span>
<br />
<input type="submit" name="btnPostback" value="Register Startup Script" id="btnPostback" />
<br />
<input type="submit" name="btnPostBack2" value="Register" id="btnPostBack2" />
</div>
<div>
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="someViewstategibberish" />
</div>
<!-- Note this part -->
<script language='javascript'>
var lbl = document.getElementById('lblDisplayDate');
lbl.style.color = 'red';
</script>
</form>
<!-- Note this part -->
</body>
</html>
b. Когда Вы используете RegisterClientScriptBlock
, сценарий представляется прямо после тега Состояния отображения, но перед любым из элементов страницы. Так как это - прямой сценарий (не функция, которая может быть названа , это будет сразу выполнено браузером. Но браузер не находит маркировку в DOM Страницы на данном этапе, и следовательно необходимо получить "Объект, не найденный" ошибка.
Вот представленный источник страницы, когда Вы вызываете RegisterClientScriptBlock
метод:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1"><title></title></head>
<body>
<form name="form1" method="post" action="StartupScript.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="someViewstategibberish" />
</div>
<script language='javascript'>
var lbl = document.getElementById('lblDisplayDate');
// Error is thrown in the next line because lbl is null.
lbl.style.color = 'green';
Поэтому для суммирования необходимо назвать последний метод, если Вы намереваетесь представить функциональное определение. Можно тогда представить эти вызов к той функции использование бывшего метода (или добавить клиентский атрибут).
Редактирование после комментариев:
<час>, Например, следующая функция работала бы:
protected void btnPostBack2_Click(object sender, EventArgs e)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<script language='javascript'>function ChangeColor() {");
sb.Append("var lbl = document.getElementById('lblDisplayDate');");
sb.Append("lbl.style.color='green';");
sb.Append("}</script>");
//Render the function definition.
if (!ClientScript.IsClientScriptBlockRegistered("JSScriptBlock"))
{
ClientScript.RegisterClientScriptBlock(this.GetType(), "JSScriptBlock", sb.ToString());
}
//Render the function invocation.
string funcCall = "<script language='javascript'>ChangeColor();</script>";
if (!ClientScript.IsStartupScriptRegistered("JSScript"))
{
ClientScript.RegisterStartupScript(this.GetType(), "JSScript", funcCall);
}
}