Stanford CS 193P iOS 7 — Домашнее задание 2

Screen Shot 2014-07-13 at 3.34.28 PMСодержание

Текст Домашнего задания на английском языке доступен на  iTunes в пункте  “Developing iOS 7 app:Assignment 2″На русском языке 

Задание 2 Matchismo 2 fall 2013.pdf

Пункт 1

Следуйте детальной инструкции на слайдах лекции (отдельный документ) для воссоздания последней версии Matchismo, которую мы построили на лекции (то есть вариант с множеством карт) и запустите его на симуляторе iPhone (iPhone Simulator) в Xcode 5. Не переходите к следующим шагам до тех пор, пока ваша карточная игра “на совпадение” не будет функционировать без ошибок и предупреждений.

 

Слайды  Лекции 3 содержат подробную пошаговую инструкцию для выполнения Домашнего задания 1 и для всех шагов, описанных выше. Следуя этой инструкции (если вы уже не сделали это в течение лекции), вы полностью выполните пункт 2 Домашней работы 2.

Полный код для этого пункта доступен на Github.

Пункт 2

Добавьте кнопку UIButton для “пересдачи” карт (то есть для начала новой игры). Она должна переустановливать счет (метку score или что-то еще в UI, что имеет значение для начала игры). В реальной игре мы бы, возможно, захотели спросить его или ее, “уверены” ли они, что хотят прервать игру в случае “пересдачи” карт, но для этого домашнего задания мы предполагаем, что он или она знают, что они делают, когда нажимают на эту кнопку.

Перетащите новую кнопку на storyboard. Заметьте, что голубой цвет надписи как для кнопки, так и для метки, на зеленом фоне плохо различимы. Вы можете поменять цвет всех надписей на кнопках с помощью Tint Color на всей storyboard, если на  закладке File Inspector (Файловый инспектор) укажите Global Tint:

Глобальное изменение цвета надписей на storyboard

Дайте кнопке название ‘Deal». Для того, чтобы эта кнопка функционировала,  создайте action (путем Ctrl-перетягивания в Ассистенте Редактора от кнопки к файлу CardGameViewController.m), который установит игру Matchismo заново и адаптирует пользовательский интерфейс:

//  CardGameViewController.m
//  Assignment-2-iOS7
.  .  .  .  .  .  .  .  .  .  .
- (IBAction)dealPress:(id)sender {
    self.game = nil;
    [self updateUI];
}
.  .  .  .  .  .  .  .  .  .  .

Полный код для этого пункта доступен на Github.

Пункт 3

Перетяните переключатель (UISwitch) или элемент сегментного управления (UISegmentedControl) куда-нибудь на ваш View, чтобы управлять количеством “совпадающих” карт в игре: 2 карты или 3 карты (то есть переключение между режимами “2-х карточное совпадение” и  “3-х карточное совпадение”). Дайте игроку подходящее количество очков в зависимости от трудности достижения совпадения карт. В 3-х карточном режиме совпадения возможно получение некоторого количество очков (хотя и значительно меньшее) при выборе 3-х карт и совпадении только двух из них. В этом случае все 3 карты должны быть выведены из игры (хотя совпали только 2 карты).  В 3-х карточном режиме совпадения выбор 2-х карт никогда не рассматривается как совпадение.

Перетащите элемент сегментного управления на storyboard и измените названия его сегментов:

Assignment 2 task 2

 

Подсоединим его ( Ctrl-перетаскиванием ) как  к outlet property

@property (weak, nonatomic) IBOutlet UISegmentedControl *numberOfMatchesSegment;

так и к action

- (IBAction)changeNumberOfMatches {
    self.game =nil;
    [self updateUI];
}

. Если сегментный элемент меняет свое значение, то вызывается этот action. Понятно, что если вы меняете количество карт, которые должны «совпадать», то есть условия игры, то игра должна начаться сначала. Поэтому мы выполняем те же действия, что и при пересдаче карт. Новое значение должно быть считано при «отложенной» инициализации самой игры в нашем CardGameViewController. Но также как со свойством deck, считывание значения сегментного элемента управления мы произведем во вспомогательном методе ( в дальнейшем нам это пригодится для объектно-ориентированного варианта CardGameViewController) :

.  .  .  .  .  .
@implementation CardGameViewController

