Задание 4 CS193P 2016

94 views
Skip to first unread message

Ilya Dolgopolov

unread,
Jun 26, 2016, 7:53:52 AM6/26/16
to Swift [ru]
Добрый день,

собираюсь приступить к следующему заданию, на много интереснее, чем калькулятор, который порядком надоел))

Вопрос в конце 9-й лекции Пол говорит, что выложит код, который он не успел показать, который должен показываться больше 100 твитов, где его можно вязть?
на сайте http://web.stanford.edu/class/cs193p/cgi-bin/drupal/ только "голый" проект, ровно то, что на экране

tatiana.kornilova

unread,
Jun 26, 2016, 9:39:30 AM6/26/16
to Swift [ru]
Он говорил о включении refresh Control, это когда тянешь вниз таблицу и идет новая выборка;




воскресенье, 26 июня 2016 г., 14:53:52 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov (llodi)

unread,
Jun 26, 2016, 9:42:48 AM6/26/16
to tatiana.kornilova, Swift [ru]
Да, спасибо, я уже нагуглил, работаю над этим, 


правда я программно:

    override func viewDidLoad() {
        super.viewDidLoad()
        //динамическая высота полей
        tableView.estimatedRowHeight = tableView.rowHeight
        tableView.rowHeight  = UITableViewAutomaticDimension
        print ("tweets count \(tweets.count)")
        refreshControl = UIRefreshControl()
        refreshControl?.attributedTitle = NSAttributedString(string: "Идет обновление...")
        refreshControl?.addTarget(self, action: #selector(TweetTableViewController.refresh), forControlEvents: UIControlEvents.ValueChanged)

    }

    

    @objc private func refresh (sender:AnyObject) {
        searchForTweets ()
        tableView.reloadData()
        refreshControl?.endRefreshing()
    }

И тут у меня вопрос, как выяснить заполнено ли TableView, т.е. если не пустое то выполнять:

        refreshControl = UIRefreshControl()
        refreshControl?.attributedTitle = NSAttributedString(string: "Идет обновление...")
        refreshControl?.addTarget(self, action: #selector(TweetTableViewController.refresh), forControlEvents: UIControlEvents.ValueChanged)

Ilya Dolgopolov (llodi)



26 июня 2016 г., в 16:39, tatiana.kornilova <tatiana....@gmail.com> написал(а):

--
Вы получили это сообщение, поскольку подписаны на одну из тем в группе "Swift [ru]".
Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/14B4-hpLjng/unsubscribe.
Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+u...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес swi...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/swiftru/8bb6f98f-67bc-4059-be6a-0ca9a2ba0330%40googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Ilya Dolgopolov

unread,
Jun 26, 2016, 1:49:16 PM6/26/16
to Swift [ru]
В итоге, раелизация update есть на сайте stanford :) сделал по правильному, но у меня снова непонимание, логическое (

в методе searchForTweets ()

с начала мы присваиваем lastTwitterRequest = request
затем извлекаем данные и сравниваем:

if request == weakSelf?.lastTwitterRequest


Вот тут то как раз и не понимание, когда оно может не равняться друг другу?

если request.fetchTweets подзавис, и в этом время я ввожу новый запрос и его запускаю,

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

воскресенье, 26 июня 2016 г., 14:53:52 UTC+3 пользователь Ilya Dolgopolov написал:
Добрый день,

Ivan Lazarev

unread,
Jun 26, 2016, 2:22:54 PM6/26/16
to Swift [ru]
Илья, может поделитесь сразу ссылкой, чтобы потом время на поиск не терять?)

Ilya Dolgopolov (llodi)

unread,
Jun 26, 2016, 2:33:59 PM6/26/16
to Ivan Lazarev, Swift [ru]
Вот :)
http://cs193p.stanford.edu

---
Best regards,
Ilya

> 26 июня 2016 г., в 21:22, Ivan Lazarev <i.s.l...@gmail.com> написал(а):
>
> Илья, может поделитесь сразу ссылкой, чтобы потом время на поиск не терять?)
>
> --
> Вы получили это сообщение, так как подписаны на группу "Swift [ru]".
> Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/14B4-hpLjng/unsubscribe.
> Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+u...@googlegroups.com.
> Чтобы добавлять сообщения в эту группу, отправьте письмо по адресу swi...@googlegroups.com.
> Просмотреть это обсуждение в Сети можно по адресу https://groups.google.com/d/msgid/swiftru/53356bc9-6387-44e3-ba4b-e381fcd18db7%40googlegroups.com.
> Настройки подписки и доставки писем: https://groups.google.com/d/optout.

