portaldacalheta.pt
  • Основен
  • Начин На Живот
  • Уеб Интерфейс
  • Ux Дизайн
  • Процес На Проектиране
Подвижен

Опростяване на използването на RESTful API и постоянството на данните в iOS с Mantle и Realm



Всеки разработчик на iOS е запознат с Core Data, обектна графика и устойчивост на Apple. Освен постоянни данни локално, рамката се предлага с множество разширени функции, като проследяване на промяна на обекта и отмяна. Тези функции, макар и полезни в много случаи, не се предлагат безплатно. Той изисква много примерни кодове, а рамката като цяло има стръмна крива на обучение.

През 2014 г. Царство , мобилна база данни, беше пусната и завладя света на разработките. Ако всичко, от което се нуждаем, е да съхраняваме данни локално, Realm е добра алтернатива. В крайна сметка не всички случаи на употреба изискват разширените функции на Core Data. Realm е изключително лесен за използване и за разлика от Core Data, изисква много малко шаблонни кодове. Той също така е безопасен за нишки и се казва, че е по-бърз от рамката за постоянство от Apple.



В повечето съвременни мобилни приложения постоянните данни решават половината от проблема. Често трябва да извличаме данни от отдалечена услуга, обикновено чрез RESTful API. Това е където Мантия влиза в игра. Това е модел с отворен код за Cocoa и Cocoa Touch. Mantle значително опростява писането на модели данни за взаимодействие с API, които използват JSON като техния формат за обмен на данни.



Realm and Mantle за iOS



В тази статия ще изградим приложение за iOS, което извлича списък със статии заедно с връзки към тях от API за търсене на статии на New York Times v2. Списъкът ще бъде извлечен с помощта на стандартна HTTP GET заявка, с модели на заявки и отговори, създадени с помощта на Mantle. Ще видим колко лесно е с Mantle да обработваме трансформации на стойности (напр. От NSDate към низ). След като данните бъдат извлечени, ние ще ги запазим локално, използвайки Realm. Всичко това с минимален код.

кога да използвате web api

RESTful API - Първи стъпки

Нека започнем със създаването на нов проект за Xcode „Master-Detail Application“ за iOS, наречен „RealmMantleTutorial“. Ще добавим рамки към него, използвайки CocoaPods. Подфайлът трябва да прилича на следното:



pod 'Mantle' pod 'Realm' pod 'AFNetworking'

След като се инсталират шушулките, можем да отворим новосъздадената MantleRealmTutorial работно пространство. Както забелязахте, известната рамка AFNetworking също е инсталирана. Ще го използваме за изпълнение на заявки към API.

Както бе споменато във въведението, New York Times предоставя отличен API за търсене на статии. За да го използвате, трябва да се регистрирате, за да получите ключ за достъп до API. Това може да стане на http://developer.nytimes.com . С API ключа в ръка сме готови да започнем с кодирането.



Преди да се задълбочим в създаването на модели на данни на Mantle, трябва да подготвим и изпълним нашия мрежов слой. Нека създадем нова група в Xcode и я наречем Мрежа. В тази група ще създадем два класа. Нека наречем първата SessionManager и се уверете, че е получено от AFHTTPSessionManager който е клас на мениджър на сесии от AFNetworking , възхитителната мрежова рамка. Нашите SessionManager class ще бъде единичен обект, който ще използваме за изпълнение на заявки за получаване на API. След като класът е създаден, моля, копирайте кода по-долу в интерфейс и файлове за изпълнение.

#import 'AFHTTPSessionManager.h' @interface SessionManager : AFHTTPSessionManager + (id)sharedManager; @end #import 'SessionManager.h' static NSString *const kBaseURL = @'http://api.nytimes.com'; @implementation SessionManager - (id)init { self = [super initWithBaseURL:[NSURL URLWithString:kBaseURL]]; if(!self) return nil; self.responseSerializer = [AFJSONResponseSerializer serializer]; self.requestSerializer = [AFJSONRequestSerializer serializer]; return self; } + (id)sharedManager { static SessionManager *_sessionManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sessionManager = [[self alloc] init]; }); return _sessionManager; } @end

Мениджърът на сесии се инициализира с основния URL, дефиниран в статиката kBaseURL променлива. Той също така ще използва JSON сериализатори на заявки и отговори.