- (CardMatchingGame *)game
{
    if (!_game) _game = [[CardMatchingGame alloc] initWithCardCount:[self.cardButtons count]
                                                          usingDeck:[self createDeck]];
    _game.numberOfMatches =[self numberOfMatches];

    return _game;
}

- (NSUInteger)numberOfMatches
{
    return self.numberOfMatchesSegment.selectedSegmentIndex+2;
}

.  .  .  .

Но для этого необходимо в игру (в public API нашего класса CardMatchingGame) добавить свойство, которое позволяет задавать количество «совпадающих» карт в игре:

@interface CardMatchingGame : NSObject

-(instancetype)initWithCardCount:(NSUInteger)count
                       usingDeck:(Deck *)deck;

-(void)chooseCardAtIndex:(NSUInteger)index;
-(Card *)cardAtIndex:(NSUInteger)index;

@property (nonatomic) NSUInteger numberOfMatches;
@property (nonatomic,readonly) NSInteger score;

@end

Так как количество «совпадающих» карт в игре не может быть менее 2-х, то в файл имплиментации нашей игры (CardMatchingGame.m) поместим setter для нашего нового свойства numberOfMatches:

- (void)setNumberOfMatches:(NSUInteger)numberOfMatches
{
    _numberOfMatches = numberOfMatches >= 2 ? numberOfMatches :2;
}

Теперь надо модифицировать алгоритм «совпадения»

-(int)match:(NSArray *) otherCards

в классе PlayingCard на случай совпадения n карт. По идеи в случае n карт нет необходимости выделять карту, для которой вызывается этот метод, так как нам потребуется сравнение каждой с каждой из всех имеющихся карт, включая ту, для которой вызывается этот метод. Поэтому мы будем предполагать, что массив otherCards содержит все «выбранные» (isChoosen = True), но не «совпавшие» ранее карты (isMatched = False). Каждая карта должна внести хотя бы одно совпадение, и если общее число совпадений не менее numberOfMatches-1, то считаем, что numberOfMatches карт «совпали». Естественно, «совпадение» по масти оценивается в 4 очка, а «совпадение» по рангу в 1 очка. Затем подсчитываем общий счет от всех совпадений.

-(int)match:(NSArray *)otherCards
{
    int score =0;
    int numMatches = 0;
    if ([otherCards count] > 0)
    {
        for (int i = 0; i < [otherCards count]; i++) {
            id otherCard1 = otherCards[i];
            if ([otherCard1 isKindOfClass:[PlayingCard class]])
            {
                PlayingCard *card1 = (PlayingCard *)otherCard1;

                for (int j = i+1; j < [otherCards count]; j++) {
                    id otherCard2 =otherCards[j];
                    if ([otherCard2 isKindOfClass:[PlayingCard class]])
                    {
                        PlayingCard *card2 =(PlayingCard *)otherCard2;
                        // check for the same suit
                        if ([card1.suit isEqualToString:card2.suit]) {
                            score += 1;
                            numMatches++;
                        }
                        // check for the same rank
                        if (card1.rank == card2.rank) {
                            score += 4;
                            numMatches++;
                        }
                    }
                }
            }
        }

        if (numMatches < [otherCards count] -1) score = 0;
    }
    return score;
}

Естественно нужно правильно накапливать «выбранные», но «несовпавшие» карты при выборе очередной карты в методе chooseCardAtIndex: в классе нашей игры (CardMatchingGame.m). Для этого создадим в расширении класса CardMatchingGame новое свойство — массив «выбранных», но «несовпавших» ранее карт:

#import "CardMatchingGame.h"

@interface CardMatchingGame()

@property (nonatomic, readwrite) NSInteger score;
@property (nonatomic, strong) NSMutableArray *cards; // of Card
@property (nonatomic,strong) NSMutableArray *faceUpCards; // of Card

@end
.  .  .  .  .  .  .  .  .  .  .  .  .

, который будем использовать для анализа на «совпадение»:

@implementation CardMatchingGame

.  .  .  .  .  .  .  .  .  .  .  .  .  .
static const int MISMATCH_PENALTY = 2;
static const int MATCH_BONUS = 4;
static const int COST_TO_CHOOSE = 1;