Ivan Lazarev

unread,
Jun 26, 2016, 2:35:21 PM6/26/16
to Swift [ru], i.s.l...@gmail.com
класс, спасибо!

воскресенье, 26 июня 2016 г., 21:33:59 UTC+3 пользователь Ilya Dolgopolov написал:
Вот :)
http://cs193p.stanford.edu

---
Best regards,
Ilya

> 26 июня 2016 г., в 21:22, Ivan Lazarev <i.s.l...@gmail.com> написал(а):
>
> Илья, может поделитесь сразу ссылкой, чтобы потом время на поиск не терять?)
>
> --
> Вы получили это сообщение, так как подписаны на группу "Swift [ru]".
> Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/14B4-hpLjng/unsubscribe.
> Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+unsubscribe@googlegroups.com.

tatiana.kornilova

unread,
Jun 26, 2016, 3:28:03 PM6/26/16
to Swift [ru]
Это связано с многопоточным программированием. 
 Присваивание lastTwitterRequest = request работает в том потоке, в котором запущен запрос на выборку твитов.  Сколько запросов столько lastTwitterRequest. А request каждый раз новый, он на  main queque (главном потоке). Каждый из запущенных на выборку потоков возвращается на main queque (главном потоке) благодаря

    dispatch_async(dispatch_get_main_queue()) {

                    if request == weakSelf?.lastTwitterRequest 

со своим lastTwitterRequest, записанном в том потоке, в котором он стартовал. Возвращается он на main queque (главном потоке) с целью построить изображение или сделать что-то другое с UI. А request, находясь на на main queque (главном потоке), может измениться. Вот мы и сравниваем их, чтобы решить, а не опоздал ли он со своим lastTwitterRequest.
Об этом очень подробно профессор рассказывает на Лекции 8. Все то же самое, но идет выборка изображений.
воскресенье, 26 июня 2016 г., 20:49:16 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov (llodi)

unread,
Jun 27, 2016, 12:18:53 AM6/27/16
to tatiana.kornilova, Swift [ru]
А получается fetchTweets выполняется в другом? А где это определено? Смотрел исходники там этого нет. А в cassini, Пол выносил из главного треда тяжелую операцию, и возвращал результат в главный. А тут результат сразу в главный возвращается.. Непонятно (

---
Best regards,
Ilya

26 июня 2016 г., в 22:28, tatiana.kornilova <tatiana....@gmail.com> написал(а):

--
Вы получили это сообщение, поскольку подписаны на одну из тем в группе "Swift [ru]".

Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/14B4-hpLjng/unsubscribe.
Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+u...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес swi...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/swiftru/1abb6557-de3b-4b15-8ded-57b2101ffac0%40googlegroups.com.

tatiana.kornilova

unread,
Jun 27, 2016, 3:14:04 AM6/27/16
to Swift [ru], tatiana....@gmail.com
Запрос к Twitter ассинхронный, следовательно исполняется в другом потоке и вам возвращается handler в виде замыкания. Такого API очень много в iOS

 

понедельник, 27 июня 2016 г., 7:18:53 UTC+3 пользователь Ilya Dolgopolov написал:
Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+unsubscribe@googlegroups.com.

Ilya Dolgopolov

unread,
Jun 27, 2016, 2:05:55 PM6/27/16
to Swift [ru]
Я начал делать 4-е задание, пункт с подкрашиванием различных элементов

собственно вопросов много: один из них что за цифры в скобках?









я использую элементы 

    public let hashtags: [Mention]

    public let urls: [Mention]

    public let userMentions: [Mention]

для "подкрашивания"


let myAttribute = [ NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleBody) ]

            let myString = NSMutableAttributedString(string: tweet.text, attributes: myAttribute )

            

            tweetTextLabel?.attributedText = myString

            

            if tweetTextLabel?.text != nil {

                for _ in tweet.media {

                    tweetTextLabel.text! += " 📷"

                }

                

                for url in tweet.userMentions {

                    let myAttributes1 = [ NSForegroundColorAttributeName: UIColor.blueColor() ]

                    let attrString3 = NSAttributedString(string: " " + String(url), attributes: myAttributes1)

                    myString.appendAttributedString(attrString3)

                    tweetTextLabel.attributedText =  myString

                }

            }



но мне кажется я иду не в том направлении..

в атрибуте tweet.text уже есть все элементы, текст, хештеги, ссылки

т.е. нужно из текста их как-то выделать и изменять стиль? или то, как я делаю норм?


Ilya Dolgopolov

unread,
Jun 27, 2016, 2:08:24 PM6/27/16
to Swift [ru]

что-то мне подсказывает, цифры это range где находиться элемент в text

Ilya Dolgopolov (llodi)

unread,
Jun 27, 2016, 2:12:54 PM6/27/16
to Swift [ru]
Точно! 

там свойство даже есть nsrange есть свет в конце тонеля

можно использовать этот range чтобы выделять особым стилем нужные части

Ilya Dolgopolov

unread,
Jun 27, 2016, 2:31:40 PM6/27/16
to Swift [ru]
ура, ура, ура :)

