Разбор задач квалификации: Mobile
iOS
7. Какие особенности стоит учитывать при переопределении метода - [NSObject (BOOL)respondsToSelector:(SEL)aSelector]?
- Результат может быть закеширован системой;
- есть особенности с вызовом super;
- все вышеперечисленные;
- ничего из перечисленного.
Внутри ObjC runtime система может закешировать результат предыдущего запроса к этому классу (объекту класса).
// inst is an instance of cls or a subclass thereof, or nil if none is known.
// Non-nil inst is faster in some cases. See lookUpImpOrForward() for details.
bool class_respondsToSelector_inst(Class cls, SEL sel, id inst)
{
IMP imp;
if (!sel || !cls) return NO;
// Avoids +initialize because it historically did so.
// We're not returning a callable IMP anyway.
imp = lookUpImpOrNil(cls, sel, inst,
NO/*initialize*/, YES/*cache*/, YES/*resolver*/);
return bool(imp);
}Правильный ответ — результат может быть закеширован системой.
17. Что произойдёт с кодом?
- (void)viewDidLoad {
UILabel *label = nil;
@autoreleasepool {
label = [[UILabel alloc] init];
}
__weak typeof(label) wlabel = label;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self addSubview:wlabel];
}];
}- Не скомпилируется;
- произойдёт ошибка в runtime;
- всё хорошо;
- текст поменяется сразу.
В данной реализации self является объектом класса UIViewController, который, в свою очередь, не имеет метода:
- (void)addSubview:(UIView *)subview;
Правильный ответ — не скомпилируется.
26. Что выведется в консоли?
@interface A : NSObject
@property (nonatomic, assign, readonly) BOOL toggle;
@end
@implementation A
@end
@interface B : A
@property (nonatomic, assign) BOOL toggle;
@end
@implementation B
@dynamic toggle;
@end
int main(int argc, char * argv[]) {
B *b = [[B alloc] init];
b.toggle = YES;
NSLog(@"%d", b.toggle);
return 0;
}- 0;
- 1;
- ничего;
- ошибка в runtime.
Мы перегрузили property toggle у класса B, наследника класса A, и в объявлении сказали, что у него есть setter, в отличие от класса родителя, который имеет только getter. Директива @dynamic говорит компилятору: «Верь мне, всё есть у одного из классов родителей» — и, соответственно, не генерирует ни setter, ни getter. При компиляции ошибки не будет, но в момент выполнения мы получим «unrecognized selector sent to instance».
Правильный ответ — ошибка в runtime.
27. Что выведется в консоли, если код будет запущен на iPhone X?
int main(int argc, char * argv[]) {
int8_t matrix [2048][2048];
NSLog(@"%d", matrix[0][0]);
return 0;
}- 0;
- ошибка компиляции;
- ошибка в runtime;
- undefined.
Здесь будет обычный StackOverflow, так как размер стека на главном потоке — 1 MB (см. ссылку).
Правильный ответ — ошибка в runtime.
29. Что будет выведено в консоли?
NSData *responseData = nil;
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
NSLog(@"A");
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"B");
responseData = data;
dispatch_group_leave(group);
}];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"C");- ABC;
- ACB;
- CAB;
- ошибка компиляции.
В данной ситуации блок не сможет изменять объект responseData (отсутствует модификатор __block), для более подробной информации см. ссылку.
Правильный ответ — ошибка компиляции.
34. Что будет выведено в консоль?
NS_ROOT_CLASS
@interface A
@end
@implementation A
- (void)methodSignatureForSelector:(SEL)aSelector {
NSLog(@"%@", NSStringFromSelector(aSelector));
}
@end
int main(int argc, char * argv[]) {
__unused NSArray *a = @[ objc_getClass("A") ];
return 0;
}- Retain;
- ошибка компиляции;
- ничего;
- isProxy.
Мы создали новый рутовый класс в ObjC, который не имеет никаких методов, в отличие от NSProxy или NSObject.
Далее, при инициализации массива нашему объекту автоматически будет послано сообщение retain, и так как такой метод не был определён, ObjC попытается осуществить стандартный механизм method forwarding.
Правильный ответ — retain.
Android
6. Что будет, если вызвать метод start() два раза у одного и того же объекта Thread?
- Два раза выполнится run() в двух разных потоках;
- два раза выполнится run() в одном потоке;
- один раз выполнится run();
- будет выброшен exception.
Нельзя вызывать у класса Thread метод start() несколько раз.
Можно прочитать про это в документации к классу: «@throws IllegalThreadStateException — if this thread has already started».
Правильный ответ — будет выброшен exception.
7. Почему плохо использовать вложенные LinearLayout с не нулевыми layout_weight?
- Это приведёт к экспоненциальному росту числа измерений Layout;
- это удвоит число измерений Layout;
- это приведёт к StackOverflowException;
- нет причин.
Прочитать про оптимизацию иерархии Layouts приложения можно в документации: https://developer.android.com/training/improving-layouts/optimizing-layout.html.
Правильный ответ — это приведёт к экспоненциальному росту числа измерений Layout.
8. Какой стандартный элемент Android может использоваться без создания Application?
- Activity;
- Service;
- ContentProvider;
- все вышеперечисленные.
Обращение к ContentProvider через ContentResolver — синхронная операция и может быть выполнена из одного приложения к другому. Поэтому её нужно выполнять как можно быстрее. И в случае, если процесс второго приложения не запущен, Android так спроектирован, что onCreate ContentProvider вызывается до onCreate Application.
Прочитать про устройство ContentProvider можно в документации (https://developer.android.com/reference/android/content/ContentProvider) и в исходном коде AOSP, например в ActivityManagerServicer#getContentProviderImpl, ActivityThread#installContentProviders, ContentProvider#attachInfo.
Правильный ответ — ContentProvider.
11. Какой из способов, приведенных ниже, позволяет обеспечить транзитивное подключение библиотеки в проекте, использующий Gradle?
- implementation;
- api;
- compile;
- все вышеперечисленные.
Почитать про подключение модулей в Gradle можно в документации:
https://docs.gradle.org/current/userguide/dependency_management_terminology.html.
Правильный ответ — api.
12. Какой результат работы кода:
int f() {
try {
return 0;
} finally {
return 1;
}
}- 1;
- 0;
- Compilation error;
- Runtime exception.
Блок finally всегда выполняется после блока try. И, соответственно, в байткоде логика возврата значения функции будет выполнена в самом конце.
Правильный ответ — 1.