-(void)chooseCardAtIndex:(NSUInteger)index
{
    Card *card = [self cardAtIndex:index];
    if (!card.isMatched) {
        if (card.isChosen) {
            card.chosen =NO;
        } else {
            // put choosen card in array self.faceUpCards
            self.faceUpCards= [[NSMutableArray alloc] initWithArray:@[card]];
            for (Card *otherCard in self.cards) {
                if (otherCard.isChosen && !otherCard.isMatched) {
                    [self.faceUpCards insertObject:otherCard atIndex:0];
                    //---------------- decision on match
                    if ([self.faceUpCards count] == (self.numberOfMatches)) {
                        int matchScore = [card match:self.faceUpCards];
                        if (matchScore) {
                            self.score += matchScore * MATCH_BONUS;
                            for (Card *faceUpCard in self.faceUpCards) {
                                faceUpCard.matched =YES;
                            }

                        } else {
                            self.score -= MISMATCH_PENALTY;
                            for (Card *faceUpCard in self.faceUpCards) {
                                if (faceUpCard != card) faceUpCard.chosen =NO;
                            }
                        }
                        break;
                    } //--------------- end of decision on match
                }
            }
            card.chosen = YES;
            self.score -= COST_TO_CHOOSE;
        }
    }
}
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

Предложение, высказанное в подсказке 7 выполнено, поскольку, если мы имеем совпадение 2-х карт при 3-х карточной игре, то при совпадении ранга нам будет начисляться 1 очко, а при совпадении 3-х карт с одинаковым рангом — 2 очка.

Полный код для этого пункта доступен на Github.

Пункт 4

Сделайте неработоспособным (disable) элемент управления режимом “2-х карточное совпадение” / “3-х карточное совпадение” (то есть  переключатель UISwitch или UISegmentedControl в обязательном задании 3), когда игра началась (то есть после первого переворота карты в игре) и вновь работоспособным (re-enable), когда происходит “пересдача” карт. (то есть кнопка Deal нажата).

Делаем неработоспособным элемент сегментного управления при выборе карты и восстанавливаем его работоспособность при нажатии кнопки «Deal» для «пересдачи» :

@implementation CardGameViewController
.  .  .  .  .  .  .  .  .  .  .  .  .
- (IBAction)touchCardButton:(id)sender
{
    self.numberOfMatchesSegment.enabled =NO;
    NSUInteger cardIndex = [self.cardButtons indexOfObject:sender];
    [self.game chooseCardAtIndex:cardIndex];
    [self updateUI];
}
- (IBAction)dealPress:(id)sender {
    self.numberOfMatchesSegment.enabled =YES;
    self.game = nil;
    [self updateUI];
}
.  .  .  .  .  .  .  .  .  .  .  .  .

Полный код для этого пункта доступен на Github.

Пункт 5

Добавьте куда-нибудь на экран текстовую метку, описывающую результат последнего рассмотрения CardMatchingGame карты, выбранной игроком. Например: “Matched J♥️ J♠️ for 4 points.”  или “6♦️ J♣️ don’t match! 2 point penalty!” или “8♦️”, если выбрана только одна карта или просто “пробел”, если вообще никаких карт не выбрано. Не нарушайте правил MVC и не создавайте UI в вашей Model. Под “UI” подразумевается все, что вы собираетесь представить пользователю. Это должно работать правильно в любом из режимов, упомянутых в обязательном задании 3.

Давайте поговорим немного о том, как нужно представить результаты анализа на совпадения и где их формировать. Как следует из Пункт 5, результат последнего переворота карты должен быть представлен пользователю (то есть это View ) описаниями (descriptions) карт, участвующих в анализе «совпадения». Эти описания карт  разделены пробелами, и  их должна сопровождать информация о количестве очков, полученных игроком при последнем «перевороте» карты и о выигрыше или проигрыше. Но View ничего не знает о том, какие карты анализировались, и тем более ему ничего не известно о «штрафах» и «бонусах» при «совпадении» или «несовпадении» карт. Этой информацией располагает только  Model, но View не может извлекать информацию из Model. Поэтому API Model должен быть таким, чтобы после каждого «переворота» карты (метод chooseCardAtIndex:) , Controller мог иметь доступ к массиву карт, исследуемых на совпадение, и к количеству очков, назначенных в зависимости от результатов «совпадения». Поэтому добавим в класса CardMatchingGame.h следующие свойства:

//CardMatchingGame.h
..........
@property (strong,nonatomic) NSArray *matchedCards;
@property (readonly,nonatomic) NSInteger lastFlipPoints;

//CardMatchingGame.m
@property (readwrite,nonatomic) NSInteger lastFlipPoints;
.......

Карты, исследуемые на «совпадение», уже собираются в массиве

