我如何让数据管理器告诉 View Controller 重新加载集合
How do I have data manager tell View Controller to reload collection
抱歉,如果我说的任何内容完全错误,但我是 swift 的新手。
我有一个包含 uicollectionsview 的 UIViewController。然后我有一个数据管理器,它从 instagram 获取 json 数据,然后解析它。我想知道的是如何让数据管理器告诉 ViewController 重新加载集合视图中的数据。每次我让数据管理器告诉 ViewController 重新加载数据时,它都会给我一个错误,说它是零。我在想这是因为数据管理器正在创建一个全新的视图控制器实例,所以我使用单例设计模式来尝试让它工作。但是,由于某种原因,当我使用 .instance 时它崩溃了。我把那部分注释掉了。
我也试过使用线程来让它工作,但还是不行。
我知道不是没有信息,因为我在视图控制器中有一个按钮,按下时会重新加载集合视图,然后所有数据都会加载到集合视图中。
我也尝试过其他一些方法,但没有任何效果。
下面是 ViewController 的代码:
class InstagramControllerView: UIViewController, MWPhotoBrowserDelegate, UICollectionViewDelegate {
class var sharedInstance : InstagramControllerView {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : InstagramControllerView? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = InstagramControllerView()
}
return Static.instance!
}
//OUTLETS
@IBOutlet weak var collectionView: UICollectionView!
//let navigationController = InstagramNavigationController()
/* this will hold all of the information
** pertaining to this instagram account
*/
//let instagramHeader = InstagramHeader()
var nextUrl = ""
var dataManagerDone: Bool = false
let instagramDataManager = InstagramDataManager()
//arrays to hold instagram content
var headerResults: JSON?
var results: [JSON]? = []
var photos: [MWPhoto] = []
var thumbnailArr: [String] = []
var standardResArr: [String] = []
var descriptionArr: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
// self.collectionView.reloadData()
// let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
// dispatch_async(dispatch_get_global_queue(priority, 0), {
// self.instagramDataManager.getProfileInfoJson(self.profileUrlPath)
// let thum = self.instagramDataManager.getImageDataJson(self.photoUrlPath)
// dispatch_async(dispatch_get_main_queue(), {
// println("this is thumb \(thum)")
// self.collectionView.reloadData()
// println("i made it to view laod")
// })
// })
}
@IBAction func refresh(sender: UIButton) {
self.refreshCollectionView()
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
var bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
if (bottomEdge >= scrollView.contentSize.height) {
instagramDataManager.getNextSetOfImages()
}
}
func refreshCollectionView(){
self.collectionView.reloadData()
}
现在是数据管理器:
class InstagramDataManager {
var profilePictureURL: NSURL?
var postCount: String?
var followerCount: String?
var followingCount: String?
var username: String?
var bio: String?
var website: String?
var doneParsingProfile: Bool = false
var doneParsingImage: Bool = false
//arrays to hold instagram content
var results: [JSON]? = []
var thumbnailArr: [String] = []
var standardResArr: [MWPhoto] = []
var descriptionArr: [String] = []
let profileUrlPath = "https://api.instagram.com/v1/users/22755819/?access_token=fdasf"
let photoUrlPath = "https://api.instagram.com/v1/users/22755819/media/recent/?count=65&access_token=jdkfjs"
var nextUrl = ""
init(){
self.getProfileInfoJson(profileUrlPath)
self.getImageDataJson(photoUrlPath)
}
//returns true when done
func getProfileInfoJson(urlPath: String) -> Bool {
Alamofire.request(.GET, urlPath).responseJSON { (request, response, json, error) in
if json != nil {
var jsonObj = JSON(object: json!)
self.parseProfileData(jsonObj)
}
}
return true
}
//returns true when done
func getImageDataJson(urlPath: String){
Alamofire.request(.GET, urlPath).responseJSON { (request, response, json, error) in
if json != nil{
var jsonObj = JSON(object: json!)
if let data = jsonObj["data"].arrayValue as [JSON]? {
self.results? += data
self.parseImageData(data)
}
if let paginationUrl = jsonObj["pagination"]["next_url"].stringValue? {
self.nextUrl = paginationUrl
}else{
self.nextUrl = ""
}
}
}
}
private func parseImageData(jsonData: [JSON]){
for i in 0..<jsonData.count{
if let thumbnail = jsonData[i]["images"]["thumbnail"]["url"].stringValue? {
self.thumbnailArr.append(thumbnail)
}
if let standardResPhoto = jsonData[i]["images"]["standard_resolution"]["url"].stringValue? {
self.standardResArr.append(MWPhoto(URL: NSURL(string: standardResPhoto)))
}
if let description = jsonData[i]["caption"]["text"].stringValue? {
self.standardResArr[i].caption = description
}
}
self.doneParsingImage = true
doneParsing()
}
private func parseProfileData(json: JSON){
if let photoUrl = json["data"]["profile_picture"].stringValue? {
self.profilePictureURL = NSURL(string: photoUrl)
}
if let postCount = json["data"]["counts"]["media"].stringValue? {
self.postCount = postCount
}
if let follows = json["data"]["counts"]["follows"].stringValue? {
self.followingCount = follows
}
if let followers = json["data"]["counts"]["followed_by"].stringValue? {
self.followerCount = followers
}
if let username = json["data"]["username"].stringValue? {
self.username = username
}
if let bio = json["data"]["bio"].stringValue? {
self.bio = bio
}
if let website = json["data"]["website"].stringValue? {
self.website = website
}
self.doneParsingProfile = true
doneParsing()
}
//reload collection view once both image and profile have been parsed
private func doneParsing(){
if self.doneParsingImage && self.doneParsingProfile {
//InstagramControllerView.sharedInstance.collectionView.reloadData()
}
}
我显然遗漏了一些不必要的代码。
我将不胜感激任何能得到的帮助。提前致谢
所以基本上不是试图获取集合视图并刷新它,而是希望您的 InstagramVC 为 DataManager 提供一个块以在接收数据时执行。这样任何对象都可以请求 Instagram 数据。 Instagram 管理器不应专门绑定到任何控制器。所以要做到这一点,你首先需要在请求数据时传递一个代码块:
func getImageDataJson(urlPath: String, completion: () -> ()) {
Alamofire.request(.GET, urlPath).responseJSON { (request, response, json, error) in
if json != nil {
var jsonObj = JSON(object: json!)
if let data = jsonObj["data"].arrayValue as [JSON]? {
self.results? += data
self.parseImageData(data)
}
// Not sure where you want this but let's just execute the block here
completion()
if let paginationUrl = jsonObj["pagination"]["next_url"].stringValue? {
self.nextUrl = paginationUrl
} else {
self.nextUrl = ""
}
}
}
}
然后在请求数据时,只要传入一个你希望在数据返回后执行的片段:
self.instagramDataManager.getProfileInfoJson(self.profileUrlPath) {
// Upon completion of receiving data refresh my collection view
self.collectionView.reloadData()
}
大功告成。然后删除所有与单例有关的东西!!!
抱歉,如果我说的任何内容完全错误,但我是 swift 的新手。
我有一个包含 uicollectionsview 的 UIViewController。然后我有一个数据管理器,它从 instagram 获取 json 数据,然后解析它。我想知道的是如何让数据管理器告诉 ViewController 重新加载集合视图中的数据。每次我让数据管理器告诉 ViewController 重新加载数据时,它都会给我一个错误,说它是零。我在想这是因为数据管理器正在创建一个全新的视图控制器实例,所以我使用单例设计模式来尝试让它工作。但是,由于某种原因,当我使用 .instance 时它崩溃了。我把那部分注释掉了。
我也试过使用线程来让它工作,但还是不行。
我知道不是没有信息,因为我在视图控制器中有一个按钮,按下时会重新加载集合视图,然后所有数据都会加载到集合视图中。
我也尝试过其他一些方法,但没有任何效果。
下面是 ViewController 的代码:
class InstagramControllerView: UIViewController, MWPhotoBrowserDelegate, UICollectionViewDelegate {
class var sharedInstance : InstagramControllerView {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : InstagramControllerView? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = InstagramControllerView()
}
return Static.instance!
}
//OUTLETS
@IBOutlet weak var collectionView: UICollectionView!
//let navigationController = InstagramNavigationController()
/* this will hold all of the information
** pertaining to this instagram account
*/
//let instagramHeader = InstagramHeader()
var nextUrl = ""
var dataManagerDone: Bool = false
let instagramDataManager = InstagramDataManager()
//arrays to hold instagram content
var headerResults: JSON?
var results: [JSON]? = []
var photos: [MWPhoto] = []
var thumbnailArr: [String] = []
var standardResArr: [String] = []
var descriptionArr: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
// self.collectionView.reloadData()
// let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
// dispatch_async(dispatch_get_global_queue(priority, 0), {
// self.instagramDataManager.getProfileInfoJson(self.profileUrlPath)
// let thum = self.instagramDataManager.getImageDataJson(self.photoUrlPath)
// dispatch_async(dispatch_get_main_queue(), {
// println("this is thumb \(thum)")
// self.collectionView.reloadData()
// println("i made it to view laod")
// })
// })
}
@IBAction func refresh(sender: UIButton) {
self.refreshCollectionView()
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
var bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
if (bottomEdge >= scrollView.contentSize.height) {
instagramDataManager.getNextSetOfImages()
}
}
func refreshCollectionView(){
self.collectionView.reloadData()
}
现在是数据管理器:
class InstagramDataManager {
var profilePictureURL: NSURL?
var postCount: String?
var followerCount: String?
var followingCount: String?
var username: String?
var bio: String?
var website: String?
var doneParsingProfile: Bool = false
var doneParsingImage: Bool = false
//arrays to hold instagram content
var results: [JSON]? = []
var thumbnailArr: [String] = []
var standardResArr: [MWPhoto] = []
var descriptionArr: [String] = []
let profileUrlPath = "https://api.instagram.com/v1/users/22755819/?access_token=fdasf"
let photoUrlPath = "https://api.instagram.com/v1/users/22755819/media/recent/?count=65&access_token=jdkfjs"
var nextUrl = ""
init(){
self.getProfileInfoJson(profileUrlPath)
self.getImageDataJson(photoUrlPath)
}
//returns true when done
func getProfileInfoJson(urlPath: String) -> Bool {
Alamofire.request(.GET, urlPath).responseJSON { (request, response, json, error) in
if json != nil {
var jsonObj = JSON(object: json!)
self.parseProfileData(jsonObj)
}
}
return true
}
//returns true when done
func getImageDataJson(urlPath: String){
Alamofire.request(.GET, urlPath).responseJSON { (request, response, json, error) in
if json != nil{
var jsonObj = JSON(object: json!)
if let data = jsonObj["data"].arrayValue as [JSON]? {
self.results? += data
self.parseImageData(data)
}
if let paginationUrl = jsonObj["pagination"]["next_url"].stringValue? {
self.nextUrl = paginationUrl
}else{
self.nextUrl = ""
}
}
}
}
private func parseImageData(jsonData: [JSON]){
for i in 0..<jsonData.count{
if let thumbnail = jsonData[i]["images"]["thumbnail"]["url"].stringValue? {
self.thumbnailArr.append(thumbnail)
}
if let standardResPhoto = jsonData[i]["images"]["standard_resolution"]["url"].stringValue? {
self.standardResArr.append(MWPhoto(URL: NSURL(string: standardResPhoto)))
}
if let description = jsonData[i]["caption"]["text"].stringValue? {
self.standardResArr[i].caption = description
}
}
self.doneParsingImage = true
doneParsing()
}
private func parseProfileData(json: JSON){
if let photoUrl = json["data"]["profile_picture"].stringValue? {
self.profilePictureURL = NSURL(string: photoUrl)
}
if let postCount = json["data"]["counts"]["media"].stringValue? {
self.postCount = postCount
}
if let follows = json["data"]["counts"]["follows"].stringValue? {
self.followingCount = follows
}
if let followers = json["data"]["counts"]["followed_by"].stringValue? {
self.followerCount = followers
}
if let username = json["data"]["username"].stringValue? {
self.username = username
}
if let bio = json["data"]["bio"].stringValue? {
self.bio = bio
}
if let website = json["data"]["website"].stringValue? {
self.website = website
}
self.doneParsingProfile = true
doneParsing()
}
//reload collection view once both image and profile have been parsed
private func doneParsing(){
if self.doneParsingImage && self.doneParsingProfile {
//InstagramControllerView.sharedInstance.collectionView.reloadData()
}
}
我显然遗漏了一些不必要的代码。
我将不胜感激任何能得到的帮助。提前致谢
所以基本上不是试图获取集合视图并刷新它,而是希望您的 InstagramVC 为 DataManager 提供一个块以在接收数据时执行。这样任何对象都可以请求 Instagram 数据。 Instagram 管理器不应专门绑定到任何控制器。所以要做到这一点,你首先需要在请求数据时传递一个代码块:
func getImageDataJson(urlPath: String, completion: () -> ()) {
Alamofire.request(.GET, urlPath).responseJSON { (request, response, json, error) in
if json != nil {
var jsonObj = JSON(object: json!)
if let data = jsonObj["data"].arrayValue as [JSON]? {
self.results? += data
self.parseImageData(data)
}
// Not sure where you want this but let's just execute the block here
completion()
if let paginationUrl = jsonObj["pagination"]["next_url"].stringValue? {
self.nextUrl = paginationUrl
} else {
self.nextUrl = ""
}
}
}
}
然后在请求数据时,只要传入一个你希望在数据返回后执行的片段:
self.instagramDataManager.getProfileInfoJson(self.profileUrlPath) {
// Upon completion of receiving data refresh my collection view
self.collectionView.reloadData()
}
大功告成。然后删除所有与单例有关的东西!!!