2017-09-28 47 views
1

我有一個分割視圖控制器與頂視圖控制器設置爲表視圖控制器,該控制器將顯示播放列表供選擇。該應用程序首次加載時要求獲得音樂訪問權限。回答是允許,但表格視圖不顯示播放列表。我最終不得不殺掉應用程序並再次運行它。我是否要求音樂庫許可權是錯誤的地方?這是在頂視圖控制器的viewWillAppear和存儲播放列表我使用的播放列表(因爲一些被篩選出)在一類播放列表中。swift問初始視圖控制器的音樂權限

 override func viewWillAppear(_ animated: Bool) { 
    self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed 
    super.viewWillAppear(animated) 

    checkMediaAccessAndSetup() 
} 

func checkMediaAccessAndSetup() { 
    let authorizationStatus = MPMediaLibrary.authorizationStatus() 
    switch authorizationStatus { 
    case .notDetermined: 
     // Show the permission prompt. 
     MPMediaLibrary.requestAuthorization({[weak self] (newAuthorizationStatus: MPMediaLibraryAuthorizationStatus) in 
      // Try again after the prompt is dismissed. 
      self?.checkMediaAccessAndSetup() 
     }) 
    case .denied, .restricted: 
     // Do not use MPMediaQuery. 
     return 
    default: 
     // Proceed as usual. 
     break 
    } 
    // Do stuff with MPMediaQuery 
    self.setupPlaylistStore() 
    tableView.reloadData() 
} 
+0

由於MPMediaLibrary requestAuthorization塊實現爲[weak self],因此self可能在塊內部爲零。你確定checkMediaAccessAndSetup方法在MPMediaLibrary請求授權後被調用嗎? – Rendel

+0

這可能是由於在主線程上未調用requestAuthorization回調引起的。嘗試在DispatchQueue.main.async中調用'self?.checkMediaAccessAndSetup()'' –

+0

嘗試self.checkMediaAccessAndSetup()裏面的DispatchQueue.main.async {}裏面viewWillAppear(它不會允許self?.checkMediaAccessAndSetup()) 。一樣。 – EdZ

回答

0

與您的代碼的主要問題是

  • 你是完全失敗的事實,該requestAuthorization完成函數被調用後臺線程作鬥爭。您需要走出主線程才能在界面上工作。

  • 您已省略所有重要的.authorized的情況。如果您有工作要做,取決於您的授權狀態,您必須在現在(如果您被授權),但是如果您沒有確定授權後進行授權。

因此,這是一個連貫的授權檢查正確的方案(其中f()是你總是想,如果你能做到的事情):

let status = MPMediaLibrary.authorizationStatus() 
switch status { 
case .authorized: 
    f() 
case .notDetermined: 
    MPMediaLibrary.requestAuthorization() { status in 
     if status == .authorized { 
      DispatchQueue.main.async { 
       f() 
      } 
     } 
    } 
// ... 
} 

如果抽象這段代碼到公共方法,其中f可以是任何東西,您可以在您的應用程序中執行此操作,其中無處不在,其中可能需要授權 - 而不僅僅是在啓動時。

+0

完美!謝謝,是的,我沒有得到它,但我現在就做。 – EdZ

-1

感謝您的意見,它給了我這是怎麼回事了多線程的線索,我能有一個計時器呼叫解決它,如果有在課堂上沒有播放列表保持對檢查和重新加載表格數據。

override func viewWillAppear(_ animated: Bool) { 
    self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed 
    super.viewWillAppear(animated) 

    checkMediaAccess() 
    self.setupPlaylistStore() 
    tableView.reloadData() 
    if store.allPlaylists.count < 1 { 
     playlistTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector:  #selector(self.playlistTimerCall), userInfo: nil, repeats: true) 
    } 
} 

@objc func playlistTimerCall() { 
    self.setupPlaylistStore() 
    if store.allPlaylists.count > 1 { 
     tableView.reloadData() 
     playlistTimer?.invalidate() 
    } 
} 
func checkMediaAccess() { 
    let authorizationStatus = MPMediaLibrary.authorizationStatus() 
    switch authorizationStatus { 
    case .notDetermined: 
     // Show the permission prompt. 
     MPMediaLibrary.requestAuthorization({[weak self] (newAuthorizationStatus: MPMediaLibraryAuthorizationStatus) in 
      // Try again after the prompt is dismissed. 
      self?.checkMediaAccess() 
     }) 
    case .denied, .restricted: 
     // Do not use MPMediaQuery. 
     return 
    default: 
     // Proceed as usual. 
     break 
    } 
} 


func setupPlaylistStore() { 

    // purge store 
    store.clearAllPlaylists() 

    // create a query of media items in playlist 
    let myPlayListsQuery = MPMediaQuery.playlists() 
    if myPlayListsQuery.collections != nil { 
     playlists = myPlayListsQuery.collections! 
    } 

    // add playlists to MyPlaylist(s) 
    if playlists.count > 0 { 
     for index in 0...playlists.count - 1 { 
      let playlist = playlists[index] 
      store.addPlaylist(playlist: playlist as! MPMediaPlaylist) 
     } 
    } 
    var toBeRemoved = [Int]() 
    let defaults = UserDefaults.standard 
    if defaults.bool(forKey: "exclude_smart_playlists") { 
     //smart 
     for index in 0...(playlists.count - 1) { 
      let playlist = playlists[index] 
      let theAttributes = playlist.value(forProperty: MPMediaPlaylistPropertyPlaylistAttributes) as! Int 
      if theAttributes == 2 { 
       toBeRemoved.append(index) 
      } 
     } 
    } 
    if defaults.bool(forKey: "exclude_folders") { 
     //folders 
     for index in 0...(playlists.count - 1) { 
      let playlist = playlists[index] 
      let isFolder = playlist.value(forProperty: "isFolder") 
      let stringIsFolder = String("\(String(describing: isFolder))") 
      if ((stringIsFolder.range(of: "1")) != nil) { 
       toBeRemoved.append(index) 
      } 
     } 
    } 
    //sort from the last to the first so i don't reindex 
    let reverseSortedPlaylists = toBeRemoved.sorted(by: >) 

    // remove the unwanted playlists 
    for list in reverseSortedPlaylists { 
     store.removePlaylist(index: list) 
    } 
} 
+0

我完全同意這一點。這種方式使用計時器只是很簡單。我有一個顯示播放列表的應用程序,它不需要這樣的黑客。這只是按正確的順序做事的問題。也許問題出在你的'setupPlaylistStore',你沒有顯示。 – matt

+0

添加了setupPlaylistStore。我有點同意,但可以看到,在授予任何授權之前,所有內容都被調用。打開其他建議,但設置只是說未經授權(還)。 – EdZ

+0

「在授予任何授權之前所有內容都被調用」當然,但是您的工作是應對這種可能性,並且在授予授權時再次調用所有內容 - 作爲授權授權的_response授權(而不是_timer_,它只是猜測這可能發生的時間)。 – matt

相關問題