2017-11-16 8 views
1

私は単純なUITable実装と果物と呼ばれる配列を持っています。例えば、thisのようになります。唯一の違いは、UITableViewControllerのUITable instedに対してUIViewControllerを使用していることですが、これは今のところ無関係です。他のスレッドからUITableに通知する

class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 

    var fruits : [String] = Array() 
    let thread : GetDataForFruitsArrayThread 

    func numberOfSections(in tableView: UITableView) -> Int { 
     return 1 
    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return fruits.count 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) 

     cell.textLabel?.text = fruits[indexPath.row] 

     return cell 
    } 

    } 

私はこのクラスでもviewDidLoad関数を持っています。関数では、配列としてパラメータを取得しているスレッドを呼び出しています。スレッドは配列を新しい値で非同期的に埋めています。値があるかどうか、値がいつ表示され、配列に設定されるかは分かりません。この点について私が尋ねたいことを想像することができます。UITableViewに、ビューが配列をUITableにロードした後で配列の内容を変更したことを通知するにはどうすればよいですか? C#ではNotifyAll()関数があり、これは属性に対するすべてのListenerを認識しません。オプションで、含まれていないライブラリをインポートせずに、迅速かつ簡単にこれを行うための簡単で実用的な方法はありますか?

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.thread = GetDataForFruitsArrayThread(array: &fruits) 
    self.thread.StartAsynchronously() 

} 

EDIT - GetDataForFruitsArrayThread

class GetDataForFruitsArrayThread : MyThread { 

var array : [String] 

init(array: inout [String]) { 
    self.array = array 
} 


override func main() { 

     // init socket 

while(true){ 

     _ = withUnsafeMutablePointer(to: &rcvaddr){ 
      $0.withMemoryRebound(to: sockaddr.self, capacity: 1){ 
     recvfrom(m_socket, &pData, bufferlength, 0, UnsafeMutablePointer($0), 
       &socketAddressLength) 
      } 
     } 

     var fruit = String(cString:inet_ntoa(rcvaddr.sin_addr), encoding: .ascii) 
     self.array.append(fruit) 

    } 
} 
} 

EDIT追加 - 2017年11月21日:サンディープバンダリの答えに続き

を私はのViewControllerに次のコードを変更:

@IBOutlet weak var tableView1: UITableView! 

var fruits : [String] = Array() { 
     didSet { 
      self.tableView1.reloadData() 
     } 
    } 

問題:私はGetDataForFruitsArrayThreadクラスのarray.append(果物)のブレークポイント。その後、didSetメソッドにブレークポイントがあります。しかし、このブレークポイントはappend() - 呼び出しの後に呼び出されることはありません!注:GetDataForFruitsArrayThreadクラスのinit関数のパラメータは、in-outパラメータです!

更新:GetDataForFruitsArrayThreadスレッド内のGetDataForFruitsArrayThread.arrayでarray.append(fruit)-callを実行すると、ViewControllerクラスのフルーツ配列が変更されないため、didSetが変更されないことがわかりました呼び出されます。この動作を変更するにはどうすればよいですか?

+0

メソッドにクロージャパラメータを追加し、ネットワーク機能が終了したときに通知を受け取るコールバックを追加します。 –

+0

この関数は終了しません。アプリケーションの実行中にネットワークからパケットを受信しようとする無限のスレッドです。要素が追加されるたびに呼び出されるパラメータとしてハンドルを渡す必要があることを意味しますか?はいの場合、ハンドラがトリガされた場合、ViewControllerで何が起こるはずですか?何とかUITableリロードができますが、どうしたらうまくいくのでしょうか? – David

+0

同じアプローチでクロージャを追加し、必要に応じてオブジェクトの配列をパラメータとしてこのクロージャを実行し、このクロージャが呼び出されると、オブジェクトのviewController配列を更新し、UITableViewを更新する必要があります –

答えて

2

アレイを更新し続けるために無限のプロセスを実行していて、アレイが変更されたらUIを更新したいと言ったので、以下のソリューションを使用できます。

var fruits : [String] = Array() { 
     didSet { 
      self.tableView.reloadData() 
     } 
    } 

私は何をしていますか?単純な配列にsetterを追加し、値が変わるたびにtableViewをリロードします。

EDIT:

上記の解決策は、あなたがGetDataForFruitsArrayThread

self.thread = GetDataForFruitsArrayThread(array: &fruits) 

にお渡しINOUT果実の配列を変更した場合にのみ動作しますので、変更はなく、直接GetDataForFruitsArrayThreadに1つのより多くの配列プロパティを作成しないでください配列はGetDataForFruitsArrayThreadに渡されます。

+0

この編集では、GetDataForFruitsArrayThread'のコンストラクタでこれをしないことを意味します:self.array = fruits。右?しかし、もし私が配列変数に対して安全でないなら、main()関数の果実パラメータにどのようにアクセスできますか? – David

+0

@ david:いいえ、あなたがやっていることを意味するものではありません:)私が意味するのは、あなたに渡された配列の同じインスタンスを使用し、配列の別のインスタンスを作成しないことです。私は深いn浅いコピーを知っていることを願っています。 InOutのパラメーターは参照渡しです。したがって、同じ参照を使用してください。私はあなたの質問を半分投稿したときにその編集を書いた。 arrayという名前の変数を見ると、あなたに渡されたものを使うのではなく、配列の新しいインスタンスがあるかもしれないと思った:) –

+0

self.array = fruitsは配列の新しいインスタンスを作成せず、 self.array = [String]()は、提案されたソリューションでは動作しない新しいインスタンスを作成します。あなたが今やっていることはうまくいくはずです:) –

関連する問題