Swift 3.0
Очень простое решение здесь
Чтобы сменить страницу (UIViewController) из UIViewController, сначала получите экземпляр Parent ViewController (который будет UIPageViewController), а затем установите его текущий ViewController
В моем случае у меня есть UIPageViewController с именем «UserDetailsPVC» и он содержит 4 страницы (UIViewControllers), которые выглядят следующим образом
PageOneVC:UIViewController
PageTwoVC:UIViewController
PageThreeVC:UIViewController
PageFourVC:UIViewController
В UIPageViewController можно определить массив страниц
var pages:[UIViewController] = [
UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageOneVC"),
UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageTwoVC"),
UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageThreeVC"),
UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageFourVC")
]
Теперь, чтобы изменить страницу UIPageViewController с любого из UIViewController
// get parent view controller
let parentVC = self.parent as! UserDetailsPVC
// change page of PageViewController
parentVC.setViewControllers([parentVC.pages[1]], direction: .forward, animated: true, completion: nil)
Наилучшей практикой является не принудительная сбор мусора.
Согласно MSDN:
«Можно принудительно собрать сбор мусора, вызвав Collect, но большая часть время, этого следует избегать, потому что это может вызвать проблемы с производительностью ».
Однако, если вы можете надежно проверить свой код, чтобы подтвердить, что вызов Collect () не будет иметь отрицательного воздействия, идти вперед ...
Просто попробуйте очистить объекты, когда они вам больше не нужны. Если у вас есть пользовательские объекты, посмотрите на использование «using statement» и интерфейса IDisposable.
В этой ссылке есть некоторые полезные практические советы относительно освобождения памяти / сборки мусора и т. Д .:
В одном случае, с которым я недавно сталкивался, требуемые ручные вызовы в GC.Collect()
были при работе с большими объектами C ++, которые были обернуты крошечными управляемыми объектами C ++, к которым, в свою очередь, обращались с C #.
Сборщик мусора так как количество управляемой памяти было незначительным, но количество неуправляемой памяти было огромным. Вручную вызов Dispose()
для объектов потребует, чтобы я отслеживал, когда объекты больше не нужны сами, тогда как вызов GC.Collect()
очистит любые объекты, которые больше не передаются .....
GC.AddMemoryPressure (ApproximateSizeOfUnmanagedResource)
в конструкторе, а затем GC.RemoveMemoryPressure(addedSize)
в финализаторе. Таким образом сборщик мусора будет запускаться автоматически, принимая во внимание размер неуправляемых структур, которые могут быть собраны. [Д0] stackoverflow.com/questions/1149181/…
– HugoRune
21 January 2013 в 11:57
Я думаю, что пример, приведенный Rico Mariani , был хорош: может быть целесообразным инициировать GC, если произойдет существенное изменение состояния приложения. Например, в редакторе документов может быть нормально запускать GC, когда документ закрыт.
Большие объекты выделяются на LOH (куча больших объектов), а не на gen 0. Если вы говорите, что они не получают сбор мусора с генератором 0, вы правы. Я считаю, что они собираются только тогда, когда происходит полный цикл GC (поколения 0, 1 и 2).
. Считаю, что с другой стороны GC будет более агрессивно настраивать и собирать память, когда вы работаете с большими объектами, и давление памяти растет.
Трудно сказать, собираться или нет, и при каких обстоятельствах. Я использовал GC.Collect () после удаления диалоговых окон / форм с многочисленными элементами управления и т. Д. (Потому что к моменту, когда форма и ее элементы управления заканчиваются в гене 2 из-за создания множества экземпляров бизнес-объектов / загрузки многих данных - нет крупные объекты, очевидно), но на самом деле не заметили никаких положительных или отрицательных эффектов в долгосрочной перспективе, сделав это.
Посмотрите на это таким образом - эффективнее ли выкидывать кухонный мусор, когда мусор может составлять 10%, или пусть он заполняется, прежде чем вынимать его?
Не пуская его в пополнение , вы тратите свое время на прогулку в мусорный ящик и обратно. Это аналогично тому, что происходит при выполнении потока GC - все управляемые потоки приостанавливаются во время работы. И если я не ошибаюсь, поток GC может делиться между несколькими AppDomains, поэтому сбор мусора влияет на все из них.
Конечно, вы можете столкнуться с ситуацией, когда вы не будете добавлять что-либо к мусор может в ближайшее время - скажем, если вы собираетесь отправиться в отпуск. Тогда было бы неплохо выбросить мусор перед выходом.
Это может быть один раз, когда принудительное использование GC может помочь - если ваша программа простаивает, используемая память не собирает мусор, потому что нет назначений.
Не уверен, что это лучшая практика, но при работе с большими объемами изображений в цикле (т. е. создании и удалении множества объектов Graphics / Image / Bitmap) я регулярно позволяю GC.Collect.
Я думаю, что где-то я читал, что GC работает только тогда, когда программа (в основном) простаивает, а не в середине интенсивного цикла, так что это может выглядеть как область, где может быть полезен ручной GC.
Я научился не пытаться перехитрить сбор мусора. С учетом сказанного я просто придерживаюсь использования ключевого слова using
при работе с неуправляемыми ресурсами, такими как подключение к файлу ввода-вывода или базы данных.
Я думаю, что вы уже перечислили лучшую практику, и это НЕ использовать, если это НЕОБХОДИМО. Я бы настоятельно рекомендовал более детально проанализировать ваш код, используя инструменты профилирования, если это необходимо для ответа на эти вопросы.
Еще одна вещь: запуск GC Collect явно не может улучшить производительность вашей программы.
. NET GC хорошо спроектирован и настроен как адаптивный, что означает, что он может настроить порог GC0 / 1/2 в соответствии с «привычкой» вашей программной памяти Применение. Таким образом, он будет адаптирован к вашей программе через некоторое время. Когда вы вызовете GC.Collect явно, пороговые значения будут сброшены! И .NET должен потратить время, чтобы снова адаптироваться к привычке вашей программы.
Мое предложение всегда является надежным .NET GC. Любые проблемы с памятью, проверьте счетчик производительности «.NET Memory» и диагностируйте мой собственный код.
Однако, если вы можете надежно протестировать свой код, чтобы подтвердить, что вызов Collect () не будет иметь отрицательного воздействия, тогда продолжайте ...
blockquote>IMHO, это аналогично высказыванию «Если вы можете доказать, что ваша программа никогда не будет иметь никаких ошибок в будущем, тогда идите вперед ...»
По всей серьезности принудительное использование GC полезно для целей отладки / тестирования. Если вы чувствуете, что вам нужно делать это в любое другое время, то либо вы ошибаетесь, либо ваша программа была построена неправильно. В любом случае, решение не заставляет GC ...
Существует несколько общих рекомендаций по программированию, которые являются абсолютными. Половина времени, когда кто-то говорит, что «вы делаете это неправильно», они просто набрасывают определенную догму. В C раньше он боялся таких вещей, как самомодифицирующийся код или потоки, в языках GC он принуждает GC или, альтернативно, предотвращает запуск GC.
Как и в случае с большинством руководств и хороших эмпирических правил (и хороших методов проектирования), есть редкие случаи, когда имеет смысл работать по установленной норме. Вы должны быть уверены, что понимаете дело, что ваш случай действительно требует отмены обычной практики и что вы понимаете риски и побочные эффекты, которые вы можете вызвать. Но есть такие случаи.
Проблемы программирования очень разнообразны и требуют гибкого подхода. Я видел случаи, когда имеет смысл блокировать GC в собранных мусором языках и местах, где имеет смысл запускать его, а не ждать, когда это произойдет естественным образом. 95% времени, любой из них был бы признаком того, что не подошел к проблеме правильно. Но 1 раз в 20, вероятно, для этого есть действительный случай.
Не уверен, что это лучшая практика ...
blockquote> blockquote>Предложение: не реализуйте это или что-нибудь, когда вы не уверены. Переоценивайте, когда факты известны, затем выполните до / после проверок производительности.
Я хотел бы добавить, что: вызов GC.Collect () (+ WaitForPendingFinalizers ()) является частью истории. Как справедливо упоминается другими, GC.COllect () является недетерминированным набором и остается на усмотрение самого GC (CLR). Даже если вы добавите вызов WaitForPendingFinalizers, это может быть не детерминированным. Возьмите код из этой ссылки msdn и запустите код с итерацией цикла объекта как 1 или 2. Вы найдете то, что не является детерминированным средством (установите точку прерывания в деструкторе объекта). Точно так же деструктор не вызывается, когда Wait .. () имеет только 1 (или 2) затяжные объекты. [Citation reqd.]
Если ваш код имеет дело с неуправляемыми ресурсами (например: внешний файл дескрипторы).
Вот интересный пример:
Примечание. Если вы уже пробовали пример из MSDN, чтобы очистить воздух.
class Program
{
static void Main(string[] args)
{
SomePublisher publisher = new SomePublisher();
for (int i = 0; i < 10; i++)
{
SomeSubscriber subscriber = new SomeSubscriber(publisher);
subscriber = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(SomeSubscriber.Count.ToString());
Console.ReadLine();
}
}
public class SomePublisher
{
public event EventHandler SomeEvent;
}
public class SomeSubscriber
{
public static int Count;
public SomeSubscriber(SomePublisher publisher)
{
publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
}
~SomeSubscriber()
{
SomeSubscriber.Count++;
}
private void publisher_SomeEvent(object sender, EventArgs e)
{
// TODO: something
string stub = "";
}
}
Я предлагаю сначала проанализировать, какой результат мог быть, а затем запустить, а затем прочитать причину ниже:
{Деструктор только неявно называется один раз программа заканчивается. } Чтобы детерминистически очистить объект, нужно реализовать IDisposable и сделать явный вызов Dispose (). В этом суть! :)
TargetOfInvocationNullException
. – IAbstract 1 April 2012 в 16:30