Сега вторият клас, който ще създадем в Мрежа ще бъде извикана група APIManager . Той ще бъде извлечен от новосъздадения ни SessionManager клас. След като бъдат създадени необходимите модели данни, ние ще добавим метод към ApiManager който ще се използва за заявяване на списък със статии от API.

Общ преглед на API за търсене на статии от New York Times

Официалната документация за този отличен API е достъпна на http://developer.nytimes.com/…/article_search_api_v2 . Това, което ще направим, е да използваме следната крайна точка:



http://api.nytimes.com/svc/search/v2/articlesearch

... за извличане на статии, намерени с помощта на термин за търсене по наш избор, ограничен от период от време. Например, това, което бихме могли да направим, е да поискаме от API да върне списък на всички статии, появили се в New York Times, които имат нещо общо с баскетбола през първите седем дни на юли 2015 г. Според API документация , за да направим това, трябва да зададем следните параметри в заявката за получаване до тази крайна точка:

Параметър Стойност
Какво 'баскетбол'
начална_дата „20150701“
крайна дата „20150707“

Отговорът от API е доста сложен. По-долу е отговорът на заявка с горните параметри, ограничени само до една статия (един елемент в масива на документи) с много полета, пропуснати за яснота.



{ 'response': { 'docs': [ { 'web_url': 'http://www.nytimes.com/2015/07/04/sports/basketball/robin-lopez-and-knicks-are-close-to-a-deal.html', 'lead_paragraph': 'Lopez, a 7-foot center, joined Arron Afflalo, a 6-foot-5 guard, as the Knicks’ key acquisitions in free agency. He is expected to solidify the Knicks’ interior defense.', 'abstract': null, 'print_page': '1', 'source': 'The New York Times', 'pub_date': '2015-07-04T00:00:00Z', 'document_type': 'article', 'news_desk': 'Sports', 'section_name': 'Sports', 'subsection_name': 'Pro Basketball', 'type_of_material': 'News', '_id': '5596e7ac38f0d84c0655cb28', 'word_count': '879' } ] }, 'status': 'OK', 'copyright': 'Copyright (c) 2013 The New York Times Company. All Rights Reserved.' }

Това, което основно получаваме в отговор, са три полета. Първият се обади отговор съдържа масива документи , който от своя страна съдържа елементи, представляващи статии. Другите две полета са статус и Авторско право . Сега, когато знаем как работи API, е време да създадем модели на данни с помощта на Mantle.

Въведение в Mantle

Както бе споменато по-рано, Mantle е рамка с отворен код, която значително опростява писането на модели на данни. Нека започнем, като създадем модел на заявка за списък със статии. Нека наречем този клас ArticleListRequestModel и се уверете, че е получено от MTL Модел , което е клас, от който трябва да бъдат получени всички модели на Mantle. Освен това нека го приведем в съответствие с MTLJSONСериализиране протокол. Нашият модел за заявка трябва да има три свойства от подходящи типове: заявка, статии от дата , и articlesToDate . Само за да сме сигурни, че нашият проект е добре организиран, предлагам този клас да бъде поставен в Модели група.

Mantle опростява писането на модели с данни, намалява кода на шаблона. Tweet

Ето как интерфейсният файл на ArticleListRequestModel трябва да изглежда:

#import 'MTLModel.h' #import 'Mantle.h' @interface ArticleListRequestModel : MTLModel @property (nonatomic, copy) NSString *query; @property (nonatomic, copy) NSDate *articlesFromDate; @property (nonatomic, copy) NSDate *articlesToDate; @end

Сега, ако потърсим документите за нашата крайна точка за търсене на статии или погледнем таблицата с параметри на заявката по-горе, ще забележим, че имената на променливите в заявката за API се различават от тези в нашия модел на заявка. Mantle се справя ефективно с това, използвайки метода:

коя е добра практика за проектиране на приложения?
+ (NSDictionary *)JSONKeyPathsByPropertyKey.

Ето как трябва да се приложи този метод при изпълнението на нашия модел на заявка:

#import 'ArticleListRequestModel.h' @implementation ArticleListRequestModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @'query': @'q', @'articlesFromDate': @'begin_date', @'articlesToDate': @'end_date' }; } @end