//CardMatchingGame.m
.......
@property (nonatomic,strong) NSMutableArray *faceUpCards; // of Card
.......

Когда вы выбираете карту, в Model  (класс CardMatchingGame) срабатывает метод  chooseCardAtIndex: и текущая карта, если она ранее не «совпадала»  и была повернута «лицом» вниз, добавляется в массив self.faceUpCards, который исследуется методом match: на предмет «совпадения» карт. Все это уже есть в нашем алгоритме, и нам остается только скопировать «внутренний» массив self.faceUpCards в массив self.matchedCards, который и предъявляется API для внешнего использования.Кроме того, вместо установки значения self.score напрямую, мы будем использовать новое свойство self.lastFlipPoints,  и с помощью его будем в конце подсчитывать окончательный счет.
В результате получим следующий код метода chooseCardAtIndex:

static const int MISMATCH_PENALTY = 2;
static const int MATCH_BONUS = 4;
static const int COST_TO_CHOOSE = 1;

-(void)chooseCardAtIndex:(NSUInteger)index
{
    Card *card = [self cardAtIndex:index];
    if (!card.isMatched) {
        if (card.isChosen) {
            card.chosen =NO;
        } else {
            // match against another cards
            self.faceUpCards= [[NSMutableArray alloc] initWithArray:@[card]];
            self.lastFlipPoints = 0;
            for (Card *otherCard in self.cards) {
                if (otherCard.isChosen && !otherCard.isMatched) {
                    [self.faceUpCards insertObject:otherCard atIndex:0];
                    // decision on match
                    if ([self.faceUpCards count] == (self.numberOfMatches)) {

                        int matchScore = [card match:self.faceUpCards];
                        if (matchScore) {
                            self.lastFlipPoints = matchScore * MATCH_BONUS;
                            for (Card *faceUpCard in self.faceUpCards) {
                                faceUpCard.matched =YES;
                            }

                        } else {
                            self.lastFlipPoints = - MISMATCH_PENALTY;
                            for (Card *faceUpCard in self.faceUpCards) {
                                if (faceUpCard != card) faceUpCard.chosen =NO;
                            }
                        }
                        self.matchedCards =[self.faceUpCards copy];
                        break;
                    }
                    // decision on match
                }
            }
            self.score+= self.lastFlipPoints - COST_TO_CHOOSE;
            self.matchedCards =[self.faceUpCards copy];
            card.chosen = YES;
        }
    }
}
 

Screen Shot 2014-08-25 at 5.11.12 PM

Добавляем метку на наш storyboard. Так как нам необходимо, чтобы метка ничего не показывала в начале игры, то мы вынуждены убрать какой-либо текст с в этой метке (как показано на рисунке). Это сделает нашу метку невидимой и может в дальнейшем создать некоторые проблемы. Если вас это напрягает, то вы можете там разместить какой-то текст, а затем, например, в  viewDidLoad, его убрать. Мы этого делать не будем.

Создадим outlet к этой метке:


@property (weak, nonatomic) IBOutlet UILabel *resultsLabel;

Метка будет устанавливаться всякий раз при модификации пользовательского интерфейса ( срабатывания метода updateUI ) на основе новых public  свойств нашей игры, то есть класса CardMatchingGame. Мы  создаем строку с описаниями «выбранных» карт, разделенными пробелом, и в зависимости от количества насчитанных очков размещаем дополнительный текст. Таким образом мы добавляем в метод updateUI вызов метода  updateFlipResult:

- (void)updateUI
{
.......
        [self updateFlipResult];
}

А метод updateFlipResult будет работать на основе новых свойств нашей игры self.game — self.game.machedCards и self.game.lastFlipPoints:

-(void)updateFlipResult
{
 NSString *text=@" ";
 if ([self.game.matchedCards count]>0)
 {
 text = [ text stringByAppendingString:
 [self.game.matchedCards componentsJoinedByString:@" "]];
 if ([self.game.matchedCards count] == [self numberOfMatches])
 {
 if (self.game.lastFlipPoints<0) {
 text = [ text stringByAppendingString:
 [NSString stringWithFormat:@"✘ %ld penalty",
 (long)self.game.lastFlipPoints]];
 } else {
 text = [ text stringByAppendingString:
 [NSString stringWithFormat:@"✔ +%ld bonus",
 (long)self.game.lastFlipPoints]];
 }
 } else text =[self textForSingleCard];
 } else text = @"Play game!";
 self.resultsLabel.text = text;
}

