Blog

  • Как выйти из режима редактирования в Терминале OS X

    Иногда по ошибке вводишь что-то не то в Терминале. Например, вот это

    В итоге попадаешь в какой-то режим редактирования (пока не знаю, что за редактор точно) с приглашением в виде треугольничка слева.

    Чтобы выйти из режима редактирования в Терминале Mac OS X, нужно нажать Ctrl + D

  • Немного о CoreData

    Core Data – это объектноориентированная оболочка над базой данных приложения в iOS/Mac OS. Позволяет создавать таблицы визуально, сама следит за Commitment Control, управлением версиями и т.д.

    Persistent Store – это “надежное” хранилище данных. (NSPersistenStoreCoordinator). Данные хранятся в applicationDocumentsDirectory/App.sqlite. Где App.sqlite – это база SQLite приложения.
    Context – это instance базы. Промежуточное хранилище, в котором производятся изменения и затем утверждаются (Commitment). Также запрос производится из Context. У одной базы может быть много Context. В каждом Context есть Managed Objects.
    Managed Object – объект, с которым мы работаем, но изменения, которые мы в него вносим не вносятся в Persistent Store до тех пор, пока мы не сделаем Save.

    CoreData – Core Data Programming Guide

    CoreDataSnippets – Core Data Code Snippets

    Базовый запрос без предиката всех строк из таблицы:

    + (BOOL)basicFetch {
        // Test Fetch of 1 item 
        
        useDelegate
        NSManagedObjectContext *context = appDelegate.managedObjectContext;
        if (context == nil) {
            NSLog(@"Error: No context");
            return NO;
        }
        
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription 
    entityForName:@"FLCatRanking" inManagedObjectContext:context];
        [fetchRequest setEntity:entity];
        
        NSError *error = nil;
        NSArray *fetchedObjects = [context 
    executeFetchRequest:fetchRequest error:&error];
        if (fetchedObjects == nil) {
            // Handle the error
            NSLog(@"Error: No fetched objects.");
            return NO;
        }
        
        // Take first product name
        FLCatRanking *flCatRanking = [fetchedObjects objectAtIndex:0];
        NSLog(@"First fetched item: %@", flCatRanking.prodID);
        return YES;
    }
    

    Запрос с фильтрацией – аналог WHERE в SQL :

    + (NSMutableDictionary*) retrieveProductsForCategory:
    (NSString*) catName {
        
        NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
        
        useDelegate
        NSManagedObjectContext *context = appDelegate.managedObjectContext;
        if (context == nil) {
            NSLog(@"Error: No context");
            return nil;
        }
        
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSPredicate *predicate = [NSPredicate 
    predicateWithFormat:@"prodCatName == %@", catName];
        NSEntityDescription *entity = [NSEntityDescription 
    entityForName:@"FLCatRanking" inManagedObjectContext:context];
        [fetchRequest setEntity:entity];
        [fetchRequest setPredicate:predicate];
        
        NSError *error = nil;
        NSArray *fetchedObjects = [context 
    executeFetchRequest:fetchRequest error:&error];
        if (fetchedObjects == nil) {
            // Handle the error
            NSLog(@"Error: No fetched objects.");
            return nil;
        }
        
        // Take first product name
        for (FLCatRanking *flCatRanking in fetchedObjects) {
            NSLog(@"FLCatRanking item: %@ - %@", flCatRanking.prodID, 
    flCatRanking.prodPos);
            [dic addEntriesFromDictionary:[NSDictionary 
    dictionaryWithObject:flCatRanking.prodID 
    forKey:flCatRanking.prodPos]];
        }
        
        return dic; 
    }
    
  • Кнопка Home в iOS приложениях

    Часто бывает нужно вернуться на главный экран после движения по Navigation Controller. Для этого нужно использовать следующий метод:

    [self.navigationController popToRootViewControllerAnimated:YES];
    
  • Конструкция “for each” в Java

    Недавно задался вопросом, есть ли такая конструкция в Java. Ясного ответа сразу не нашел. Некоторые говорят на форумах, что нет, а некоторые говорят, что есть, но как-то хитро через коллекции. Так вот, привожу пример своего кода, в котором использован аналог “for each” в Java:

    <br />
    Elements links = doc.select(“link”);<br />
    for (Element link : links) {<br />
          linksList.add(link.text());<br />
          Log.v(TAG, “link:”+link.text());<br />
    }<br />
    
  • Плагин WordPress для увеличения изображений (Plugin for resizing images on WordPress)

    По умолчанию WordPress увеличивает картинку, открывая целую страницу либо в текущем, либо в новом окне. Я долго искал плагин, который бы позволял увеличивать изображение в той же странице. Изучив три плагина, я все таки нашел четвертый, который мне подошел. Итак, называется он Auto Thickbox Plugin For WordPress и скачать его можно на странице плагинов WordPress или на официальной странице, где я и скачал.

    Кликните на следующую картинку, чтобы посмотреть, как это работает:

  • Отключение ARC для некоторых сорс-файлов (iOS)

    Чтобы отключить ARC(Automatic Reference Counting) лишь для некоторых сорс-файлов, нужно прописать в Compiler Flags:

    -fno-objc-arc
    

    как показано на рисунке:

    Важное замечание
    Для того, чтобы отключить ARC сразу на нескольких сорс файлах, нужно их выделить, затем нажать Enter(а не 2 щелчка), ввести эту опцию и снова нажать Enter.

  • Как пользоваться iBooks

    iBooks – очень полезное бесплатное приложение Apple для iOS, которое позволяет читать книги в форматах EPUB и PDF. Это наверно первое, что нужно устанавливать при покупке iPhone и особенно – iPad (если оно, конечно, уже не уставлено). Как это выглядит на iPhone:

    Пользоваться iBooks просто. Например, можно скачать книги из iTunes Store, раздела Books:

    и они появятся в Вашей медиатеке в разделе Books в iTunes.

    Книги в форматах EPUB и PDF можно также импортировать в iTunes/Books, нажав Cmd+O или Файл->Добавить в медиатеку.

    После этого, нужно просто синхронизировать раздел Books в устройстве с iOS с Вашей медиатекой iTunes/Books:

    В итоге, мы получаем целую библиотеку на iOS устройстве в приложении iBooks.

  • Определение координат центра iPhone / iPad

    Я относительно долго мучился, пытаясь создать код, который был бы унивесальным для iPhone и iPad и определял координаты центра экрана и координаты нижней части экрана. Это нужно было для того, чтобы позиционировать ActivityIndicatorView и AdView. Причиной мучений было то, что функция self.view.bounds работает некооректно на iPad и возвращает координаты прямоугольника такие же как на iPhone, хотя размер экрана другой. Итак, привожу код, по нему все понятно. Сначала я создаю объект CGSize screenSize и далее его использую для позиционирования Activity Indicator и iAd. Вычитаю 20.0 – это высота Status Bar; 44.0 – высота Navigation Bar; 50.0 – высота ADBannerView. У Вас в этом моменте может быть по другому, главное – принцип.

    <br />
        CGSize screenSize = [UIScreen mainScreen].bounds.size;</p>
    <p>    // Универсальное определение центра iPhone / iPad<br />
        CGFloat centerX = screenSize.width/2.0;<br />
        CGFloat centerY = (screenSize.height – 20.0 – 44.0)/2.0;<br />
        activity.center = CGPointMake(centerX, centerY);</p>
    <p>    // Универсальное позиционирование рекламы внизу экрана iPhone / iPad<br />
        CGFloat adWidth = screenSize.width;<br />
        CGFloat adYCoordinate = screenSize.height – 20.0 – 44.0 – 50.0;<br />
        NSLog(@”adWidth=%f, adYCoordinate=%f”, adWidth, adYCoordinate);<br />
        CGRect bannerFrame = CGRectMake(0, adYCoordinate, adWidth, 50.0);<br />
        bannerView.frame = bannerFrame;<br />
    
  • Как сделать приложение универсальным для iPhone / iPad

    Универсальность приложения – это большой плюс, так как на iPad в таком случае приложение будет работать так же красиво, как на iPhone без масштабирования и как иногда говорят “пикселизации”. Кроме этого, поддерживать универсальное приложение удобнее, так как оно одно, в противном случае нужно поддерживать два разных приложения для двух платформ, что более трудоемко. А еще в App Store будет одна страница. Следовательно легче продвигать, комментарии все в одном месте и т.д. Есть и минусы универсальности. Сложные приложения проще сделать, наверное, в двух вариантах.

    Для того, чтобы сделать приложение универсальным нужно учесть несколько аспектов или сделать несколько вещей.

    1. Заходим в Build Settings проекта и делаем поиск параметра Targeted Device Family. Выбираем опцию iPhone/iPad. См. рисунок. При щелчке он увеличивается.
    2. Создаем все необходимые заставки и иконки в нужных размерах. Для iPad размер заставки 768×1004 px, размер иконки 72х72 px. Для iPhone 360×460, иконка 57×57 для iPhone 3GS и ранее, 720х920, 114х114 соответственно для Retina display в iPhone 4 и выше. Если Вы не отображаете Status bar, то нужно прибавить еще 20 к высоте. Присваиваем все заставки и иконки во вкладке Summary для Вашего Target.
    3. Если какие-то XIB файлы View нужно переделать под iPad, то создаем эти XIB файлы. Для этого нажимаем правой кнопкой по папке Classes в проекте, New File -> User Interface -> View. Но просто создать XIB недостаточно. Нужно еще его File Owner присвоить значение нужного класса. См. Рисунок.

      Теперь у нас есть 2 XIB файла для одного View Controller: MainAboutViewController.xib и MainAboutViewControllerIPad.xib к примеру.
      В коде, там где вызывается этот контроллер, нужно сделать разветвление наподобие следующего:
      <br />
      – (IBAction)showAboutScreen:(id)sender {</p>
      <p>    NSString *nibName;<br />
          if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)<br />
              nibName = @”MainAboutViewControllerIPad”;<br />
          else<br />
              nibName = @”MainAboutViewController”;</p>
      <p>    MainAboutViewController *mainAboutViewController = [[MainAboutViewController alloc] initWithNibName:nibName bundle:nil];<br />
          mainAboutViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;<br />
          mainAboutViewController.title = @”О приложении”;<br />
          [self presentModalViewController:mainAboutViewController animated:YES];<br />
      }<br />
      
    4. Во всех других участках, где нужно учитывать тип устройства пишем аналогичный код:
      if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
      else ... 
      
    5. Ссылки:
      Converting iPhone apps to universal

      A few more notes

  • Android 2.3.3: “Waiting for debugger to attach”

    Не работал Debug на Android 2.3.3, а на Android 4.0.3. работал. Решил данную проблему простым перезапуском Eclipse и AVD Android 2.3.3.

    Решение нашел здесь в комментарии к правильному ответу.