Внедряването на този метод указва как свойствата на модела се картографират в неговите JSON представления. След като методът JSONKeyPathsByPropertyKey е реализиран, можем да получим представяне на речника на JSON на модела с метода на класа +[MTLJSONAdapter JSONArrayForModels:]

Едно нещо, което все още остава, както знаем от списъка с параметри, е, че и двата параметъра за дата трябва да бъдат във формата „ГГГГММДД“. Тук Mantle става много полезен. Можем да добавим персонализирана трансформация на стойност за всяко свойство чрез внедряване на незадължителен метод +JSONTransformer Прилагайки го, ние казваме на Mantle как стойността на конкретно JSON поле трябва да се трансформира по време на десериализацията на JSON. Можем да внедрим и обратим трансформатор, който ще се използва при създаване на JSON от модела. Тъй като трябва да трансформираме NSDate обект в низ, ние също ще използваме NSDataFormatter клас. Ето пълното изпълнение на ArticleListRequestModel клас:

#import 'ArticleListRequestModel.h' @implementation ArticleListRequestModel + (NSDateFormatter *)dateFormatter { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateFormat = @'yyyyMMdd'; return dateFormatter; } #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @'query': @'q', @'articlesFromDate': @'begin_date', @'articlesToDate': @'end_date' }; } #pragma mark - JSON Transformers + (NSValueTransformer *)articlesToDateJSONTransformer { return [MTLValueTransformer transformerUsingForwardBlock:^id(NSString *dateString, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter dateFromString:dateString]; } reverseBlock:^id(NSDate *date, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter stringFromDate:date]; }]; } + (NSValueTransformer *)articlesFromDateJSONTransformer { return [MTLValueTransformer transformerUsingForwardBlock:^id(NSString *dateString, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter dateFromString:dateString]; } reverseBlock:^id(NSDate *date, BOOL *success, NSError *__autoreleasing *error) { return [self.dateFormatter stringFromDate:date]; }]; } @end

Друга чудесна характеристика на Mantle е, че всички тези модели отговарят на NSC кодиране протокол, както и изпълнение е равно и хеш методи.

Както вече видяхме, полученият JSON от извикването на API съдържа масив от обекти, които представляват статии. Ако искаме да моделираме този отговор с помощта на Mantle, ще трябва да създадем два отделни модела на данни. Човек би моделирал обекти, представляващи статии ( документи array elements), а другият би моделирал целия JSON отговор, с изключение на елементите на масива docs. Сега не трябва да картографираме всяко свойство от входящия JSON в нашите модели на данни. Да предположим, че се интересуваме само от две полета на обекти на статии и това би било оловен_параграф и web_url . The ArticleModel class е доста лесно за изпълнение, както можем да видим по-долу.

#import 'MTLModel.h' #import @interface ArticleModel : MTLModel @property (nonatomic, copy) NSString *leadParagraph; @property (nonatomic, copy) NSString *url; @end #import 'ArticleModel.h' @implementation ArticleModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @'leadParagraph': @'lead_paragraph', @'url': @'web_url' }; } @end

Сега, когато моделът на статията е дефиниран, можем да завършим дефиницията на модел на отговор, като създадем модел за списъка със статии. Ето как ще изглежда моделът за отговор на класа ArticleList.

#import 'MTLModel.h' #import #import 'ArticleModel.h' @interface ArticleListResponseModel : MTLModel @property (nonatomic, copy) NSArray *articles; @property (nonatomic, copy) NSString *status; @end #import 'ArticleListResponseModel.h' @class ArticleModel; @implementation ArticleListResponseModel #pragma mark - Mantle JSONKeyPathsByPropertyKey + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ @'articles' : @'response.docs', @'status' : @'status' }; } #pragma mark - JSON Transformer + (NSValueTransformer *)articlesJSONTransformer { return [MTLJSONAdapter arrayTransformerWithModelClass:ArticleModel.class]; } @end

Този клас има само две свойства: статус и статии . Ако го сравним с отговора от крайната точка, ще видим, че третият JSON атрибут авторско право няма да бъде картографиран в модела на отговор. Ако разгледаме статииJSONTransformer метод, ще видим, че връща трансформатор на стойност за масив, съдържащ обекти от клас ArticleModel .