я разобрался, поговорил тут сам с собой ))

код выглядет так, но я еще поиграюсь с ним :)

            let myAttribute = [ NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleBody) ]

            let myString = NSMutableAttributedString(string: tweet.text, attributes: myAttribute )

         

            for hash in tweet.hashtags {

                myString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: hash.nsrange)

            }

            

            for url in tweet.urls {

                myString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: url.nsrange)

            }

            

            for userMention in tweet.userMentions {

                myString.addAttribute(NSForegroundColorAttributeName, value: UIColor.orangeColor(), range: userMention.nsrange)

            }

            

            if tweetTextLabel?.text != nil {

                for _ in tweet.media {

                    //tweetTextLabel.text! += " 📷"

                }

            }

            

            tweetTextLabel?.attributedText = myString



итоговый результат:

нужно еще tweetTextLabel.text! += " 📷" реализовать













Ilya Dolgopolov

unread,
Jun 28, 2016, 1:22:48 PM6/28/16
to Swift [ru]
Татьяна, объясните пож-та почему 

var tweets = [Array<Twitter.Tweet>]()

а не просто массив?

ведь в таблице каждый твит - это 1 секция или одна строка, всегда одной секции?

Ilya Dolgopolov

unread,
Jun 28, 2016, 1:48:56 PM6/28/16
to Swift [ru]
и еще вопрос, почему-то у меня не работает segue 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == Storyboard.DetailedSequeIdentifier {

            if let dttvc = segue.destinationViewController as? DetailedTweetTableViewController {

                let cell = (sender as? TweetTableViewCell)?.tweet

                print(cell?.description)

                dttvc.tweet = cell

            }

        }

    }


а именно if let dttvc = segue.destinationViewController asDetailedTweetTableViewController
в дебагере segue - UIViewController, а не UITableViewController
мой контроллер: class DetailedTweetTableViewController: UITableViewController


Ilya Dolgopolov

unread,
Jun 28, 2016, 1:57:59 PM6/28/16
to Swift [ru]
нашел косяк

    // MARK: - Navigation

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == Storyboard.DetailedSequeIdentifier {

            if let navcon = segue.destinationViewController as? UINavigationController {

                if let dttvc = navcon.visibleViewController as? DetailedTweetTableViewController {

                    let cell = (sender as? TweetTableViewCell)?.tweet

                    dttvc.tweet = cell

                }

            }

        }

    }


вторник, 28 июня 2016 г., 20:48:56 UTC+3 пользователь Ilya Dolgopolov написал:

tatiana.kornilova

unread,
Jun 28, 2016, 2:17:17 PM6/28/16
to Swift [ru]
Кстати, если внимательно послушаете Лекцию 7, а именно ту часть, что касается extentions (расширений), то можно написать весь этот код с  UINavigationController и парой if всего одной строкой. Там Пол предлагает хороший приемчик.

вторник, 28 июня 2016 г., 20:57:59 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov (llodi)

unread,
Jun 28, 2016, 2:18:25 PM6/28/16
to tatiana.kornilova, Swift [ru]
Да я уже пробовал, че-т у меня не получалось, еще раз попробую

Ilya Dolgopolov (llodi)



28 июня 2016 г., в 21:17, tatiana.kornilova <tatiana....@gmail.com> написал(а):

--
Вы получили это сообщение, поскольку подписаны на одну из тем в группе "Swift [ru]".
Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/14B4-hpLjng/unsubscribe.
Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+u...@googlegroups.com.

Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес swi...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/swiftru/932aa9cb-1ddf-4b37-8efd-46e5bcba8b5a%40googlegroups.com.

Ilya Dolgopolov

