From 2f7cba71bd93ba53d63085d36ebf84cf20073aed Mon Sep 17 00:00:00 2001 From: DevTchernov Date: Wed, 29 Aug 2018 21:32:35 +0700 Subject: [PATCH 1/2] Update readme file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b00e391..fb8057f 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# addNote2 +# addNote2 - Тестовое задание Вадима Пустовойтова на позицию iOS разработчика From 4b9ead12d32ea15292421d6580fa448e4cdd0953 Mon Sep 17 00:00:00 2001 From: Andrey Tchernov Date: Wed, 29 Aug 2018 22:06:36 +0700 Subject: [PATCH 2/2] Update: Review code --- nodeProject.xcodeproj/project.pbxproj | 6 +-- .../UserInterfaceState.xcuserstate | Bin 0 -> 18478 bytes .../xcschemes/xcschememanagement.plist | 14 +++++ nodeProject/ImageViewCell.swift | 7 +-- nodeProject/ViewController.swift | 16 ++++-- nodeProject/addNote.swift | 48 ++++++++++++++++-- 6 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 nodeProject.xcodeproj/project.xcworkspace/xcuserdata/andreytchernov.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 nodeProject.xcodeproj/xcuserdata/andreytchernov.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/nodeProject.xcodeproj/project.pbxproj b/nodeProject.xcodeproj/project.pbxproj index f2a0af8..86d070f 100644 --- a/nodeProject.xcodeproj/project.pbxproj +++ b/nodeProject.xcodeproj/project.pbxproj @@ -20,14 +20,14 @@ /* Begin PBXFileReference section */ 5AD6B8ED211EA1CC0080EA0F /* nodeProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = nodeProject.app; sourceTree = BUILT_PRODUCTS_DIR; }; 5AD6B8F0211EA1CC0080EA0F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 5AD6B8F2211EA1CC0080EA0F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 5AD6B8F2211EA1CC0080EA0F /* ViewController.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; tabWidth = 4; }; 5AD6B8F5211EA1CC0080EA0F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 5AD6B8F8211EA1CC0080EA0F /* nodeProject.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = nodeProject.xcdatamodel; sourceTree = ""; }; 5AD6B8FA211EA1CF0080EA0F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 5AD6B8FD211EA1CF0080EA0F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 5AD6B8FF211EA1CF0080EA0F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5AD6B928211F31670080EA0F /* addNote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = addNote.swift; sourceTree = ""; }; - 5AD6B94B2121C8880080EA0F /* ImageViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewCell.swift; sourceTree = ""; }; + 5AD6B928211F31670080EA0F /* addNote.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = addNote.swift; sourceTree = ""; tabWidth = 4; }; + 5AD6B94B2121C8880080EA0F /* ImageViewCell.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = ImageViewCell.swift; sourceTree = ""; tabWidth = 4; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ diff --git a/nodeProject.xcodeproj/project.xcworkspace/xcuserdata/andreytchernov.xcuserdatad/UserInterfaceState.xcuserstate b/nodeProject.xcodeproj/project.xcworkspace/xcuserdata/andreytchernov.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..9fbf5fcb8a12af39ba39f33a2ba9c6f130cb8098 GIT binary patch literal 18478 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 literal 0 HcmV?d00001 diff --git a/nodeProject.xcodeproj/xcuserdata/andreytchernov.xcuserdatad/xcschemes/xcschememanagement.plist b/nodeProject.xcodeproj/xcuserdata/andreytchernov.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..07a5c73 --- /dev/null +++ b/nodeProject.xcodeproj/xcuserdata/andreytchernov.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + nodeProject.xcscheme + + orderHint + 0 + + + + diff --git a/nodeProject/ImageViewCell.swift b/nodeProject/ImageViewCell.swift index 0d3a236..01db6a3 100644 --- a/nodeProject/ImageViewCell.swift +++ b/nodeProject/ImageViewCell.swift @@ -14,20 +14,21 @@ class ImageViewCell: UICollectionViewCell { var index: NSInteger = 0 - var delegate: ImageViewCellDelegate? = nil + //Review: делегаты должны быть по слабым ссылкам + /* weak */ var delegate: ImageViewCellDelegate? = nil @IBAction func removeImage(_ sender: Any) { + //Review: Проверка на nil не нужна if( delegate != nil ) { delegate?.removePhoto(index: index) } } + //Review: Методы подразумевающие действий называть нужно глаголами - hide() func hidden() { - } func show() { - } } protocol ImageViewCellDelegate { diff --git a/nodeProject/ViewController.swift b/nodeProject/ViewController.swift index d012810..653bcf1 100644 --- a/nodeProject/ViewController.swift +++ b/nodeProject/ViewController.swift @@ -9,14 +9,18 @@ import UIKit import CoreData +//Review: Именование класса. Непонятно что делает конкретно этот контроллер class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, addNoteDelegate { @IBAction func addNoteForm(_ sender: Any) { + //Review: Навигацию лучше через Storyboard делать let vc2 = storyboard?.instantiateViewController(withIdentifier: "addNoteSID") as! addNote vc2.delegate = self navigationController?.pushViewController(vc2, animated: true) } + @IBAction func deleteAll(_ sender: Any) { + //Review: Вынести методы работы с данными в отдельный класс let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext for name in names { @@ -31,20 +35,21 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega tableView.reloadData() } - + //Review: private @IBOutlet weak var tableView: UITableView! var names = [Nodes]() override func viewDidLoad() { super.viewDidLoad() - + //Review: Делается в Storyboard title = "\"The List\"" tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") tableView.delegate = self tableView.dataSource = self } + //Review: Вынести методы делегатов и источников данных в отдельный класс/extension к контроллеру func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return names.count } @@ -57,9 +62,11 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - + //Review: Простую навигацию лучше через Storyboard, передача параметров в методе prepareToSegue let vc2 = storyboard?.instantiateViewController(withIdentifier: "addNoteSID") as! addNote navigationController?.pushViewController(vc2, animated: true) + + //Review: Использование force-cast'ов vc2.titl = names[indexPath.row].name! vc2.info = (names[indexPath.row].info)! let adv: Int = (names[indexPath.row].picturesN?.count)! @@ -94,7 +101,7 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega readData() } - + //Review: Ненужный код override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. @@ -107,6 +114,7 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega } + //Review: Вынести в класс работы с базой данных func readData(){ let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext diff --git a/nodeProject/addNote.swift b/nodeProject/addNote.swift index 7ee400f..646992c 100644 --- a/nodeProject/addNote.swift +++ b/nodeProject/addNote.swift @@ -8,38 +8,56 @@ import UIKit +//Review: Code-style (https://github.com/raywenderlich/swift-style-guide) - Классы с заглавной буквы. Для наследников от Cocoa-классов имя должно заканчиваться на базовый класс. Т.е. AddNoteViewController class addNote: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource, ImageViewCellDelegate { + //Review: Должны быть private, должны быть в MARK секции (код контроллера на несколько страниц) @IBOutlet weak var nameNoteText: UITextField! @IBOutlet weak var infoNoteText: UITextView! + //Review: Опечатка @IBOutlet weak var colleectionViewImages: UICollectionView! @IBOutlet weak var begDateText: UITextField! @IBOutlet weak var updateDateText: UITextField! + //Review: Те поля что дальше должны быть собраны в модель заметки, инициализированной по умолчанию, чтобы не захламлять контроллер и оперировать уже этой моделью + + //Review: Должны быть приватными хотя бы сеттеры - private (set) var names = [Nodes]() var picturesNode = [Pictures]() + //Review: Code-style, именование переменных var titl :String = "" var info = "" + //Review: Должен быть enum тип var type = 0 - var picture = UIImage() + //Review: Зачем пустое изображение?, пусть будет неинициализировано + var picture = UIImage() // let imagePicker = UIImagePickerController() var arrayImage: [UIImage] = [UIImage]() - var delegate: addNoteDelegate? = nil + //Review: Делегаты должны храниться по weak ссылкам (https://medium.com/@JoyceMatos/arc-strong-and-weak-references-in-swift-f2a085a17119, https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html) + /* weak */ var delegate: addNoteDelegate? = nil + + //Review: Должен быть Bool тип var isEdit = 0 + + //Review: методы которые используются только кнутри класса должны быть private @IBAction func saveNote(_ sender: Any) { + //Review: не стоит использовать force cast (!), лучше заменить на (nameNoteText.text ?? "") self.saveName(name: nameNoteText.text!, info: infoNoteText.text, pictures: arrayImage) delegate?.updateTable() navigationController?.popViewController(animated: true) } + override func viewDidLoad() { super.viewDidLoad() + //Review: Хоть что-то кинуть в NSLog в обратном случае if( UIImagePickerController.isSourceTypeAvailable(.photoLibrary)) { imagePicker.delegate = self imagePicker.sourceType = .photoLibrary } + colleectionViewImages.dataSource = self colleectionViewImages.delegate = self @@ -48,18 +66,21 @@ class addNote: UIViewController, UIImagePickerControllerDelegate,UINavigationCon } } + //Review: Ненужный код override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } - func saveName(name: String, info: String, pictures: [UIImage]){ + func saveName(name: String, info: String, pictures: [UIImage]) { + //Review: Работу с базой данных надо выносить в отдельный класс let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext let node = Nodes(entity: Nodes.entity(), insertInto: context) let pictureSave = Pictures(entity: Pictures.entity(), insertInto: context) node.setValue(name, forKey: "name") node.setValue(info, forKey: "info") + //Review: Code-style if isEdit == 0 { node.setValue(NSDate(), forKey: "begDate") @@ -70,6 +91,15 @@ class addNote: UIViewController, UIImagePickerControllerDelegate,UINavigationCon } // let pictureCount = pictures.count // цикл по колличеству картинок если разберусь с таблицей!!! + + //Review: Лучше так + /* + for picture in pictures { + let pictureN = UIImageJPEGRepresentation(picture, 0.0) + pictureSave.setValue(pictureN, forKey: "picture") + node.addToPicturesN(pictureSave) + } + */ if( pictures.count > 0 ) { for index in 0...pictures.count - 1 { let pictureN = UIImageJPEGRepresentation(pictures[index], 0.0) @@ -87,6 +117,7 @@ class addNote: UIViewController, UIImagePickerControllerDelegate,UINavigationCon } } + //Review: Плохо выделять функцию ради одной строчки func presentImagePicker() { present(imagePicker, animated: true, completion: nil) } @@ -140,14 +171,25 @@ class addNote: UIViewController, UIImagePickerControllerDelegate,UINavigationCon if( indexPath.row == arrayImage.count) { presentImagePicker() } + //Review: Добавить сюда снятие выделения + //collectionView.deselectItem(at: indexPath, animated: false) } + //Review: Зачем на Deselect? func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { if( indexPath.row == arrayImage.count) { presentImagePicker() } } } +//Review: Если не получается вынести иточник данных и делегат в отдельный класс (хотя в этом случае можно было бы), то лучше делать вот так: +/* + extension addNote: UICollectionViewDelegate { + ... +} + */ + + protocol addNoteDelegate { func updateTable()