Също така си струва да се отбележи, че в метода JSONKeyPathsByPropertyKey , свойството на модела статии съответстват на масивите docs, които са вложени в атрибута JSON отговор .

Досега трябва да имаме внедрени три моделни класа: ArticleListRequestModel, ArticleModel и ArticleListResponseModel.

създаване на частен капиталов фонд

Първа заявка за API

Спокоен API

Сега, когато внедрихме всички модели на данни, е време да се върнем към класа APIManager за внедряване на метода, който ще използваме за изпълнение на GET заявки към API. Методът:

- (NSURLSessionDataTask *) getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure

отнема ArticleListRequestModel заявка модел като параметър и връща ArticleListResponseModel в случай на успех или NSError в противен случай. Прилагането на този метод използва AFNetworking да изпълни GET заявка към API. Моля, обърнете внимание, че за да направим успешна заявка за API, трябва да предоставим ключ, който може да бъде получен, както беше споменато по-рано, като се регистрирате на http://developer.nytimes.com .

#import 'SessionManager.h' #import 'ArticleListRequestModel.h' #import 'ArticleListResponseModel.h' @interface APIManager : SessionManager - (NSURLSessionDataTask *)getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure; @end #import 'APIManager.h' #import 'Mantle.h' static NSString *const kArticlesListPath = @'/svc/search/v2/articlesearch.json'; static NSString *const kApiKey = @'replace this with your own key'; @implementation APIManager - (NSURLSessionDataTask *)getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure{ NSDictionary *parameters = [MTLJSONAdapter JSONDictionaryFromModel:requestModel error:nil]; NSMutableDictionary *parametersWithKey = [[NSMutableDictionary alloc] initWithDictionary:parameters]; [parametersWithKey setObject:kApiKey forKey:@'api-key']; return [self GET:kArticlesListPath parameters:parametersWithKey success:^(NSURLSessionDataTask *task, id responseObject) { NSDictionary *responseDictionary = (NSDictionary *)responseObject; NSError *error; ArticleListResponseModel *list = [MTLJSONAdapter modelOfClass:ArticleListResponseModel.class fromJSONDictionary:responseDictionary error:&error]; success(list); } failure:^(NSURLSessionDataTask *task, NSError *error) { failure(error); }]; }

При прилагането на този метод се случват две много важни неща. Първо нека да разгледаме този ред:

NSDictionary *parameters = [MTLJSONAdapter JSONDictionaryFromModel:requestModel error:nil];

Това, което се случва тук е, че използвайки метода, предоставен от MTLJSONAdapter клас получаваме a NSD Dictionary представяне на нашия модел данни. Това представяне отразява JSON, който ще бъде изпратен до API. Тук се крие красотата на Mantle. След като се внедри JSONKeyPathsByPropertyKey и +JSONTransformer методи в класа ArticleListRequestModel, можем за нула време да получим правилното JSON представяне на нашия модел данни само с един ред код.

Mantle също ни позволява да извършваме трансформации и в другата посока. И точно това се случва с данните, получени от API. Полученият от нас NSD Dictionary се преобразува в обект на класа ArticleListResponseModel, използвайки следния метод на класа:

ArticleListResponseModel *list = [MTLJSONAdapter modelOfClass:ArticleListResponseModel.class fromJSONDictionary:responseDictionary error:&error];

Персистиращи данни с Realm

Сега, когато сме в състояние да извлечем данни от отдалечен API, е време да ги продължим. Както бе споменато във въведението, ще го направим с помощта на Realm. Realm е мобилна база данни и заместител на Core Data и SQLite. Както ще видим по-долу, той е изключително лесен за използване.

Realm, най-добрата мобилна база данни, е идеалният заместител на Core Data и SQLite. Tweet

За да запазим част от данните в Realm, първо трябва да капсулираме обект, който е получен от клас RLMObject. Това, което трябва да направим сега, е да създадем клас на модел, който да съхранява данни за отделни статии. Ето колко лесно е да създадете такъв клас.

#import 'RLMObject.h' @interface ArticleRealm : RLMObject @property NSString *leadParagraph; @property NSString *url; @end