unread,
Jun 29, 2016, 2:26:17 AM6/29/16
to Swift [ru]
У меня почему-то нет кнопки back после перехода из твита  в другой TableView


Auto Generated Inline Image 1

tatiana.kornilova

unread,
Jun 29, 2016, 3:27:01 AM6/29/16
to Swift [ru]
Зачем вам второй  Navigation Controller?

среда, 29 июня 2016 г., 9:26:17 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jun 29, 2016, 3:40:35 AM6/29/16
to Swift [ru]
Чтобы был заголовок..

tatiana.kornilova

unread,
Jun 29, 2016, 3:43:49 AM6/29/16
to Swift [ru]
Достаточно одного в вашей схеме - у всех последующий будут заголовки, ведь это это же стэк - "стопка карт" по образной терминологии Пола. Второй делают лишь в Split View Controller  для Detail.

среда, 29 июня 2016 г., 10:40:35 UTC+3 пользователь Ilya Dolgopolov написал:
Чтобы был заголовок..

Ilya Dolgopolov

unread,
Jun 29, 2016, 9:27:39 AM6/29/16
to Swift [ru]
У меня почему-то не работает авто height для текстовых полей, я погуглил как вообще реализовывать, на примере сделал.
для ImageView свойство Mode выставлено как Aspect Fit в инснпекторе





Auto Generated Inline Image 1

Ilya Dolgopolov

unread,
Jun 29, 2016, 11:57:41 AM6/29/16
to Swift [ru]
Заработало, самое интересное, что ничего не менял, просто пришел домой и на маке заново запустил



воскресенье, 26 июня 2016 г., 14:53:52 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jun 29, 2016, 1:12:38 PM6/29/16
to Swift [ru]
моя работа, начала так сказать
https://github.com/llodi/Smashtag_cs193p_Spring

Пока добавил 2-й table  view controller, сделал 3 секции: фото, хэштеги и упоминания (забыл url, сделаю)

я сделал без enum, с ним не плохо выглядет (видел несколько примеров), но пусть будет как альтернатива
и я не передаю весь твит, а только то, что нужно

воскресенье, 26 июня 2016 г., 14:53:52 UTC+3 пользователь Ilya Dolgopolov написал:
Добрый день,

Ilya Dolgopolov

unread,
Jun 30, 2016, 3:28:05 AM6/30/16
to Swift [ru]
Вопрос по заданию, п. 5:
Написано "The view controller to which you segue must work identically to the main Tweet-viewing view controller (TweetTableViewController)"

Нужно реализовывать отдельный TableViewController или можно использовать TweetTableViewController? в примерах за прошлый год использовали TweetTableViewController
но тут формулировка такая: что не понятно.

Ilya Dolgopolov

unread,
Jun 30, 2016, 4:51:42 AM6/30/16
to Swift [ru]
И еще вопрос:

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

Можно передавать UIImage, а не качать по ссылке снова?
насколько это соответствует парадигме MVC?

tatiana.kornilova

unread,
Jun 30, 2016, 7:26:48 AM6/30/16
to Swift [ru]
 Вы можете себе придумать любую Модель, в том числе и UIImage. Как вы понимаете, судя по Лекции 8, в Стэнфорде слишком быстрый интернет и для того, чтобы показать проблему профессор вынужден брать огромной емкости изображения. Так что для них - проще передать url. Если хотите сделать что-то другое - пожалуйста.

четверг, 30 июня 2016 г., 11:51:42 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jun 30, 2016, 7:39:07 AM6/30/16
to Swift [ru]
не дождавшись ответа тут, создал вопрос тут http://stackoverflow.com/questions/38120926/is-it-correct-to-send-uiimage-between-two-controllers

может быть кому-то пригодиться.

tatiana.kornilova

unread,
Jun 30, 2016, 7:44:56 AM6/30/16
to Swift [ru]
Я думаю это прекрасный помощник, мы все им пользуемся. 

четверг, 30 июня 2016 г., 14:39:07 UTC+3 пользователь Ilya Dolgopolov написал:

Ivan Lazarev

unread,
Jun 30, 2016, 8:03:47 AM6/30/16
to Swift [ru]
возможно кто-то еще, как я, застрял пока на втором задании, которое, из-за нехватки времени только доделываю, так что просто не дошел еще до момента, чтобы ответить

четверг, 30 июня 2016 г., 14:39:07 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jul 1, 2016, 7:23:48 AM7/1/16
to Swift [ru]
Привет,

