我应该在哪里准备我的数据?在awakeFromNib,viewDidLoad或其他内容中

时间:2013-12-22 23:18:51

标签: ios objective-c uiviewcontroller initialization

我仍然相对较新的iOS编程。这是一个困扰我很长时间的问题。

因此,在其中一个视图控制器中,在将此视图控制器推入导航项之前,我在前一个视图控制器的prepareForSegue中向其传递一个参数,例如userId。当此视图控制器基于前一个视图控制器的userId加载(初始化)时,我正在进行网络调用以获取与该用户相关的信息列表,然后将此信息填充到模型中。当前的视图控制器。

我应该把这个数据准备的逻辑放在哪里?

3 个答案:

答案 0 :(得分:1)

- (void) viewDidLoad {
    [super viewDidLoad]; 
    // initialize stuff
}

虽然,最好进行网络调用并将所有这些信息收集到包含所有信息的自定义类中,然后执行segue。然后,您需要在新视图控制器中执行的操作是从对象中提取数据(这仍将在viewDidLoad中完成)。

可以说,这种方法可能更好,因为如果网络出现问题,您可以显示错误消息,然后不执行segue,让用户更轻松地重新尝试相同的操作,或者至少他们会离开应用程序以检查网络设置并返回后,在页面上重新尝试相同的操作。

当然,如果出现网络错误,你可以一直向前推进,然后向后移动,但我认为这看起来很蹩脚。

另外,值得注意的是,如果您使用UICollectionViewUITableView来展示信息,那么呈现逻辑可以(应该)移出viewDidLoad并进入集合/表数据源方法。

答案 1 :(得分:1)

使用viewDidLoad:应该可以正常使用故事板,因为故事板不会重复使用视图控制器。无论如何,为了我的视图控制器使用场景的完整性,我倾向于使用这种模式:

  • 开始在viewWillAppear:
  • 中异步加载远程数据
  • 停止在viewWillDisappear:
  • 中加载远程数据

这可确保您的数据始终更新为当前userId,因为ID可能会在viewDidLoad之后更改,例如如果在设置.view之前视图控制器重用或访问userId属性。

您还应该跟踪您的数据是否已加载。例如,您可以创建名为_isDataLoaded的私有布尔字段,在完成加载数据时将其设置为true,并在取消加载数据或设置新false时将其设置为userId

总结一下,我的想法中的模式应该是这样的:

@interface UserViewControler : UIViewController {
    bool _isDataLoaded;
    NSURLConnection _dataConnection;
}

@implementation UserViewController

-(void) setUserId:(int)userId {
    if (_userId != userId) {
        _userId = userId;
        _isDataLoaded = false;
    }
}

-(void) viewWillAppear:(BOOL)animated {
    if (!_isDataLoaded) {
        _dataConnection = // init data connection here
        _dataConnection.delegate = self;
        [_dataConnection start];
    }
}

-(void) viewWillDisappear:(BOOL)animated {
    if (_dataConnection) {
        [_dataConnection cancel];
        _dataConnection = nil;
        _isDataLoaded = false;
    }
}

// NSURLConnection call this when finish
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    _isDataLoaded = true;
    _dataConnection = nil;
}

// NSURLConnection call this when fail to load data
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    _isDataLoaded = false;
    _dataConnection = nil;
}

这取决于您使用什么框架从远程服务器检索数据,但模式应该是这样的。这将确保:

  • 只有在视图显示时才会加载数据。
  • 视图控制器在消失后不会加载更多数据。
  • 如果userId相同,则不会再次下载数据。
  • 支持视图控制器重用。

答案 2 :(得分:0)

我过去所做的是制作自定义初始化程序。

+(instancetype)initWithUserID:(NSString)userID;

以下是实施示例。

+(instancetype)initWithUserID:(NSString *)userID {
    return [[self alloc] initWithUserID:userID];
}

-(id)initWithUserID:(NSString *)userID {
    self = [self initWithNibName:@"TheNameOfTheNib" bundle:nil];
    if(self) {
        _userID = userID;
    }
    //do something with _userID here. 
    //example: start loading content from API
    return self;
}

-(void)viewDidLoad {
//or do something with userID here instead.
}

我建议的另一件事是创建一个加载数据并使用块的自定义类。

然后你可以做这样的事情

[API loadDataForUserID:userID withCompletionBlock^(NSArray *blockArray) {
     //in this case I changed initWithUserID to initWithUsers
     [self.navigationController pushViewController:[NextController initWithUsers:blockArray] animated:YES];
}