2016-08-28 2 views
1

У меня есть приложение с вкладками.Вызов метода в другом контроллере просмотра, но не перейдите к нему?

вкладка A: кнопка загрузки.

Вкладка B: TableView

То, что я хочу сделать, когда нажать на кнопку в A, я хочу функцию загрузки в B можно назвать.

Теперь у меня есть несколько сценариев, после нажмите кнопку:

  • пребывания в
  • если я нажимаю B теперь я могу видеть процесс загрузки, или если выполнится, я могу увидеть там файл ,

    +----------------+   +-----------------+ 
    |    |   |downloaded files | 
    |    |   +-----------------+ 
    | +------------+ |   |     | 
    | | download | |   +-----------------+ 
    | +------------+ |   |     | 
    |    |   |     | 
    +-------+--------+   +--------+--------+ 
    |now in | B |   | A  | now in | 
    | A |  |   |  | B | 
    +-------+--------+   +--------+--------+ 
    

Теперь я пишу функцию загрузки в A, и сохранить все файлы в каталоге, всякий раз, когда я нажимаю на вкладку B, функция viewWillAppear будет загружать загруженные файлы из каталога, но проблема Я хочу показать процесс загрузки, если файл большой.

Любое предложение и фрагмент кода оцениваются.

+4

Для управления загрузкой вам нужен третий класс (C). A и B оба ссылаются на один экземпляр этого, либо с использованием одноэлементного или (предпочтительно) вашего контроллера панели вкладок, обеспечивающего ссылку на объект на A и B. Затем A может вызывать метод на C, чтобы инициировать загрузку и B может запросить C о состоянии загрузки. – Paulw11

ответ

3

Использование Swift 3

Перед тем, как обеспечить решение, которое я укажу вам @ Paulw11 свой комментарий, он 100% правильно. Правильное соглашение состоит в том, чтобы вытащить логику подключения из контроллеров вашего вида. Единственный код, который вы должны иметь в контроллерах вашего вида, - это код, необходимый для отображения вашего представления. Подключение к серверу и управление результатом не имеет ничего общего с , представляя результирующие данные в представлении.

Если вы действительно были вынуждены вызвать функцию непосредственно с другого вида, , вы не должны делать это, создав новый экземпляр вашего контроллера вида. Скорее всего, вы должны просто получить существующий экземпляр так:

let app = UIApplication.shared.delegate! as! AppDelegate 
    if let viewControllers = app.window?.rootViewController?.childViewControllers { 
     viewControllers.forEach { vc in 
      if let view = vc as? AnotherViewController { 
       view.downloadIt() 
      } 
     } 
    } 

Лично я рекомендовал бы вытягивать эту логику из контроллера зрения в любом случае. Если вы пытаетесь сохранить что-то минимальное или если это единственный вызов веб-службы, который вы делаете, вы можете просто сделать что-то вроде этого:

Добавить новый файл Swift с протоколом и расширением для этого протокола:

protocol Downloadable : class { } 

extension Downloadable { 

    func downloadStuff() -> String { 
     // Add your download logic here 
     return "downloading" 
    } 
} 

Затем, в любом виде вы хотите, чтобы иметь возможность использовать эту функцию загрузки просто добавить протокол к вашей View Controller, как это:

class ViewController: UIViewController, Downloadable {} 

Тогда вы можете очень легко получить загруженные данные, такие как это:

@IBAction func handleDownloadTapped(_ sender: UIButton) { 
    let result = downloadStuff() 
    print(result) 
} 

Опять же, вы не должны привыкать к этому, так как это может стать беспорядочным, если вы работаете с несколькими различными вызовами api.

Лучшей практикой является создание класса, который содержит ваши материалы веб-сервиса, мне лично нравится подход objc.io. Здесь вы можете найти учебник.

https://talk.objc.io/episodes/S01E01-networking

В основном вы будете создавать услугу, как этот

public typealias JSONDict = [String: AnyObject] 

struct Resource<A> { 
    let url: URL 
    let parse: (NSData) -> A? 
} 

let url = URL(string: "https://url")! 

let myResource = Resource<[JSONDict]>(url: url) { data in 
    let json = try? JSONSerialization.jsonObject(with: data as Data, options: []) 
    return json as? [JSONDict] 
} 

final class Connect { 
    class func load<A>(resource: Resource<A>, completion: @escaping (A?) -> Void) { 
     URLSession.shared.dataTask(with: resource.url) { (data, _, _) in 

      if let data = data { 
       completion(resource.parse(data as NSData)) 
      } else { 
       completion(nil) 
      } 
      }.resume() 
    } 
} 

А вы можете назвать его везде, где вам нужно это нравится:

Connect.load(resource: myResource) { result in 
    // do stuff with result 
} 

Я надеюсь, что это было полезно кто-то

+0

Как использовать этот метод с AFNetworking? –

+0

@ Mr.UB Я не использовал AFNetworking, я почти всегда заказываю свой собственный сеанс URL. Когда я не использую сеанс URL напрямую, я обычно использую Alamofire. Вы можете просто заменить код Connect на Alamo или AF, и он должен работать нормально. –

+0

О, ошибка, я на самом деле имел в виду 'Alamofire'. Можете ли вы привести небольшой пример? –

Смежные вопросы