Спешу поделиться классной штукой, реализацией открытия web-страниц для задания, п. 6 ( с начала я сделал как hint 17, потом через отбельный контроллер и webView)
но по гуглив, я нашел способ более удобные и очень популярный сейчас:

нужно в наш MentionController (тот в котором мы открываем твит, у меня он назван DatailedTweet), добавить:
import SafariServices



Затем в реализации segue (у каждого своя):


 let safariVC
= SFSafariViewController(URL: NSURL(string: url)!)
 
 
self.presentViewController(safariVC, animated: true, completion: nil)


и вауля, удобный браузер (кстати эта фича только ios9, можно делать проверку
if #available(iOS 9, *), но xcode пишет смысла в этом нет)


Auto Generated Inline Image 1
Auto Generated Inline Image 2

Ilya Dolgopolov

unread,
Jul 1, 2016, 7:26:18 AM7/1/16
to Swift [ru]
Кстати мой код тут https://github.com/llodi/Smashtag_cs193p_Spring

для изображений autozoom to fit, я сделал релаизацию, когда юзеру нужно сделать tap чтобы сработал autozoom to fit

пятница, 1 июля 2016 г., 14:23:48 UTC+3 пользователь Ilya Dolgopolov написал:

Ivan Lazarev

unread,
Jul 1, 2016, 7:26:38 AM7/1/16
to Swift [ru]
Илья, спасибо, полезная вещь!

пятница, 1 июля 2016 г., 14:23:48 UTC+3 пользователь Ilya Dolgopolov написал:

tatiana.kornilova

unread,
Jul 1, 2016, 12:01:22 PM7/1/16
to Swift [ru]
Спасибо. Делитесь с нами интересными находками.

пятница, 1 июля 2016 г., 14:23:48 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jul 2, 2016, 5:46:52 AM7/2/16
to Swift [ru]
После добавление TabBar  сделал еще одну интересную вещь: если скролить вниз список то, чтобы вернуть наверх, нужно лишь нажать на название текущей  вкладки внизу tabBar'а:


После добавления TabBarController в Storyboard создал класс "SmashtagBarViewController" и добавил следование протоколу "UITabBarControllerDelegate"

в viewDidLoad добавил "self.delegate = self"

и реализовал метод:

    func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {

        if let navcon = viewController as? UINavigationController {

            if let vc = navcon.visibleViewController as? UITableViewController {

                vc.tableView.setContentOffset(CGPointZero, animated: true)

            }

        }

    }

Теперь если в Search вкладке вы отлистали список твитов вниз, нажав на название item'а Search, вы перемещаетесь наверх (почти на верх, т.е. наверх TableView)



https://github.com/llodi/Smashtag_cs193p_Spring



Ilya Dolgopolov

unread,
Jul 2, 2016, 10:32:22 AM7/2/16
to Swift [ru]
у меня проблема (( Нужна помощь

пытаюсь реализовать hint с Collection View, но по своему: отдельный таб, щелкнув на который открывается коллекция фото, что найдена по последнему поиску


но мультитрейдинг не работает и твиты не получаются и фото не грузятся ((

при этом вкладка с поиском работает ((


Ilya Dolgopolov

unread,
Jul 2, 2016, 10:49:00 AM7/2/16
to Swift [ru]
Нашел косяк, был в идентификаторе элемента коллекции

Ilya Dolgopolov

unread,
Jul 3, 2016, 2:33:21 AM7/3/16
to Swift [ru]
Мой вариант Smashtag (добавил иконки), думаю с 4-й Assignment хватит, нужно двигаться дальше, если конеш откровенных багов не встретиться



кстати закачал приложение на телефон ) работает )

Ivan Lazarev

unread,
Jul 3, 2016, 4:59:35 PM7/3/16
to Swift [ru]
жду не дождусь доделать 3-е задание, чтобы приступить очень интересному 4-му :)

кстати, профессор часто использует какой-то механизм xcode когда кусок кода вытаскивается из контекста...что это такое?



воскресенье, 3 июля 2016 г., 9:33:21 UTC+3 пользователь Ilya Dolgopolov написал:

tatiana.kornilova

unread,
Jul 3, 2016, 10:12:28 PM7/3/16
to Swift [ru]
Это авто продолжение кода. Если вы, например, набираете код инициализатора "CGPoint ( ", то после круглой скобки, если немного подождать, появится картинка с возможными продолжениями кода, то есть выдаст все инициализаторы

 
То же самое с методами какого-нибудь объекта. Если вы наберете экземпляр объекта, а затем точку "." и немного подождете, то появятся все возможные методы и свойства этого объекта и типа объекта:



такая же ситуация с любыми идентификаторами - вы только начинаете набирать буквы и компилятор вам уже подсказывает, что есть в контексте на эти набранные буквы:


воскресенье, 3 июля 2016 г., 23:59:35 UTC+3 пользователь Ivan Lazarev написал:
жду не дождусь доделать 3-е задание, чтобы приступить очень интересному 4-му :)

кстати, профессор часто использует какой-то механизм xcode когда кусок кода вытаскивается из контекста...что это такое?


Этим надо обязательно пользоваться, иначе невозможно набирать длинные идентификаторы.
Кстати, 3-е Задание реально очень трудное и потребует от вас значительного времени. Если вам хочется выполнять Задание 4, то вы можете поступить как Илья - начать выполнять Задание 4, оно совершенно не зависит от Заданий 1, 2 и 3. Вам понадобиться прочесть Лекцию 8 и 9. А потом, когда будет время и желание, вернуться к Заданию 3, потому что это уже "высший пилотаж".

Ilya Dolgopolov

unread,
Jul 4, 2016, 1:16:39 AM7/4/16
to Swift [ru]
Я кстати так и добил большую часть 3 задания, и даже начал понимать алгебру/геометрию, что там заложена, именно поэтому оно для меня сложное было, я уже все напрочь забыл, память плоха )))

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