- (NSString *)textForSingleCard
{
 Card *card = [self.game.matchedCards lastObject];
 return [NSString stringWithFormat:@" %@ flipped %@",card,(card.isChosen) ? @"up!" : @"back!"];
}

Полный код для этого пункта доступен на Github.

Пункт 6

Измените пользовательский интерфейс (UI) вашей игры так, чтобы у вас было 30 карт вместо 12. Посмотрите подсказки относительно размера карт.

Измените размер карт — вместо применения подсказки, вы можете использовать Инспектор Размера ( Size Inspector) в Области Утилит для установки нужного размера ( на рис. ниже 40х60 ) напрямую. Кроме того, для размножения строк из 6-ти карт можно использовать меню Edit -> Duplicate, а также Copy — Paste. Не забудьте подсоединить ваши карты к outlet


@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;

в вашем  viewController.

Assignment 2 Task 6

Измените фонт текста на кнопках на System 14.0
Полный код для этого пункта доступен на Github.

Пункт 7

Не изменяйте сигнатуру любых public методов (Сигнатура метода — это сокращенная форма записи параметров метода и типов возвращаемого значения. Следует подчеркнуть, что в сигнатуру не входят ни имя метода, ни имена параметров) , которые мы создали на лекции. Допустимо изменять сигнатуру private методов (хотя вряд ли вам это понадобится) или добавлять public и/или private методы.

… Выполнено.

Пункт 8 ( дополнительный 1 )

Добавить ползунок UISlider к UI, который обеспечивает путешествие по истории результатов выбора карты в текущей карточной игре и отображение их пользователю (передвижение ползунка UISlider будет модифицировать содержание текстовой метки, которую вы создали в Обязательном задании 5 для показа состояния игры). Когда отображаются прошлые результаты, возможно, вы захотите  чтобы тексовая метка была серой или еще чем-то (обратите внимание на на метод alpha класса UIView и заметьте, что UISlider наследует от  UIView) так, чтобы было понятно, что это “прошлое”. И каждый раз, когда происходит новый выбор карты, вы возможно захотите “прыгнуть в настоящее” на слайде. Выполнение этого дополнительного задания потребует от вас знакомства с API класса UISlider и добавления структуры данных в ваш Controller для отслеживания истории. Это может быть выполнение менее чем дюжиной  (12) строк кода.

История предыдущих переворотов карт ничего не вносит в нашу модель игры, следовательно мы будем запоминать историю «переворотов» в нашем  viewController.  Для этого создадим массив и его «отложенное» получение  экземпляра класса (lazy instantiation)  :

@interface CardGameViewController ()
......
@property (strong,nonatomic) NSMutableArray *flipsHistory;
......
- (NSMutableArray *)flipsHistory
{
    if (!_flipsHistory)_flipsHistory = [[NSMutableArray alloc] init];
    return _flipsHistory;
}

«Запись» истории будет происходить в методе updateFlipResult, в котором формируется информационная строка для пользователя о результатах «переворота» очередной карты:

-(void)updateFlipResult
{
..........
        [self.flipsHistory addObject:text];
    } else text = @"Play game!";
    self.resultsLabel.text = text;
}

Когда вы нажимаете на кнопку «Deal» пересдачи карт, то массив истории «переворотов» устанавливается в nil:

- (IBAction)Deal:(UIButton *)sender
{
........
    self.flipsHistory =nil;
    [self updateUI];
}

Добавьте ползунок (slider) на ваш storyboard, установите его диапазон в 0 (потому что в начале у нас нет истории) :

Assignment 2 Task 8

 

Подсоедините ползунок к outlet property и к  action.

@interface CardGameViewController ()
..............
@property (weak, nonatomic) IBOutlet UISlider *historySlider;
@end
......
- (IBAction)takeHistory:(UISlider *)sender {

}
............

Assignment 2 Task 8

Assignment 2 Task 8

По умолчанию ползунок работает с аналоговым значением, то есть получает значения  (values) ввиде чисел с плавающей точкой. Но у нас дискретная история, поэтому мы будем двигать ползунок к ближайшей доступной дискретной точке нашей истории. Если вы передвигаете ползунок с «текущей» позиции, то нужно поменять значение  alpha метки с отображением информации о прошлом «перевороте» чтобы сделать метку более «прозрачной» (translucent), и конечно нужно заменить текст этой метки на информацию о результатах этого  прошлого «переворота». Немного отвлечемся от ползунка и подумаем о том, как обозначить «текущую» позицию и дискретные метки в нашей «истории». Так как у нас «история» «переворотов» карт, то естественно использовать для этого номер «переворота».Добавим дополнительное свойства 