И това може да бъде основно това, изпълнението на този клас може да остане празно. Моля, обърнете внимание, че свойствата в класа на модела нямат атрибути като неатомно, силно или копиране. Realm се грижи за тях и не е нужно да се притесняваме за тях.

Тъй като статиите, които можем да получим, са моделирани с модела Mante Член би било удобно да се инициализира ArticleRealm обекти с обекти от клас Член . За целта ще добавим initWithMantleModel метод към нашия Realm модел. Ето пълното изпълнение на ArticleRealm клас.

#import 'RLMObject.h' #import 'ArticleModel.h' @interface ArticleRealm : RLMObject @property NSString *leadParagraph; @property NSString *url; - (id)initWithMantleModel:(ArticleModel *)articleModel; @end #import 'ArticleRealm.h' @implementation ArticleRealm - (id)initWithMantleModel:(ArticleModel *)articleModel{ self = [super init]; if(!self) return nil; self.leadParagraph = articleModel.leadParagraph; self.url = articleModel.url; return self; } @end

Взаимодействаме с базата данни, използвайки обекти от клас RLM Реално . Лесно можем да получим RLM Реално обект чрез извикване на метода “[RLMRealm defaultRealm]”. Важно е да запомните, че такъв обект е валиден само в нишката, в която е създаден и не може да бъде споделен между нишките. Записването на данни в Realm е доста лесно. Едно записване или поредица от тях трябва да се извърши в рамките на транзакция за запис. Ето пример за запис в базата данни:

RLMRealm *realm = [RLMRealm defaultRealm]; ArticleRealm *articleRealm = [ArticleRealm new]; articleRealm.leadParagraph = @'abc'; articleRealm.url = @'sampleUrl'; [realm beginWriteTransaction]; [realm addObject:articleRealm]; [realm commitWriteTransaction];

Това, което се случва тук, е следното. Първо създаваме a RLM Реално обект за взаимодействие с базата данни. Тогава an ArticleRealm създава се обект на модел (моля, имайте предвид, че е получен от RLM Реално клас). И накрая, за да го запишете, започва транзакция за запис, обектът се добавя към базата данни и след като бъде запазен, транзакцията за запис е ангажирана. Както виждаме, транзакциите за запис блокират нишката, на която са извикани. Докато Realm се казва, че е много бърз, ако трябва да добавим множество обекти към базата данни в рамките на една транзакция на основната нишка, това може да доведе до това потребителският интерфейс да не реагира, докато транзакцията приключи. Естествено решение за това е да се извърши такава транзакция за запис на фонова нишка.

API заявка и постоянен отговор в сферата

Това е цялата информация, от която се нуждаем, за да продължим статиите, използващи Realm. Нека се опитаме да изпълним заявка за API, използвайки метода

- (NSURLSessionDataTask *) getArticlesWithRequestModel:(ArticleListRequestModel *)requestModel success:(void (^)(ArticleListResponseModel *responseModel))success failure:(void (^)(NSError *error))failure

и модели за искане и отговор на Mantle, за да се получат статии от Ню Йорк Таймс, които имат нещо общо (както в предишния пример) с баскетбола и са публикувани през първите седем дни на юни 2015 г. След като списъкът с такива статии е наличен, ще го упорства в царството. По-долу е кодът, който прави това. Поставя се в viewDidLoad метод на контролера за табличен изглед в нашето приложение.

стратегии за управление на валутния риск
ArticleListRequestModel *requestModel = [ArticleListRequestModel new]; // (1) requestModel.query = @'Basketball'; requestModel.articlesToDate = [[ArticleListRequestModel dateFormatter] dateFromString:@'20150706']; requestModel.articlesFromDate = [[ArticleListRequestModel dateFormatter] dateFromString:@'20150701']; [[APIManager sharedManager] getArticlesWithRequestModel:requestModel // (2) success:^(ArticleListResponseModel *responseModel){ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // (3) @autoreleasepool { RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteAllObjects]; [realm commitWriteTransaction]; [realm beginWriteTransaction]; for(ArticleModel *article in responseModel.articles){ ArticleRealm *articleRealm = [[ArticleRealm alloc] initWithMantleModel:article]; // (4) [realm addObject:articleRealm]; } [realm commitWriteTransaction]; dispatch_async(dispatch_get_main_queue(), ^{ // (5) RLMRealm *realmMainThread = [RLMRealm defaultRealm]; // (6) RLMResults *articles = [ArticleRealm allObjectsInRealm:realmMainThread]; self.articles = articles; // (7) [self.tableView reloadData]; }); } }); } failure:^(NSError *error) { self.articles = [ArticleRealm allObjects]; [self.tableView reloadData]; }];