tatiana.kornilova

unread,
Jul 4, 2016, 2:49:14 AM7/4/16
to Swift [ru]
Там даже не геометрия представляет собой сложность. По-моему это единственное задание, где нужно писать и читать из местной памяти NSUserDefaults, а это делается в Swift очень просто и изящно с помощью вычисляемых переменных. Это задание все пронизано вычисляемыми переменными, причем не типа "давайте что-то посчитаем", а когда одна вычисляемая переменная управляет другой, хранимой и сочетанием private и public. Еще одна важная вещь в этом задании - замена делегирования на передачу замыканий. Профессор в этом курсе по iOS 9 стал проводить идею, что лучше пользоваться передачей замыканий вместо делегирования. Этого не было в курсе iOS 8. 
Но все это можно почитать в постах, посвященных Заданию 3 iOS 9, там я подробно все описываю, в том числе и геометрию, ориентируясь на тех, кто забыл. Так что на досуге можно посмотреть. 

понедельник, 4 июля 2016 г., 8:16:39 UTC+3 пользователь Ilya Dolgopolov написал:

Ivan Lazarev

unread,
Jul 4, 2016, 2:56:06 AM7/4/16
to Swift [ru]
получается, если это автокомплит, то получается, что у профессора подключены какие-то макросы (напр. closedeye) с кодом для примеров?

3-его задания я не боюсь, и пока что не тороплюсь, начну выполнять его, думаю, что не зря профессор продумывал логику своего курса, зато потом, возможно, другие задания после этого будут легче даваться :)

понедельник, 4 июля 2016 г., 5:12:28 UTC+3 пользователь tatiana.kornilova написал:

tatiana.kornilova

unread,
Jul 4, 2016, 3:32:48 AM7/4/16
to Swift [ru]
Да, я невнимательно посмотрела ваш вопрос. Это работа с библиотекой snippet codes (с фрагментами кода), в Области Утилит

В этой библиотеке можно разместить свой фрагмент и дать ему shortcut для автокомплита. Что и сделал профессор. На эту тему можно посмотреть статью Xcode-Snippet - http://nshipster.com/xcode-snippets/




понедельник, 4 июля 2016 г., 9:56:06 UTC+3 пользователь Ivan Lazarev написал:

Ivan Lazarev

unread,
Jul 4, 2016, 4:09:12 AM7/4/16
to Swift [ru]
теперь понятно, спасибо!

понедельник, 4 июля 2016 г., 10:32:48 UTC+3 пользователь tatiana.kornilova написал:

Ilya Dolgopolov

unread,
Jul 4, 2016, 12:38:45 PM7/4/16
to Swift [ru]
кстати, я сделал некоторые улучшения, логики, что я реализовал:

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

    var clickedItemOld: UITabBarItem?

    

    var clickedItem: UITabBarItem? {

        didSet {

            clickedItemOld = oldValue

        }

    }

    

    override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {

        clickedItem = item

    }

    

 

    // UITabBarControllerDelegate

    func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {

        

        if tabBarController.tabBar.selectedItem == clickedItemOld ?? tabBarController.tabBar.selectedItem {

            if let navcon = viewController as? UINavigationController {

                if let vc = navcon.visibleViewController as? UITableViewController {

                    vc.tableView.scrollRectToVisible(vc.tableView.frame, animated: true)

                }

                

                if let vc = navcon.visibleViewController as? UICollectionViewController {

                    vc.collectionView?.scrollRectToVisible(vc.collectionView!.frame, animated: true)

                }

            }

        }

    }



2. сделал тож самое для Collection View
3. сделал Refresh для Collection View
4. Сделал кнопку edit ( котороя меняется на done, когда в режиме редактирования) для recent search

В итоге я поймал кайф: узнал столько фич, которые мне понадобиться в будущем для реализации моих будущих идей и приложений

Хотелось бы более глубоко изучить collection layout, не на уровне копи/паста чужого кода, а на уровне понимания, но видать пока мне это не дано - сложно, может быть в будущем


проект как всегда тут https://github.com/llodi/Smashtag_cs193p_Spring
но с началом лекции 11

tatiana.kornilova

unread,
Jul 4, 2016, 1:08:47 PM7/4/16
to Swift [ru]
Илья, я обязательно посмотрю ваш код, но когда дойду до Задания 4.

понедельник, 4 июля 2016 г., 19:38:45 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jul 5, 2016, 7:29:16 AM7/5/16
to Swift [ru]
Кстати, еще одна вещь, о которой не было сказано Полом или кем-то, для нашей поисковой строки лучше выбрать специальный тип клавиатуры, чтобы удобнее было набирать хэштеги и mention
Там же еще некоторое кол-во настроек






Auto Generated Inline Image 1

tatiana.kornilova

unread,
Jul 5, 2016, 9:05:32 AM7/5/16
to Swift [ru]
Он говорит об этом очень кратко в конце Лекции 8, когда говорит о типе клавиатуре, но не так, чтобы что-то понять и показать. Я думаю таких вещей очень много. Дело в том, что в Стэнфорде очень многое отдано на самостоятельную работу и подразумевается, что студенты в процессе выполнения Заданий сами должны добывать необходимую информацию. Этим и интересны Задания, так как там всплывает очень много вопросов, которых на лекции все не расскажешь. Но у них есть Piazza, и они там очень эффективно обмениваются сведениями друг с другом, а может и с другими студентами, которые закончили этот курс раньше. Кроме того, они могут там задать вопрос и Полу Хэгерти.

вторник, 5 июля 2016 г., 14:29:16 UTC+3 пользователь Ilya Dolgopolov написал:

Ivan Lazarev

