RepositoriesViewController.m 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2014 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #import "RepositoriesViewController.h"
  19. #import "RepositoryCell.h"
  20. #import "Repository.h"
  21. @interface RepositoriesViewController () <UITextFieldDelegate>
  22. @property (nonatomic, weak) IBOutlet UISegmentedControl *sortOrderControl;
  23. @property (nonatomic, weak) IBOutlet UITextField *searchField;
  24. @property (nonatomic) RLMResults *results;
  25. @property (nonatomic) RLMNotificationToken *token;
  26. @end
  27. @implementation RepositoriesViewController
  28. - (void)dealloc {
  29. [self.token invalidate];
  30. }
  31. - (void)viewDidLoad {
  32. [super viewDidLoad];
  33. __weak typeof(self) weakSelf = self;
  34. self.token = [[RLMRealm defaultRealm] addNotificationBlock:^(NSString * _Nonnull notification, RLMRealm * _Nonnull realm) {
  35. [weakSelf reloadData];
  36. }];
  37. NSURLComponents *components = [NSURLComponents componentsWithString:@"https://api.github.com/search/repositories"];
  38. components.queryItems = @[[NSURLQueryItem queryItemWithName:@"q" value:@"language:objc"],
  39. [NSURLQueryItem queryItemWithName:@"sort" value:@"stars"],
  40. [NSURLQueryItem queryItemWithName:@"order" value:@"desc"]];
  41. [[[NSURLSession sharedSession] dataTaskWithURL:components.URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  42. if (!error) {
  43. NSError *jsonError = nil;
  44. NSDictionary *repositories = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
  45. if (!jsonError) {
  46. NSArray *items = repositories[@"items"];
  47. RLMRealm *realm = [RLMRealm defaultRealm];
  48. [realm transactionWithBlock:^{
  49. for (NSDictionary *item in items) {
  50. Repository *repository = [Repository new];
  51. repository.identifier = [NSString stringWithFormat:@"%@", item[@"id"]];
  52. repository.name = item[@"name"];
  53. repository.avatarURL = item[@"owner"][@"avatar_url"];
  54. [realm addOrUpdateObject:repository];
  55. }
  56. }];
  57. } else {
  58. NSLog(@"%@", jsonError);
  59. }
  60. } else {
  61. NSLog(@"%@", error);
  62. }
  63. }] resume];
  64. }
  65. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  66. return self.results.count;
  67. }
  68. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  69. RepositoryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
  70. Repository *repository = self.results[indexPath.item];
  71. cell.titleLabel.text = repository.name;
  72. [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:repository.avatarURL] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  73. if (!error) {
  74. dispatch_async(dispatch_get_main_queue(), ^{
  75. UIImage *image = [UIImage imageWithData:data];
  76. cell.avatarImageView.image = image;
  77. });
  78. } else {
  79. NSLog(@"%@", error);
  80. }
  81. }] resume];
  82. return cell;
  83. }
  84. - (void)reloadData {
  85. self.results = [Repository allObjects];
  86. if (self.searchField.text.length > 0) {
  87. self.results = [self.results objectsWhere:@"name contains[c] %@", self.searchField.text];
  88. }
  89. self.results = [self.results sortedResultsUsingKeyPath:@"name" ascending:self.sortOrderControl.selectedSegmentIndex == 0];
  90. [self.collectionView reloadData];
  91. }
  92. - (IBAction)valueChanged:(id)sender {
  93. [self reloadData];
  94. }
  95. - (IBAction)clearSearchField:(id)sender {
  96. self.searchField.text = nil;
  97. [self reloadData];
  98. }
  99. - (void)textFieldDidEndEditing:(UITextField *)textField {
  100. [self reloadData];
  101. }
  102. @end