Category: iOS

  • Почему GitHub так важен для iOS разработчиков

    Сегодня я прозрел как разработчик iOS приложений, спустя год после начала разработки под эту платформу, и решил с вами поделиться этим. Наверное, это прозрение, этот момент, наступает, когда разработчик уже ознакомился в целом почти со всеми возможностями нативных(родных) фреймворков от Apple.

    Повторное использование кода существенно ускоряет разработку. Вообще, ООП (объектно-ориентированное программирование) изначально создавалось с такой идеей, чтобы разработчики могли так же, как инженеры, создавать программы из готовых блоков, либо, по крайней мере, создавать блоки, которые были бы reusable, то есть повторно используемыми. Это одна из причин, почему просмотр Open Source проектов важен. Он позволяет увеличить собственную библиотеку повторно используемых компонентов и ускорить процесс разработки не только за счет нативных фреймворков и собственного кода, но и за счет плодов программистов со всего мира. Кроме того, за тот же срок можно сделать более интересный и качественный продукт, если использовать готовый код. А чем ты профессиональнее и чем быстрее и качественнее ты создаешь продукты, тем больше и твоя компенсация.

    В тесте Yandex’а для iOS-разработчиков есть вопрос – есть ли у Вас GitHub аккаунт. Я некоторое время не мог понять, почему он так важен и обязателен.

    Кроме этого, моему прозрению предшествовали многочисленные собеседования, которые я проходил. На одном из них у меня спросили, использую ли я Three20 – бесплатную Open Source библиотеку от создателя приложения для Facebook. Потом, спустя 4 месяца, я ее скачал с GitHub и изучил. Также я скачал и стал применять библиотеку MBProgressHUD, которая позволяет показывать волчок, а сам долгий процесс запускать в параллельном потоке. Также я только по необходимости скачивал оттуда MailCore.

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

    В GitHub выкладывают очень много Open Source проектов, в том числе и на Objective-C (там их целых 2 процента и этот язык там на 10 месте по популярности). Многие проекты представляют огромную ценность, так как в них реализованы интересные фичи, приемы, контролы и т.д.

    Например, я скачал с GitHub 4 проекта, которые были популярны сегодня. Первый позволяет отображать PDF c кучей контролов и читать его с удобством (Reader), второй – показывает различные View как Pop up с разной анимацией (MJPopupViewController), третий позволяет легко записывать видео из приложения (cam), четвертый представляет из себя по сути горизонтальный Table View (FantasyView).

    В GitHub есть разделы по разным языкам и кроме этого, есть сортировка по количеству бранчей и закачек. Также, в GitHub можно посмотреть самые популярные по просмотрам проекты за день, неделю, месяц и все время. А еще – самые популярные по бранчам.

    Я решил теперь для себя, что буду просмотривать раздел, связанный с Objective C, регулярно, даже без необходимости, просто чтобы увидеть, что делают другие и как делают. Ну и по возможности выложу что-нибудь свое. Пока из существенного я выложил только свою программу на C# для заполнения Excel данными из википедии (ExcelFiller).

    По аналогии, буду также просматривать Open Source раздел Google, Apple и других компаний. Все, что я здесь написал, относится не только к GitHub и не только к Objective C. Просто с них я начал.

    Еще, хотелось бы добавить, для разработчика iOS важны OpenSource проекты не только на Objective C, но и на C++/C. Например, я как-то использовал ZXing и ZBar для распознования штрих-кодов.

    Напоследок несколько ссылок для быстрого доступа:
    Раздел GitHub на Objective C
    Топовые GitHub проекты под iOS
    Мой собственный аккаунт на GitHub
    Google Open Source
    Sample Code для разработчиков Apple
    Проекты на SourceForge под iOS, наиболее популярные

  • MailCore CTCoreAttachment example

    To add attachments in MailCore add this ONLY after setBody/setHTMLBody:

    <br />
        // Set Attachments<br />
    NSString *filePrefix = [[NSBundle mainBundle] bundlePath];<br />
    NSString *path = [NSString stringWithFormat:@”%@/%@”,filePrefix,@”TestData/DSC_6201.jpg”];<br />
    NSLog(@”path:%@”, path);</p>
    <p>CTCoreAttachment *attach = [[CTCoreAttachment alloc] initWithContentsOfFile:path];<br />
    if ([attach data]==nil) {<br />
        NSLog(@”Error: attachment data is nil”);<br />
    }<br />
    [myMessage addAttachment:attach];<br />
    

    Here, you should add TestData folder with image to your project as a folder reference.

  • TWTweetComposeViewController doesn’t display initial tweet

    TWTweetComposeViewController doesn’t display tweets, that are too long. You can take a substring of a tweet by cutting down to 140 symbols:

    [tweetView setInitialText:[self.textToExport substringToIndex:140]];
    NSLog(@"tweetView.initialText:%@", [self.textToExport \
     substringToIndex:140]);
    
  • Apple’s Twitter framework example

    This is an example, how to integrate Twitter framework of Apple to your app.

    Firstly, add Twitter (Twitter.framework) and MobileCoreServices frameworks to your app.

    Then add header files to your source file:

    </p>
    <pre>#import <Twitter/TWTweetComposeViewController.h>
    #import <MobileCoreServices/MobileCoreServices.h></pre>
    <p>

    Then add this method or similar:

    <br />
    – (void)sendToTwitter {<br />
    useDelegate<br />
    if ([appDelegate iOSVersion5]) {<br />
    [self showErrorAlert:@”Отправка в Twitter доступна только в iOS 5 и выше.”];<br />
    return;<br />
    }</p>
    <p>tweetView = [[TWTweetComposeViewController alloc] init];</p>
    <p>TWTweetComposeViewControllerCompletionHandler<br />
    completionHandler =<br />
    ^(TWTweetComposeViewControllerResult result) {<br />
    switch (result)<br />
    {<br />
    case TWTweetComposeViewControllerResultCancelled: {<br />
    NSLog(@”Twitter Result: canceled”);<br />
    [self showErrorAlert:@”Отправка в Twitter отменена.”];<br />
    break;<br />
    }<br />
    case TWTweetComposeViewControllerResultDone: {<br />
    NSLog(@”Twitter Result: sent”);<br />
    [self showErrorAlert:@”Отправка в Twitter выполнена.”];<br />
    break;<br />
    }<br />
    default: {<br />
    NSLog(@”Twitter Result: default”);<br />
    [self showErrorAlert:@”Отправка в Twitter не выполнена.”];<br />
    break;<br />
    }<br />
    }<br />
    [self dismissModalViewControllerAnimated:YES];<br />
    };<br />
    [tweetView setCompletionHandler:completionHandler];</p>
    <p>[tweetView setInitialText:self.textToExport];<br />
    [self presentModalViewController:tweetView animated:YES];<br />
    }<br />
    

    Here, firstly iOS version is checked, because it will work only in iOS 5 or later. Then, I create TWTweetComposeViewController instance, it’s block completion handler, set text to export to Twitter and then present controller as a modal controller.

  • How to check iOS version programmatically

    To check the iOS version you can use the following method:

    - (BOOL)iOSVersion5 {
        NSLog(@"System Version is %@", \
    [[UIDevice currentDevice] systemVersion]);
        NSString *ver = [[UIDevice currentDevice] systemVersion];
        float ver_float = [ver floatValue];
        if (ver_float < 5.0) {
            return NO;
        }
        else {
            return YES;
        }
    }
    
  • Deleting from Core Data

    Deleting objects from Core Data should not be recognized as deleting rows from SQLite table. It is like deleting objects from Object Graph. This is an example of deleting all rows for the current file number. I retrieve all NSManagedObject objects and delete them in cycle.

    <br />
    + (BOOL)deleteScrollPositionsForFileNumber:(NSInteger)fileNumber {<br />
        BOOL success;<br />
        useDelegate<br />
        NSManagedObjectContext *context = appDelegate.managedObjectContext;<br />
        if (context == nil) {<br />
            NSLog(@”Error: No context”);<br />
            success = NO;<br />
            return success;<br />
        }</p>
    <p>    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];<br />
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@”fileNumber == %d”, fileNumber];<br />
        NSEntityDescription *entity = [NSEntityDescription entityForName:@”ScrollPosition” inManagedObjectContext:context];<br />
        [fetchRequest setEntity:entity];<br />
        [fetchRequest setPredicate:predicate];</p>
    <p>    NSError *error = nil;<br />
        NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];<br />
        NSLog(@”Number of deleted objects: %d”, [fetchedObjects count]);<br />
        for (NSManagedObject *object in fetchedObjects) {<br />
            [context deleteObject:object];<br />
        }<br />
        success = YES;<br />
        return success;<br />
    }<br />
    
  • Change MBProgressHUD color

    To change the background color of MBProgressHUD comment this line and add this in MBProgressHUD.m in drawRect method:

        //CGContextSetGrayFillColor(context, 0.0f, self.opacity);
        CGFloat fillColor[4]    = {0.0,0.0,1.0,1.0};
        CGContextSetFillColor(context, fillColor);
    

    This code changes HUD color to blue.

  • Reload UITableView cells

    Sometimes it’s needed to reload only some of the rows of UITableView to save some time and energy and not reload whole the table. This is how it can be done:

    NSIndexPath * indexPath = \
       [NSIndexPath indexPathForRow:row inSection:0]; 
    [self.tableView reloadRowsAtIndexPaths: \
       [NSArray arrayWithObject:indexPath] \
       withRowAnimation:UITableViewRowAnimationMiddle];
    
  • Save current position in UIScrollView and then scroll to this position

    To save a position of the current scroll view use this method:

    - (void)savePosition {
        positionY = webView.scrollView.contentOffset.y;
        NSLog(@"positionY:%d", positionY);
    }
    

    To scroll programmatically to the saved position use this method:

    - (void)scrollToYPosition:(int)positionY {
        [self.webView.scrollView setContentOffset: \
    CGPointMake(self.webView.scrollView.contentOffset.x, positionY)];
    }
    
  • How to build MailCore framework on iOS

    MailCore is a Cocoa e-mail framework built by Matt Ronge that is the core of the e-mail client Kiwi. MailCore provides a nice set of objects for working with IMAP, MIME and SMTP, all of which use the C e-mail library LibEtPan. Here is some short information about MailCore. This is short documentation on MailCore from Matt Ronge. Official website is here.

    To make it run on your iOS simulator, do the following:

    1. Download MailCore from GitHub:
      git clone https://github.com/mronge/MailCore.git
      cd MailCore/
      git submodule init
      git submodule update
      
    2. Build m4, autoconf, automake, libtool on Mac OS X Lion using this post.
    3. Run update.sh script in MailCore to build and install everything before opening it in Xcode. If you don’t know, how to run shell scripts, read this
    4. Open MessageSender project in MailCore library. Select MessageSender to build. It will not do anything. To make it sending a test message write the following code in ViewDidLoad:
      CTCoreMessage myMessage = [[CTCoreMessage alloc] init];
          
      // Set To
      CTCoreAddress *addrTo1 = [CTCoreAddress address];
      [addrTo1 setEmail:@"Your E-mail1"];
      CTCoreAddress *addrTo2 = [CTCoreAddress address];
      [addrTo2 setEmail:@"E-mail2"];
      /*CTCoreAddress *addrTo3 = [CTCoreAddress address];
      [addrTo3 setEmail:@"E-mail3"];*/
      [myMessage setTo:[NSSet setWithObjects:addrTo1, addrTo2, nil]];
        
      // Set From 
      CTCoreAddress *addrFrom = [CTCoreAddress address];
      [addrFrom setEmail:@"Your E-mail"];
      [addrFrom setName:@"Your Name"];
      [myMessage setFrom:[NSSet setWithObject:addrFrom]];
         
      [myMessage setSubject:@"Test Mail Core"];
      [myMessage setHTMLBody:@"This is a test HTML message"];
         
      [CTSMTPConnection sendMessage:myMessage \
      server:@"smtp.mail.ru" username:@"YourUserName" \
      password:@"YourPassword" port:587 useTLS:YES useAuth:YES];
      
    5. Use this method to retrieve message subjects from Inbox of your mail:

      - (IBAction)retrieveClicked:(id)sender {
          CTCoreAccount *account = [[CTCoreAccount alloc] init];
          [account connectToServer:@"imap.yandex.ru" port:143 \
       connectionType:CONNECTION_TYPE_PLAIN authType:IMAP_AUTH_TYPE_PLAIN \
       login:@"YOUR USERNAME" password:@"YOUR PASSWORD"];
          
          NSSet *subFolders = [account subscribedFolders];
          
          CTCoreFolder *inbox = [account folderWithPath:@"INBOX"];
          
          NSSet *messageList = [inbox messageObjectsFromIndex:1 \
       toIndex:0];
          
          for (CTCoreMessage *message in messageList) {
              NSLog(@"%@", [message subject]);
          }
      }
      

    Official MailCore website.