Първо се извършва API извикване (2) с модел на заявка (1), който връща модел на отговор, който съдържа списък със статии. За да се запазят тези статии, използващи Realm, трябва да създадем обекти на Realm модел, което се извършва в цикъла for (4). Също така е важно да се отбележи, че тъй като множество обекти се запазват в рамките на една транзакция за запис, тази транзакция за запис се извършва на фонова нишка (3). След като всички статии са запазени в Realm, ние ги присвояваме на свойството на класа самостоятелни статии (7). Тъй като те ще бъдат достъпни по-късно в основната нишка в методите на източника на данни TableView, е безопасно да ги изтеглите и от базата данни Realm в основната нишка (5). Отново, за достъп до базата данни от нова нишка, трябва да се създаде нов обект RLMRealm (6) на тази нишка.

Ако получаването на нови статии от API не успее по някаква причина, съществуващите се извличат от локалното хранилище в блока за повреда.

Обобщавайки

В този урок научихме как да конфигурираме Mantle, модел на рамка за Cocoa и Cocoa Touch, за да взаимодействаме с дистанционно ПОЖАР . Също така научихме как да запазим локално данните, извлечени под формата на обекти на модел на Mantle, използвайки мобилна база данни Realm.

В случай, че искате да изпробвате това приложение, можете да извлечете изходния код от неговото хранилище на GitHub . Ще трябва да генерирате и предоставите свой собствен API ключ, преди да стартирате приложението.

Buggy CakePHP код: 6-те най-често срещани грешки, които CakePHP разработчиците правят

Технология

Buggy CakePHP код: 6-те най-често срещани грешки, които CakePHP разработчиците правят
13 подкасти, които всеки дизайнер трябва да слуша

13 подкасти, които всеки дизайнер трябва да слуша

Процес На Проектиране

Популярни Публикации
Автоматизирани Android Crash Reports с ACRA и Cloudant
Автоматизирани Android Crash Reports с ACRA и Cloudant
Шаблони за терминологични листове - клаузи, за които трябва да се внимава по време на преговорите
Шаблони за терминологични листове - клаузи, за които трябва да се внимава по време на преговорите
Elasticsearch за Ruby on Rails: Урок за дъвчащия скъпоценен камък
Elasticsearch за Ruby on Rails: Урок за дъвчащия скъпоценен камък
Често срещани грешки в комуникацията с клиенти: Как да не разочаровате клиента си
Често срещани грешки в комуникацията с клиенти: Как да не разочаровате клиента си
Състезателно машинно обучение: Как да атакувате и защитавате ML модели
Състезателно машинно обучение: Как да атакувате и защитавате ML модели
 
С байпас на филтъра и някои шестнадесетични, хакнатите номера на кредитни карти все още са все още в състояние с Google
С байпас на филтъра и някои шестнадесетични, хакнатите номера на кредитни карти все още са все още в състояние с Google
UI срещу UX - Разгледайте основните разлики (Инфографика)
UI срещу UX - Разгледайте основните разлики (Инфографика)
Характеристики на Rails 6: Какво ново и защо е важно
Характеристики на Rails 6: Какво ново и защо е важно
Убедителен дизайн: Ефективно използване на напреднала психология
Убедителен дизайн: Ефективно използване на напреднала психология
Зелено за излитане - Вътре в електрическата самолетна индустрия
Зелено за излитане - Вътре в електрическата самолетна индустрия
Популярни Публикации
  • как да напиша код
  • при вземането на бизнес решения, мениджърите обикновено разглеждат двата основни фактора:
  • научете как да кодирате в c
  • щеше да е помогнало стъклото Стигъл
  • уеб портфолиа, които използват визуална йерархия
  • javascript получава текущото време в UTC
Категории
  • Начин На Живот
  • Уеб Интерфейс
  • Ux Дизайн
  • Процес На Проектиране
  • © 2022 | Всички Права Запазени

    portaldacalheta.pt