以下Objective-C代码在 UICollectionView的委托(这就是我想要的)之前处理NSURLSession代码(通过viewDidLoad()):
--- Session ---
--- Session ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
--- {CellForItemAtIndexPath} ---
注意:上面的调试消息是在各自的break属性中进行的。
删节 Objective-C代码:
@interface MainViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray *downloaders;
@property (nonatomic, strong) NSArray *photoInfos;
@end
@implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self fetchFlickrPhotoWithSearchString:@"Ric"];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (_currentImageDownloader) {
[_downloaders replaceObjectAtIndex:_selectedItemIndex withObject:_currentImageDownloader];
}
}
// -----------------------------------------------------------------------------------------------------------------------
#pragma mark -
- (void)fetchFlickrPhotoWithSearchString:(NSString *)searchString {
SimpleFlickrAPI *flickr = [SimpleFlickrAPI new];
[[[NSURLSession sharedSession] dataTaskWithURL:[flickr getURLForString:@"Ric"]
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (!error) {
NSString *string = [flickr stringByRemovingFlickrJavaScript:data];
NSData *jsonData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&error];
self.photoInfos = [[jsonDict objectForKey:@"photos"] objectForKey:@"photo"];
NSMutableArray *downloaders = [[NSMutableArray alloc] initWithCapacity:[_photoInfos count]];
for (NSInteger index = 0; index < [_photoInfos count]; index++) {
ImageDownloader *downloader = [[ImageDownloader alloc] initWithDict:_photoInfos[index]];
[downloaders addObject:downloader];
}
self.downloaders = downloaders; // ...link local array with instance array 'downloaders' (Note: same object!).
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
} else {
NSLog(@"*** {SessionDataError}: %@",error);
// ...Handle Error.
}
}] resume];
}
// -----------------------------------------------------------------------------------------------------------------------
#pragma mark - UICollectionViewDelegate methods
// ...to be implemented later.
// -----------------------------------------------------------------------------------------------------------------------
#pragma mark - UICollectionViewDataSource methods
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.photoInfos count];
}
// -----------------------------------------------------------------------------------------------------------------------
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PhotoCell" forIndexPath:indexPath];
...
...
return cell;
}
...
@end
<小时/> 但是......斯威夫特的处理模式不同。 UIControllerView的数据源委托方法是NSURLSession的先行过程:
--- {UICollectionView numberOfItems...} ---
--- {cellForItemAtIndexPath} ---
--- {cellForItemAtIndexPath} ---
--- {cellForItemAtIndexPath} ---
--- {cellForItemAtIndexPath} ---
--- {cellForItemAtIndexPath} ---
--- {session} ---
--- {session} ---
这是Swift'等效'代码:
import UIKit
var gPhotoData:Array<Dictionary<String,AnyObject>>?
var gDownloaders:NSMutableArray = NSMutableArray()
var currentImageDownloader:ImageDownloader?
var gSelectedItemIndex:Int?
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
fetchFlickrPhotoWithSearchString("Ric");
}
// -----------------------------------------------------------------------------------------------------
// MARK: -
func fetchFlickrPhotoWithSearchString(searchString:String) {
let url = getURLForString("Ric")
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
if let httpRes = response as? NSHTTPURLResponse {
if httpRes.statusCode == 200 {
let string = stringByRemovingFlickrJavaScriptFromData(data)
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
let JSON: AnyObject? = NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments, error: nil)
let rawDataDict = JSON as Dictionary<String,AnyObject>!
let photos: AnyObject? = rawDataDict["photos"]
gPhotoData = (photos!["photo"] as Array<Dictionary<String,AnyObject>>)
let myCount = (gPhotoData!.count - 1)
for index in 0...myCount {
let smirf = gPhotoData![index]
let downloader:ImageDownloader = ImageDownloader(dict: smirf)
gDownloaders.addObject(downloader)
}
dispatch_async(dispatch_get_main_queue(), {
// ...do something.
})
}
}
}
task.resume()
} // ...end class ViewController().
// =======================================================================================================================
// MARK: - Action Methods
@IBAction func exitAction(sender: AnyObject) {
exit(0)
}
}
// =======================================================================================================================
extension ViewController: UICollectionViewDataSource {
// -----------------------------------------------------------------------------------------------------
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let anyData = gPhotoData {
return gPhotoData!.count
}
return 5 //...arbitrary number to avoid crashing.
}
// -----------------------------------------------------------------------------------------------------
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: AnyObject = collectionView.dequeueReusableCellWithReuseIdentifier("photoCell", forIndexPath:indexPath)
let photoImageView = cell.viewWithTag!(1) as UIImageView
...
...
return cell as UICollectionViewCell
}
}
注意:上面的调试消息是在各自的break属性中进行的。
问题:如何在启动UIViewController的委托方法之前完成NSURLSession / Swift的启动(如在Objective-C版本中那样)?
答案 0 :(得分:0)
如果你的目标是在通过会话检索后在collectionView中显示数据,为什么不在你的dispatch_main_queue中调用collectionView.reloadData()
?
为了避免numberOfRows中的崩溃,请不要强制取消数组,但要对可选项return anyData.count
执行操作。只有当anyData不是nil并且在可选的un-wrapping之后返回0应该没问题时,它才会调用此代码。