@interface CardGameViewController ()
.........
@property (nonatomic) int flipCount;
.......
@end

с помощью которого будем считать количество «переворотов» в нашей игре. Для логики игры это не имеет значения, поэтому разместим это в нашем viewController. Количество «переворотов» соответствует количеству нажатий кнопок карт или количеству срабатываний метода  touchCardButton:, поэтому там и будем рассчитывать количество переворотов:

- (IBAction)touchCardButton:(id)sender
{
    self.numberOfMatchesSegment.enabled =NO;
    NSUInteger cardIndex = [self.cardButtons indexOfObject:sender];
    [self.game chooseCardAtIndex:cardIndex];
    self.flipCount++;
    [self updateUI];
}

Количество «переворотов» следует выставить в 0 при пересдачи карт

- (IBAction)dealPress:(id)sender {
........
    self.flipCount =0;
........
}

Количество «переворотов» будем показывать пользователю на UI в маленькой метке

@interface CardGameViewController ()
.........
@property (weak, nonatomic) IBOutlet UILabel *sliderMaxLabel;
.......
@end

, расположенной справа от ползунка

Assignment 2 Task 8
Вернемся к нашему ползунку. Для того, чтобы ползунок начал действовать мы должны выставлять его максимальное значение, которое уместно выставлять при модификации экрана, то есть в методе updateUI. Это и будет «текущее» значение числа «переворотов». Одновременно поместим «текущее» значение в метке справа от ползунка:

- (void)updateUI
{
.........
    self.historySlider.maximumValue = self.flipCount;
    [self.historySlider setValue:(float)self.flipCount animated:YES];
    self.sliderMaxLabel.text = [NSString stringWithFormat:@"%d",(int)ceilf(self.historySlider.maximumValue)];
}

При перемещении ползунка работает action метод takeHistory:

- (IBAction)takeHistory:(UISlider *)sender {
    int selectedIndex = (int) sender.value;
    if (selectedIndex <0 || (selectedIndex > self.flipCount-1)) return;
    self.resultsLabel.alpha = (selectedIndex < self.flipCount-1 ) ? 0.5 : 1.0;
    NSString *text = [NSString stringWithFormat:@"%d:",(selectedIndex+1)];
    self.resultsLabel.text = ];
}

Полный код для этого пункта доступен на Github.

Пункт 9 ( дополнительный 2 )

Поменяйте изображение обратной стороны карты (то есть что-то отличное от логотипа Stanford). А также установите иконки с изображениями для самого приложения Matchismo и для его запуска. Попытайтесь установить правильное разрешение для изображения каждой иконки: Application и Launch. Отпустите на свободу свое воображение при конструировании этих иконок.

Используя свою любимую графическую программу, создайте изображение обраьной стороны карты, и экспортируйте его в двух форматах  40×60 и 80×120. В Xcode в навигаторе выберите папку  image assets и перетяните туда свои новые изображения обратной стороны карты:

Для иконки вашего приложения необходимо 3 различных размера  2*29pt = 58×58, 2*40pt = 80×80 and 2*60pt = 120×120. Также как и раньше их необходимо перетянуть в ваш  image assets:

App icon

Для получения launch images запустите свое приложение на iPhone simulator (симуляторе iPhone), один раз на 3.5-дюймовом и оди раз на  4-дюймовом и сделайте screen shots (cmd-s). The launch images должны быть идентичны первому экрану приложения, за исключением текста и элементов, которые могут изменяться. Откройте полученные  screen shots и уберите все тексты и все изменяемые элементы. Для Matchismo убираем метку счета, кнопку пересдачи карт, переключатель для количества карт, анализируемых на «совпадение» ( 2 карты/ 3 карты) и все, что находится на  the status bar в верхней части экрана:

iOS Simulator Screen shot Aug 26, 2014, 2.40.09 PM

Теперь у вас должно быть два launch images размером  640×960 and 640×1136, которые вы можете перетянуть в ваш  image assets:


Screen Shot 2014-08-26 at 2.59.17 PM

 

The complete code is available on Github.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *