iOS - 使用时出现问题 API - dispatch_async
iOS - Issue When Consuming API - dispatch_async
我试图获得 API 工作的基本原型。我有网络服务设置,现在我正在尝试让 iOS 应用程序请求数据并将其显示在 table 中。这是非常基本的,但是,数据的随机部分在 table 中显示为 null
,我无法找到一个共同的线程。
但基本上,我调用这个 API,我解析数据,我使用 StopCollection
class 到 createItem
(类型 StopItem
) 并将其添加到 StopCollection
中的 NSMutableArray
。然后在 MainTableViewController
中,我使用该数组作为数据源。
数据正确地来自 API。我可以将它添加到 NSMutableArray
就好了。但是,似乎在 MainTableViewController
中,一旦我到达以下行,我就无法再访问数组中的相同数据,并且一堆值是 null
:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
这是我正在处理的内容:
MainTableViewController.m
#import "MainTableViewController.h"
#import "StopCollection.h"
#import "StopItem.h"
@interface MainTableViewController ()
@property (nonatomic, strong) NSURLSession *session;
@end
@implementation MainTableViewController
- (instancetype)init
{
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
[self fetchFeed];
}
return self;
}
- (void)fetchFeed
{
NSString *requestString = @"http://nexttrain.dev/station?include=stopTime";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask =
[self.session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
for(NSDictionary *stop in jsonObject[@"data"])
{
for (NSDictionary *stopTime in stop[@"stopTime"][@"data"]) {
[[StopCollection sharedStore] createItem:stop[@"station"]
withRoute:stopTime[@"route"]
withHeadsign:stopTime[@"trip"]
withArrivalTime:stopTime[@"arrival_time"]];
NSLog(@"%@", stop[@"station"]);
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
[dataTask resume];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UITableViewCell"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[StopCollection sharedStore] stops] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
NSArray *allStops = [[StopCollection sharedStore] stops];
StopItem *stop = allStops[indexPath.row];
NSString *formattedText = [NSString stringWithFormat:@"%@ - %@ - %@", stop.station, stop.route, stop.arrivalTime];
cell.textLabel.text = formattedText;
cell.textLabel.font = [UIFont systemFontOfSize:12];
return cell;
}
StopCollection.m
#import "StopCollection.h"
#import "StopItem.h"
@interface StopCollection()
@property (nonatomic) NSMutableArray *privateStops;
@end
@implementation StopCollection
// Override Accessor for Stops, and return from privateStops.
- (NSArray *)stops
{
return [self.privateStops copy];
}
// Singleton Access to Object.
+ (instancetype)sharedStore
{
// Static will be Strong and will remain.
static StopCollection *sharedStore;
// Create initial instance.
if (!sharedStore) {
sharedStore = [[self alloc] initPrivate];
}
// Return instance if exists.
return sharedStore;
}
// Make defualt init inaccessible.
- (instancetype)init
{
// Throw Exception if accesssed.
[NSException raise:@"Singleton"
format:@"Use + (instancetype)sharedStore"];
return nil;
}
// Private initializer will call Super init.
- (instancetype)initPrivate
{
self = [super init];
if (self) {
_privateStops = [[NSMutableArray alloc] init];
}
return self;
}
- (void)createItem:(NSString *)station withRoute:(NSString *)route withHeadsign:(NSString *)headsign withArrivalTime:(NSString *)arrivalTime
{
StopItem *stop = [[StopItem alloc] initWithStation:station
lattitude:22
longitude:56
route:route
tripHeadsign:headsign
arrivalTime];
[self.privateStops addObject:stop];
}
@end
StopCollection.h
#import <Foundation/Foundation.h>
@interface StopCollection : NSObject
+ (instancetype)sharedStore;
@property(nonatomic, readonly, copy) NSArray *stops;
- (void)createItem:(NSString *)station
withRoute:(NSString *)route
withHeadsign:(NSString *)headsign
withArrivalTime:(NSString *)arrivalTime;
@end
StopItem.m
#import "StopItem.h"
@implementation StopItem
- (instancetype)initWithStation:(NSString *)station lattitude:(NSInteger)lattitude longitude:(NSInteger)longitude route:(NSString *)route tripHeadsign:(NSString *)headsign arrivalTime:(NSString *)arrivalTime
{
self = [super init];
if (self) {
_station = station;
_lattitude = lattitude;
_longitude = longitude;
_route = route;
_tripHeadsign = headsign;
_arrivalTime = arrivalTime;
}
return self;
}
- (instancetype)init {
return [self initWithStation:@"Hey" lattitude:0 longitude:0 route:@"" tripHeadsign:@"" arrivalTime:[[NSString alloc] init]];
}
@end
StopItem.h
@interface StopItem : NSObject
@property (nonatomic, weak) NSString *station;
@property (nonatomic) NSInteger lattitude;
@property (nonatomic) NSInteger longitude;
@property (nonatomic, weak) NSString *route;
@property (nonatomic, weak) NSString *tripHeadsign;
@property (nonatomic, weak) NSString *arrivalTime;
- (instancetype)initWithStation:(NSString *)station
lattitude:(NSInteger)lattitude
longitude:(NSInteger)longitude
route:(NSString *)route
tripHeadsign:(NSString *)headsign
arrivalTime:(NSString *)arrivalTime;
@end
这是我正在使用的 JSON 数据集:
{
"data":[
{
"station":"2 Av",
"lattitude":"40.723402",
"longitude":"-73.989938",
"stopTime":{
"data":[
{
"arrival_time":"02:40:30",
"trip":"JAMAICA - 179 ST",
"route":"some longer word with a -"
}
]
}
},
{
"station":"2 Av",
"lattitude":"40.723402",
"longitude":"-73.989938",
"stopTime":{
"data":[
{
"arrival_time":"00:54:00",
"trip":"CONEY ISLAND - STILLWELL AV",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Delancey St",
"lattitude":"40.718611",
"longitude":"-73.988114",
"stopTime":{
"data":[
{
"arrival_time":"02:39:00",
"trip":"JAMAICA - 179 ST",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Delancey St",
"lattitude":"40.718611",
"longitude":"-73.988114",
"stopTime":{
"data":[
{
"arrival_time":"00:55:30",
"trip":"CONEY ISLAND - STILLWELL AV",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Essex St",
"lattitude":"40.718315",
"longitude":"-73.987437",
"stopTime":{
"data":[
{
"arrival_time":"01:23:30",
"trip":"JAMAICA CENTER - PARSONS/ARCHER",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Essex St",
"lattitude":"40.718315",
"longitude":"-73.987437",
"stopTime":{
"data":[
{
"arrival_time":"00:52:30",
"trip":"BROAD ST",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Bowery",
"lattitude":"40.72028",
"longitude":"-73.993915",
"stopTime":{
"data":[
{
"arrival_time":"01:22:00",
"trip":"JAMAICA CENTER - PARSONS/ARCHER",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Bowery",
"lattitude":"40.72028",
"longitude":"-73.993915",
"stopTime":{
"data":[
{
"arrival_time":"00:54:00",
"trip":"BROAD ST",
"route":"some longer word with a -"
}
]
}
}
]
}
这与 dispatch
无关。这是因为你有 weak
属性,只要有可能就会被取消,即当没有引用持有它们时。在您的 StopItem
模型中将 weak
更改为 strong
或 copy
,一切都会起作用。
我试图获得 API 工作的基本原型。我有网络服务设置,现在我正在尝试让 iOS 应用程序请求数据并将其显示在 table 中。这是非常基本的,但是,数据的随机部分在 table 中显示为 null
,我无法找到一个共同的线程。
但基本上,我调用这个 API,我解析数据,我使用 StopCollection
class 到 createItem
(类型 StopItem
) 并将其添加到 StopCollection
中的 NSMutableArray
。然后在 MainTableViewController
中,我使用该数组作为数据源。
数据正确地来自 API。我可以将它添加到 NSMutableArray
就好了。但是,似乎在 MainTableViewController
中,一旦我到达以下行,我就无法再访问数组中的相同数据,并且一堆值是 null
:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
这是我正在处理的内容:
MainTableViewController.m
#import "MainTableViewController.h"
#import "StopCollection.h"
#import "StopItem.h"
@interface MainTableViewController ()
@property (nonatomic, strong) NSURLSession *session;
@end
@implementation MainTableViewController
- (instancetype)init
{
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
[self fetchFeed];
}
return self;
}
- (void)fetchFeed
{
NSString *requestString = @"http://nexttrain.dev/station?include=stopTime";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask =
[self.session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
for(NSDictionary *stop in jsonObject[@"data"])
{
for (NSDictionary *stopTime in stop[@"stopTime"][@"data"]) {
[[StopCollection sharedStore] createItem:stop[@"station"]
withRoute:stopTime[@"route"]
withHeadsign:stopTime[@"trip"]
withArrivalTime:stopTime[@"arrival_time"]];
NSLog(@"%@", stop[@"station"]);
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
[dataTask resume];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UITableViewCell"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[StopCollection sharedStore] stops] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
NSArray *allStops = [[StopCollection sharedStore] stops];
StopItem *stop = allStops[indexPath.row];
NSString *formattedText = [NSString stringWithFormat:@"%@ - %@ - %@", stop.station, stop.route, stop.arrivalTime];
cell.textLabel.text = formattedText;
cell.textLabel.font = [UIFont systemFontOfSize:12];
return cell;
}
StopCollection.m
#import "StopCollection.h"
#import "StopItem.h"
@interface StopCollection()
@property (nonatomic) NSMutableArray *privateStops;
@end
@implementation StopCollection
// Override Accessor for Stops, and return from privateStops.
- (NSArray *)stops
{
return [self.privateStops copy];
}
// Singleton Access to Object.
+ (instancetype)sharedStore
{
// Static will be Strong and will remain.
static StopCollection *sharedStore;
// Create initial instance.
if (!sharedStore) {
sharedStore = [[self alloc] initPrivate];
}
// Return instance if exists.
return sharedStore;
}
// Make defualt init inaccessible.
- (instancetype)init
{
// Throw Exception if accesssed.
[NSException raise:@"Singleton"
format:@"Use + (instancetype)sharedStore"];
return nil;
}
// Private initializer will call Super init.
- (instancetype)initPrivate
{
self = [super init];
if (self) {
_privateStops = [[NSMutableArray alloc] init];
}
return self;
}
- (void)createItem:(NSString *)station withRoute:(NSString *)route withHeadsign:(NSString *)headsign withArrivalTime:(NSString *)arrivalTime
{
StopItem *stop = [[StopItem alloc] initWithStation:station
lattitude:22
longitude:56
route:route
tripHeadsign:headsign
arrivalTime];
[self.privateStops addObject:stop];
}
@end
StopCollection.h
#import <Foundation/Foundation.h>
@interface StopCollection : NSObject
+ (instancetype)sharedStore;
@property(nonatomic, readonly, copy) NSArray *stops;
- (void)createItem:(NSString *)station
withRoute:(NSString *)route
withHeadsign:(NSString *)headsign
withArrivalTime:(NSString *)arrivalTime;
@end
StopItem.m
#import "StopItem.h"
@implementation StopItem
- (instancetype)initWithStation:(NSString *)station lattitude:(NSInteger)lattitude longitude:(NSInteger)longitude route:(NSString *)route tripHeadsign:(NSString *)headsign arrivalTime:(NSString *)arrivalTime
{
self = [super init];
if (self) {
_station = station;
_lattitude = lattitude;
_longitude = longitude;
_route = route;
_tripHeadsign = headsign;
_arrivalTime = arrivalTime;
}
return self;
}
- (instancetype)init {
return [self initWithStation:@"Hey" lattitude:0 longitude:0 route:@"" tripHeadsign:@"" arrivalTime:[[NSString alloc] init]];
}
@end
StopItem.h
@interface StopItem : NSObject
@property (nonatomic, weak) NSString *station;
@property (nonatomic) NSInteger lattitude;
@property (nonatomic) NSInteger longitude;
@property (nonatomic, weak) NSString *route;
@property (nonatomic, weak) NSString *tripHeadsign;
@property (nonatomic, weak) NSString *arrivalTime;
- (instancetype)initWithStation:(NSString *)station
lattitude:(NSInteger)lattitude
longitude:(NSInteger)longitude
route:(NSString *)route
tripHeadsign:(NSString *)headsign
arrivalTime:(NSString *)arrivalTime;
@end
这是我正在使用的 JSON 数据集:
{
"data":[
{
"station":"2 Av",
"lattitude":"40.723402",
"longitude":"-73.989938",
"stopTime":{
"data":[
{
"arrival_time":"02:40:30",
"trip":"JAMAICA - 179 ST",
"route":"some longer word with a -"
}
]
}
},
{
"station":"2 Av",
"lattitude":"40.723402",
"longitude":"-73.989938",
"stopTime":{
"data":[
{
"arrival_time":"00:54:00",
"trip":"CONEY ISLAND - STILLWELL AV",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Delancey St",
"lattitude":"40.718611",
"longitude":"-73.988114",
"stopTime":{
"data":[
{
"arrival_time":"02:39:00",
"trip":"JAMAICA - 179 ST",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Delancey St",
"lattitude":"40.718611",
"longitude":"-73.988114",
"stopTime":{
"data":[
{
"arrival_time":"00:55:30",
"trip":"CONEY ISLAND - STILLWELL AV",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Essex St",
"lattitude":"40.718315",
"longitude":"-73.987437",
"stopTime":{
"data":[
{
"arrival_time":"01:23:30",
"trip":"JAMAICA CENTER - PARSONS/ARCHER",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Essex St",
"lattitude":"40.718315",
"longitude":"-73.987437",
"stopTime":{
"data":[
{
"arrival_time":"00:52:30",
"trip":"BROAD ST",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Bowery",
"lattitude":"40.72028",
"longitude":"-73.993915",
"stopTime":{
"data":[
{
"arrival_time":"01:22:00",
"trip":"JAMAICA CENTER - PARSONS/ARCHER",
"route":"some longer word with a -"
}
]
}
},
{
"station":"Bowery",
"lattitude":"40.72028",
"longitude":"-73.993915",
"stopTime":{
"data":[
{
"arrival_time":"00:54:00",
"trip":"BROAD ST",
"route":"some longer word with a -"
}
]
}
}
]
}
这与 dispatch
无关。这是因为你有 weak
属性,只要有可能就会被取消,即当没有引用持有它们时。在您的 StopItem
模型中将 weak
更改为 strong
或 copy
,一切都会起作用。