unread,
Jul 31, 2016, 5:35:58 AM7/31/16
to Swift [ru]
Всем привет!
Начал 4-е задание (https://github.com/ballard/Smashtag):
Попробовал реализовать 1-ый пункт required tasks:


вроде бы работает, но почему-то, не для всех твитов...

Ivan Lazarev

unread,
Aug 22, 2016, 5:31:52 AM8/22/16
to Swift [ru]
реализация основных пунктов 4-го задания - https://github.com/ballard/Twitter-client-sc193p

Artem Salimyanov

unread,
Sep 9, 2016, 10:02:30 AM9/9/16
to Swift [ru]
Добрый день.
Пытаюсь реализовать дополнительный пункт 3 для 4-го задания.
В случае стартового MVC TweetTableViewController может быть как root, так и нет, если мы пришли на него не со старта приложения, а "углубились" до него.
Так образом кнопку для этого MVC нужно добавлять в коде, но мой код для добавления кнопки не работает (код ниже).
При первом запуске print выводит 1, а все остальные разы когда мы попадаем на это MVC nil, не понимаю почему так, объясните пожалуйста как это работает?

    override func viewDidLoad() {

        super.viewDidLoad()

        tableView.estimatedRowHeight = tableView.rowHeight

        tableView.rowHeight = UITableViewAutomaticDimension

        

        let toRoot = UIBarButtonItem(barButtonSystemItem: .Stop,

                                     target: self,

                                     action: #selector(TweetTableViewController.toRootViewController(_:)))

        

        print("Количество карт в стеке: \(navigationController?.viewControllers.count)")

        if navigationController?.viewControllers.count > 1 {

            if navigationController?.viewControllers.count > 0 {

                navigationItem.rightBarButtonItem = toRoot

            }

        }

        

    }

Ivan Lazarev

unread,
Sep 9, 2016, 10:09:27 AM9/9/16
to Swift [ru]
Добрый день!
Попробуйте реализовать Ваш код во viewDidAppear, и, кстати, есть замечательный метод popToRootViewControllerAnimated...


пятница, 9 сентября 2016 г., 17:02:30 UTC+3 пользователь Artem Salimyanov написал:

Artem Salimyanov

unread,
Sep 9, 2016, 10:48:43 AM9/9/16
to Swift [ru]
Иван, спасибо.
Реализация во viewDidAppear помогла.
Но я все равно не понимаю почему этот код не работал во viewDidLoad, получается в этот момент MVC еще не знает, что находится  в NavigationController?


пятница, 9 сентября 2016 г., 17:09:27 UTC+3 пользователь Ivan Lazarev написал:

Ivan Lazarev

unread,
Sep 9, 2016, 11:15:38 AM9/9/16
to Swift [ru]
Артем , viewDidLoad не всегда вызывается при переходах в navigation

tatiana.kornilova

unread,
Sep 9, 2016, 3:12:44 PM9/9/16
to Swift [ru]
Артем, я тоже использовала viewDidLoad, и у меня была абсолютно ваша ситуация.
Проведя определенные исследования, я установила, что в viewDidLoad если грузится root,  то navigationController не nil и число  navigationController?.viewControllers.count = 1. Если же вы попали в  viewDidLoad НЕ как root, то navigationController равен nil и соответственно  navigationController?.viewControllers.count = nil.
Поэтому в viewDidLoad выражение navigationController?.viewControllers.count принимает только два значения: либо 1 (единственный раз при загрузке приложения), либо nil. Причем 1 действительно появляется только один раз, потому что вы знаете, что  viewDidLoad для root вызывается только один раз при инициализации со storyboard, а потом он сидит постоянно в стэке и для него viewDidLoad больше не вызывается.
Объяснение, почему не стоит использовать в viewDidLoad navigationController состоит в следующем:
До тех пор, пока вы не сделаете push для своего UIViewController, его свойство navigationController  будет nil, а метод viewDidLoad всегда вызывается ПЕРЕД push.  Так что в методе  viewDidLoad  свойство navigationController  не определено и равно nil
К тому времени, когда вызываются методы viewWillAppear  и viewDidAppear, push прошел,  navigationController определен и не nil, так что  navigationController?.viewControllers.count будет считаться правильно.
Можете поставить печать в viewDidLoad и viewWillAppear (позже скажу почему он лучше  viewDidAppear) и убедиться в этом:

    override func viewDidLoad() {

        super.viewDidLoad()

.  .  .  .  

 if let navcon = navigationController{

            print ("DidLoad count = \(navcon.viewControllers.count)")

            

        } else {

            print ("DidLoad navigation \(navigationController)")

            

        }

.  .  .  .
}

    override func viewWillAppear(animated: Bool) {

          super.viewWillAppear(animated)

        if let navcon = navigationController{

            print ("WillAppear \(navcon.viewControllers.count)")

           

            } else {

            print ("WillAppear \(navigationController)")


        }

    }

Вот что вывелось на консоль:

DidLoad count = 1

WillAppear 1

DidLoad navigation nil

WillAppear 3

DidLoad navigation nil

WillAppear 5

DidLoad navigation nil

WillAppear 7

WillAppear 1  // нажата кнопка возврата


Так что Иван прав, но по-моему лучше использовать viewWillAppear , а не viewDidAppear, чтобы после появления на экране кнопки не прыгали.
Вывод: свойство  navigationController не определено в viewDidLoad и нужно использовать метод  viewWillAppear.
Я выкрутилась и анализирую  navigationController в viewDidLoad на nil, но это плохое решение - буду переделывать. 
Так что Ивану спасибо.

 
пятница, 9 сентября 2016 г., 15:48:43 UTC+1 пользователь Artem Salimyanov написал:

Ivan Lazarev

unread,
Sep 9, 2016, 5:24:04 PM9/9/16
to Swift [ru]
Спасибо Татьяне за столь развернутый и детализированный комментарий!
Действительно, возможно лучшим решением будет воспользоваться viewWillAppear, дело в том, что в своем решении я добавлял кнопку на storyboard и использовал show/hide для нее, поэтому при использовании viewDidAppear вопросов к поеведениею ui у меня не было.

пятница, 9 сентября 2016 г., 22:12:44 UTC+3 пользователь tatiana.kornilova написал:
Reply all
Reply to author
Forward
0 new messages