├── Marvel-Hero ├── .DS_Store ├── Assets.xcassets │ ├── Contents.json │ ├── .DS_Store │ ├── star.imageset │ │ ├── star.png │ │ └── Contents.json │ ├── filled.imageset │ │ ├── filled.png │ │ └── Contents.json │ ├── no_avatar.imageset │ │ ├── no_avatar.png │ │ └── Contents.json │ ├── Marvel.imageset │ │ ├── iTunesArtwork@1x.png │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── PageHandler.swift ├── Models │ ├── GlobalModels │ │ ├── DateElement.swift │ │ ├── Price.swift │ │ ├── Next.swift │ │ ├── Series.swift │ │ ├── URLElement.swift │ │ ├── CreatorsItem.swift │ │ ├── Extension.swift │ │ ├── URLType.swift │ │ ├── Characters.swift │ │ └── Creators.swift │ ├── Comics │ │ ├── TextObject.swift │ │ ├── DataClassCo.swift │ │ ├── JsonRepreseCo.swift │ │ └── ResultCo.swift │ ├── Chars │ │ ├── ComicsItem.swift │ │ ├── DataClass.swift │ │ ├── StoriesItem.swift │ │ ├── Comics.swift │ │ ├── Stories.swift │ │ ├── JSONReprese.swift │ │ ├── Thumbnail.swift │ │ └── Result.swift │ ├── Stories │ │ ├── ItemSt.swift │ │ ├── OriginalIssueSt.swift │ │ ├── DataClassSt.swift │ │ ├── CreatorsSt.swift │ │ ├── CharactersSt.swift │ │ ├── JsonRepreseSt.swift │ │ └── ResultSt.swift │ ├── Series │ │ ├── DataClassSe.swift │ │ ├── JsonRepreseSe.swift │ │ └── ResultSe.swift │ ├── Events │ │ ├── DataClassEv.swift │ │ ├── StoriesItemEv.swift │ │ ├── StoriesEv.swift │ │ ├── JsonRepreseEv.swift │ │ └── ResultEv.swift │ ├── AuthenticationHandler.swift │ ├── SearchModel.swift │ ├── WebServiceParser.swift │ └── ApiHandler.swift ├── string+md5.swift ├── Controllers │ ├── MainSearchBar.swift │ ├── DetailCell.swift │ ├── HeroCell.swift │ ├── FavoriteController.swift │ ├── SearchController.swift │ ├── MainController.swift │ └── DetailController.swift ├── HashGenerator.swift ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── uiImageView + Downloader.swift ├── AppDelegate.swift └── Views │ ├── DetailCell.xib │ └── HeroCell.xib ├── Marvel-Hero.xcodeproj ├── xcuserdata │ ├── Work.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── mralirezaa.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ ├── Work.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ └── mralirezaa.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── project.pbxproj ├── Marvel-HeroTests ├── Info.plist └── Marvel_HeroTests.swift └── Marvel-HeroUITests ├── Info.plist └── Marvel_HeroUITests.swift /Marvel-Hero/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero/.DS_Store -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/star.imageset/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero/Assets.xcassets/star.imageset/star.png -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/filled.imageset/filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero/Assets.xcassets/filled.imageset/filled.png -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/no_avatar.imageset/no_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero/Assets.xcassets/no_avatar.imageset/no_avatar.png -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/Marvel.imageset/iTunesArtwork@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero/Assets.xcassets/Marvel.imageset/iTunesArtwork@1x.png -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/xcuserdata/Work.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Marvel-Hero/PageHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageHandler.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/24/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/project.xcworkspace/xcuserdata/Work.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero.xcodeproj/project.xcworkspace/xcuserdata/Work.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/xcuserdata/mralirezaa.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/project.xcworkspace/xcuserdata/mralirezaa.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiananvari/Marvel-App/HEAD/Marvel-Hero.xcodeproj/project.xcworkspace/xcuserdata/mralirezaa.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/DateElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DateElement.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | struct DateElement: Codable { 11 | let type, date: String 12 | } 13 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Comics/TextObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextObjectCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | struct TextObject: Codable { 11 | let type, language, text: String 12 | } 13 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/Price.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Price.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Price: Codable { 12 | let type: String 13 | let price: Double 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/Next.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NextCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Next: Codable { 12 | let resourceURI: String 13 | let name: String 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/Series.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Series.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Series: Codable { 12 | let resourceURI: String 13 | let name: String 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/ComicsItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ComicsItem.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ComicsItem : Codable { 12 | let resourceURI: String? 13 | let name: String? 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/URLElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLElement.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct URLElement : Codable { 12 | let type: String? 13 | let url: String? 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/ItemSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Item.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | struct ItemSt: Codable { 11 | let resourceURI: String 12 | let name: String 13 | let role: String 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Series/DataClassSe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataClassSe.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | struct DataClassSe: Codable { 11 | let offset, limit, total, count: Int 12 | let results: [ResultSe] 13 | } 14 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/OriginalIssueSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OriginalIssue.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct OriginalIssueSt: Codable { 12 | let resourceURI: String 13 | let name: String 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Comics/DataClassCo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataClassCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct DataClassCo: Codable { 12 | let offset, limit, total, count: Int 13 | let results: [ResultCo] 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Events/DataClassEv.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataClassCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct DataClassEv: Codable { 12 | let offset, limit, total, count: Int 13 | let results: [ResultEv] 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/CreatorsItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CreatorsItemCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct CreatorsItem: Codable { 12 | let resourceURI: String 13 | let name, role: String 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/DataClassSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataClass.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct DataClassSt: Codable { 12 | let offset, limit, total, count: Int 13 | let results: [ResultSt] 14 | } 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extension.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum Extension : String, Codable { 12 | case gif = "gif" 13 | case jpg = "jpg" 14 | case png = "png" 15 | } 16 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/DataClass.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataClass.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | struct DataClass : Codable { 13 | let offset, limit, total, count: Int? 14 | let results: [Result] 15 | } 16 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/StoriesItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoriesItem.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct StoriesItem : Codable { 12 | let resourceURI: String? 13 | let name: String? 14 | let ItemType: String? 15 | } 16 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Events/StoriesItemEv.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoriesItemCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct StoriesItemEv: Codable { 12 | let resourceURI: String 13 | let name: String 14 | let type: String 15 | } 16 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/URLType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLType.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum URLType : String, Codable { 12 | case comiclink = "comiclink" 13 | case detail = "detail" 14 | case wiki = "wiki" 15 | } 16 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/Comics.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Comics.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Comics : Codable { 12 | let available: Int? 13 | let collectionURI: String? 14 | let items: [ComicsItem]? 15 | let returned: Int? 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Events/StoriesEv.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoriesCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | struct StoriesEv: Codable { 11 | let available: Int 12 | let collectionURI: String 13 | let items: [StoriesItemEv] 14 | let returned: Int 15 | } 16 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/Stories.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Stories.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Stories : Codable { 12 | let available: Int? 13 | let collectionURI: String? 14 | let items: [StoriesItem]? 15 | let returned: Int? 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/CreatorsSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Creators.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct CreatorsSt: Codable { 12 | let available: Int 13 | let collectionURI: String 14 | let items: [ItemSt] 15 | let returned: Int 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/Characters.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CharactersCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Characters: Codable { 12 | let available: Int 13 | let collectionURI: String 14 | let items: [Next] 15 | let returned: Int 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/GlobalModels/Creators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CreatorsCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Creators: Codable { 12 | let available: Int 13 | let collectionURI: String 14 | let items: [CreatorsItem] 15 | let returned: Int 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/CharactersSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Characters.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | struct CharactersSt: Codable { 13 | let available: Int 14 | let collectionURI: String 15 | let items: [OriginalIssueSt]? 16 | let returned: Int 17 | } 18 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Comics/JsonRepreseCo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JsonRepreseCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct JsonRepreseCo: Codable { 12 | let code: Int 13 | let status, copyright, attributionText, attributionHTML: String 14 | let etag: String 15 | let data: DataClassCo 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Events/JsonRepreseEv.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JsonRepreseCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct JsonRepreseEv: Codable { 12 | let code: Int 13 | let status, copyright, attributionText, attributionHTML: String 14 | let etag: String 15 | let data: DataClassEv 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Series/JsonRepreseSe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JsonRepreseSe.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct JsonRepreseSe: Codable { 12 | let code: Int 13 | let status, copyright, attributionText, attributionHTML: String 14 | let etag: String 15 | let data: DataClassSe 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/JsonRepreseSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JsonReprese.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct JsonRepreseSt: Codable { 12 | let code: Int 13 | let status, copyright, attributionText, attributionHTML: String 14 | let etag: String 15 | let data: DataClassSt 16 | } 17 | -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/star.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "star.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/filled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "filled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/no_avatar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "no_avatar.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/Marvel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "iTunesArtwork@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/JSONReprese.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSONReprese.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct JSONReprese: Codable{ 12 | 13 | let code: Int? 14 | let status, copyright, attributionText, attributionHTML: String? 15 | let etag: String? 16 | let data: DataClass? 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/xcuserdata/Work.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Marvel-Hero.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/Thumbnail.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Thumbnail.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Thumbnail : Codable { 12 | let path: String? 13 | let thumbnailExtension: Extension? 14 | 15 | enum CodingKeys: String, CodingKey { 16 | case path 17 | case thumbnailExtension = "extension" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/xcuserdata/mralirezaa.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Marvel-Hero.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Marvel-Hero/string+md5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // string+md5.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/12/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CommonCrypto 11 | 12 | extension String { 13 | func md5() -> String { 14 | let data = Data(utf8) as NSData 15 | var hash = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH)) 16 | CC_MD5(data.bytes, CC_LONG(data.length), &hash) 17 | return hash.map { String(format: "%02hhx", $0) }.joined() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/AuthenticationHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticationHandler.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/12/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class AuthenticationHandler { 12 | 13 | var HashManager = HashGenerator() 14 | 15 | static func getAccessAddress(firstPart : String) -> String{ 16 | 17 | 18 | let finalUrl = "\(firstPart)\(HashGenerator.getAccess())" 19 | 20 | 21 | 22 | return finalUrl 23 | 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/MainSearchBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainSearchBar.swift 3 | // SearchBar 4 | // 5 | // Created by Uladzislau Daratsiuk on 9/9/18. 6 | // Copyright © 2018 Uladzislau Daratsiuk. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainSearchBar: UISearchBar { 12 | 13 | override init(frame: CGRect) { 14 | super.init(frame: frame) 15 | self.translatesAutoresizingMaskIntoConstraints = false 16 | 17 | } 18 | 19 | required init?(coder aDecoder: NSCoder) { 20 | fatalError("init(coder:) has not been implemented") 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Chars/Result.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/19/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Result: Codable { 12 | let id: Int? 13 | let name, resultDescription: String? 14 | let modified: String? 15 | let thumbnail: Thumbnail? 16 | let resourceURI: String? 17 | let comics, series: Comics? 18 | let stories: Stories? 19 | let events: Comics? 20 | let urls: [URLElement]? 21 | 22 | enum CodingKeys: String, CodingKey { 23 | case id, name 24 | case resultDescription = "description" 25 | case modified, thumbnail, resourceURI, comics, series, stories, events, urls 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Marvel-HeroTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Marvel-HeroUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Marvel-Hero/HashGenerator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HashGenerator.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/28/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class HashGenerator { 12 | 13 | 14 | static func getAccess() -> String { 15 | 16 | let timestamp = Int(NSDate().timeIntervalSince1970 * 1000) 17 | // Static Keys From Marver Developers Portal 18 | let publicKey = "da17de630ee01367caf99f049072dd7e" 19 | let privateKey = "91deddd110232c38ef2856da98bcb1cbbb668522" 20 | let hashStyle = "\(timestamp)\(privateKey)\(publicKey)" 21 | 22 | let access = "ts=\(timestamp)&apikey=\(publicKey)&hash=\(hashStyle.md5())" 23 | 24 | return access 25 | 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Stories/ResultSt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | struct ResultSt: Codable { 13 | let id: Int? 14 | let title, resultDescription: String? 15 | let resourceURI: String? 16 | let type: String? 17 | let modified: String? 18 | let thumbnail: Thumbnail? 19 | let creators: CreatorsSt? 20 | let characters, series, comics, events: CharactersSt? 21 | let originalIssue: OriginalIssueSt? 22 | 23 | enum CodingKeys: String, CodingKey { 24 | case id, title 25 | case resultDescription = "description" 26 | case resourceURI, type, modified, thumbnail, creators, characters, series, comics, events, originalIssue 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Events/ResultEv.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResultCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/8/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ResultEv: Codable { 12 | let id: Int? 13 | let title, resultDescription: String? 14 | let resourceURI: String? 15 | let urls: [URLElement?] 16 | let modified: String? 17 | let start, end: String? 18 | let thumbnail: Thumbnail? 19 | let creators: Creators? 20 | let characters: Characters? 21 | let stories: StoriesEv? 22 | let comics, series: Characters? 23 | let next, previous: Next? 24 | 25 | enum CodingKeys: String, CodingKey { 26 | case id, title 27 | case resultDescription = "description" 28 | case resourceURI, urls, modified, start, end, thumbnail, creators, characters, stories, comics, series, next, previous 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Series/ResultSe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResultSe.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ResultSe: Codable { 12 | let id: Int? 13 | let title: String? 14 | let resultDescription: String? 15 | let resourceURI: String? 16 | let urls: [URLElement?] 17 | let startYear, endYear: Int? 18 | let rating: String? 19 | let type: String? 20 | let modified: String? 21 | let thumbnail: Thumbnail? 22 | let creators: Creators? 23 | let characters: Characters? 24 | let stories: Stories? 25 | let comics, events: Characters? 26 | let next, previous: Next? 27 | 28 | enum CodingKeys: String, CodingKey { 29 | case id, title 30 | case resultDescription = "description" 31 | case resourceURI, urls, startYear, endYear, rating, type, modified, thumbnail, creators, characters, stories, comics, events, next, previous 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Marvel-HeroTests/Marvel_HeroTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Marvel_HeroTests.swift 3 | // Marvel-HeroTests 4 | // 5 | // Created by Work on 1/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Marvel_Hero 11 | 12 | class Marvel_HeroTests: XCTestCase { 13 | 14 | override func setUp() { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Marvel-HeroUITests/Marvel_HeroUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Marvel_HeroUITests.swift 3 | // Marvel-HeroUITests 4 | // 5 | // Created by Work on 1/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class Marvel_HeroUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | 16 | // In UI tests it is usually best to stop immediately when a failure occurs. 17 | continueAfterFailure = false 18 | 19 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 20 | XCUIApplication().launch() 21 | 22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 23 | } 24 | 25 | override func tearDown() { 26 | // Put teardown code here. This method is called after the invocation of each test method in the class. 27 | } 28 | 29 | func testExample() { 30 | // Use recording to get started writing UI tests. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/Comics/ResultCo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResultCo.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/9/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ResultCo: Codable { 12 | let id, digitalID: Int? 13 | let title: String? 14 | let issueNumber: Int? 15 | let variantDescription, resultDescription: String? 16 | let modified: String? 17 | let isbn, upc, diamondCode, ean: String? 18 | let issn, format: String? 19 | let pageCount: Int? 20 | let textObjects: [TextObject?] 21 | let resourceURI: String? 22 | let urls: [URLElement?] 23 | let series: Series? 24 | let variants: [Series?] 25 | let collections: [Series?] 26 | let collectedIssues: [Series?] 27 | let dates: [DateElement?] 28 | let prices: [Price?] 29 | let thumbnail: Thumbnail? 30 | let images: [Thumbnail?] 31 | let creators: Creators? 32 | let characters: Characters? 33 | let stories: Stories? 34 | let events: Characters? 35 | 36 | enum CodingKeys: String, CodingKey { 37 | case id 38 | case digitalID = "digitalId" 39 | case title, issueNumber, variantDescription 40 | case resultDescription = "description" 41 | case modified, isbn, upc, diamondCode, ean, issn, format, pageCount, textObjects, resourceURI, urls, series, variants, collections, collectedIssues, dates, prices, thumbnail, images, creators, characters, stories, events 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/DetailCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailCell.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DetailCell: UITableViewCell { 12 | 13 | @IBOutlet weak var DetailImageView: UIImageView! 14 | @IBOutlet weak var NameTextLbl: UILabel! 15 | @IBOutlet weak var DesTextLbl: UILabel! 16 | 17 | 18 | private var task: URLSessionDataTask? 19 | 20 | override func prepareForReuse() { 21 | super.prepareForReuse() 22 | 23 | task?.cancel() 24 | task = nil 25 | DetailImageView.image = UIImage.init(named: "Marvel") 26 | } 27 | 28 | 29 | func configureWith(urlString: String? , name : String? , description : String?) { 30 | if task == nil { 31 | 32 | NameTextLbl.text = "\(name!)" 33 | if let description = description { 34 | DesTextLbl.text = "\(description)" 35 | } 36 | 37 | if let avatar = urlString { 38 | task = DetailImageView.downloadImage(from: avatar) 39 | } 40 | 41 | 42 | } 43 | } 44 | 45 | 46 | 47 | override func awakeFromNib() { 48 | super.awakeFromNib() 49 | // Initialization code 50 | } 51 | 52 | override func setSelected(_ selected: Bool, animated: Bool) { 53 | super.setSelected(selected, animated: animated) 54 | 55 | // Configure the view for the selected state 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Marvel-Hero/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | $(DEVELOPMENT_LANGUAGE) 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleVersion 25 | 1 26 | LSRequiresIPhoneOS 27 | 28 | UILaunchStoryboardName 29 | LaunchScreen 30 | UIRequiredDeviceCapabilities 31 | 32 | armv7 33 | 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/HeroCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeroCell.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/10/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HeroCell: UICollectionViewCell { 12 | 13 | var url : String? 14 | var id : Int? 15 | var name = "Name : " 16 | 17 | @IBOutlet weak var heroAvatarImg: UIImageView! 18 | @IBOutlet weak var heroNameLbl: UILabel! 19 | @IBOutlet weak var favBtnClicked: UIButton! 20 | 21 | 22 | 23 | private var task: URLSessionDataTask? 24 | 25 | override func prepareForReuse() { 26 | super.prepareForReuse() 27 | 28 | task?.cancel() 29 | task = nil 30 | heroAvatarImg.image = UIImage.init(named: "Marvel") 31 | } 32 | 33 | 34 | func configureWith(urlString: String , name : String , id : Int) { 35 | if task == nil { 36 | 37 | heroNameLbl.text = name 38 | self.name = name 39 | self.id = id 40 | self.url = urlString 41 | task = heroAvatarImg.downloadImage(from: urlString) 42 | 43 | // if urlString == "http://i.annihil.us/u/prod/marvel/i/mg/b/40/image_not_available.jpg"{ 44 | // 45 | // heroAvatarImg.image = UIImage.init(named: "Marvel") 46 | // 47 | // }else{ 48 | // task = heroAvatarImg.downloadImage(from: urlString) 49 | // } 50 | 51 | 52 | } 53 | } 54 | 55 | 56 | 57 | override func awakeFromNib() { 58 | 59 | 60 | super.awakeFromNib() 61 | // Initialization code 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Marvel-Hero/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Marvel-Hero/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Marvel-Hero/uiImageView + Downloader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // uiImageView + Downloader.swift 3 | // ImageDownloader 4 | // 5 | // Created by Work on 4/19/19. 6 | // Copyright © 2019 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | let imageCache = NSCache() 13 | 14 | extension UIImageView { 15 | 16 | func downloadImage(from imgURL: String) -> URLSessionDataTask? { 17 | guard let url = URL(string: imgURL) else { return nil } 18 | 19 | // set initial image to nil so it doesn't use the image from a reused cell 20 | image = nil 21 | 22 | // check if the image is already in the cache 23 | if let imageToCache = imageCache.object(forKey: imgURL as NSString) { 24 | self.image = imageToCache 25 | return nil 26 | } 27 | 28 | // download the image asynchronously 29 | let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 30 | if let err = error { 31 | print(err) 32 | return 33 | } 34 | 35 | DispatchQueue.main.async { 36 | // create UIImage 37 | let imageToCache = UIImage(data: data!) 38 | // add image to cache 39 | imageCache.setObject(imageToCache!, forKey: imgURL as NSString) 40 | self.image = imageToCache 41 | } 42 | } 43 | task.resume() 44 | return task 45 | } 46 | } 47 | 48 | //extension UIImageView { 49 | // 50 | // 51 | // func downloadFromUrl (url : URL){ 52 | // 53 | // DispatchQueue.global(qos: .background).async{ 54 | // 55 | // do { 56 | // 57 | // let myData = try Data.init(contentsOf: url) 58 | // 59 | // let myimage = UIImage.init(data: myData) 60 | // 61 | // DispatchQueue.main.async { 62 | // self.image = myimage 63 | // } 64 | // 65 | // } catch let error { 66 | // 67 | // print(error) 68 | // 69 | // } 70 | // } 71 | // 72 | // } 73 | //} 74 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/SearchModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchModel.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/27/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class SearchModel { 12 | 13 | var apiManager = ApiHandler() 14 | var myResults = [Result]() 15 | var count : Int? 16 | var total : Int? 17 | 18 | static func getResultListById(heroId : Int , complimatin : @escaping (JSONReprese)->Void){ 19 | 20 | let FinalAddress = "https://gateway.marvel.com:443/v1/public/characters/\(heroId)?\(HashGenerator.getAccess())&offset=0" 21 | 22 | print(FinalAddress) 23 | ApiHandler.getSearchedCharacters(url: FinalAddress) { (result) in 24 | 25 | complimatin(result) 26 | // print("total is :\(result.data.total)") 27 | // print(result.data.count) 28 | 29 | } 30 | 31 | } 32 | 33 | 34 | static func getFavorietsChars(heroesId : [Int]? , complimatin : @escaping ([JSONReprese])->Void){ 35 | 36 | var results = [JSONReprese]() 37 | 38 | if let heroesId = heroesId { 39 | 40 | for item in heroesId { 41 | 42 | print("item is \(item)") 43 | let FinalAddress = "https://gateway.marvel.com:443/v1/public/characters/\(item)?\(HashGenerator.getAccess())&offset=0" 44 | 45 | print(FinalAddress) 46 | 47 | ApiHandler.getSearchedCharacters(url: FinalAddress) { (result) in 48 | 49 | 50 | results.append(result) 51 | complimatin(results) 52 | 53 | } 54 | 55 | } 56 | 57 | 58 | } 59 | 60 | 61 | 62 | 63 | } 64 | 65 | 66 | static func getResultListByName(name : String , complimatin : @escaping (JSONReprese)->Void){ 67 | 68 | let FinalAddress = "https://gateway.marvel.com:443/v1/public/characters?nameStartsWith=\(name)&\(HashGenerator.getAccess())&offset=0" 69 | 70 | // print(FinalAddress) 71 | ApiHandler.getSearchedCharacters(url: FinalAddress) { (result) in 72 | 73 | complimatin(result) 74 | // print("total is :\(result.data.total)") 75 | // print(result.data.count) 76 | 77 | } 78 | 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /Marvel-Hero/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | 19 | 20 | // let mainView = MainController() 21 | let flowLayout = UICollectionViewFlowLayout() 22 | flowLayout.minimumInteritemSpacing = CGFloat(10) 23 | flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width / 2 - 20, height: 200) 24 | flowLayout.sectionInset = UIEdgeInsets(top: 20, left: 12, bottom: 5, right: 12) 25 | 26 | let myCollectionView = MainController(collectionViewLayout: flowLayout) 27 | 28 | let navigationController = UINavigationController.init(rootViewController: myCollectionView) 29 | 30 | 31 | window = UIWindow.init(frame: UIScreen.main.bounds) 32 | window?.rootViewController = navigationController 33 | window?.makeKeyAndVisible() 34 | 35 | return true 36 | } 37 | 38 | func applicationWillResignActive(_ application: UIApplication) { 39 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 40 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 41 | } 42 | 43 | func applicationDidEnterBackground(_ application: UIApplication) { 44 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 45 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 46 | } 47 | 48 | func applicationWillEnterForeground(_ application: UIApplication) { 49 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 50 | } 51 | 52 | func applicationDidBecomeActive(_ application: UIApplication) { 53 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 54 | } 55 | 56 | func applicationWillTerminate(_ application: UIApplication) { 57 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 58 | } 59 | 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/FavoriteController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FavoriteController.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/12/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | // 9 | 10 | 11 | import UIKit 12 | 13 | class FavoriteController: UICollectionViewController { 14 | let MyCollectionViewCellId: String = "HeroCell" 15 | var favListArray:NSMutableArray = [] 16 | 17 | var hero = [[String : Any]]() 18 | 19 | override func numberOfSections(in collectionView: UICollectionView) -> Int { 20 | 21 | return 1 22 | } 23 | 24 | 25 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 26 | 27 | return hero.count 28 | } 29 | 30 | 31 | 32 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 33 | 34 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCellId, for: indexPath) as! HeroCell 35 | 36 | cell.layer.cornerRadius = 10 37 | cell.layer.masksToBounds = true 38 | 39 | // print(hero[indexPath.row]) 40 | 41 | let avatarUrl = hero[indexPath.row]["url"] 42 | 43 | cell.configureWith(urlString: "\(avatarUrl!)", name: hero[indexPath.row]["name"] as! String , id : hero[indexPath.row]["id"] as! Int) 44 | 45 | if favListArray.contains(hero[indexPath.row]) { 46 | 47 | cell.favBtnClicked.setImage(UIImage.init(named: "filled"), for: UIControl.State.normal) 48 | 49 | }else{ 50 | 51 | cell.favBtnClicked.setImage(UIImage.init(named: "star"), for: UIControl.State.normal) 52 | } 53 | 54 | cell.favBtnClicked.tag = indexPath.row 55 | 56 | cell.favBtnClicked.addTarget(self, action:#selector(addToFav) , for: UIControl.Event.touchUpInside) 57 | 58 | return cell 59 | } 60 | 61 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 62 | 63 | let detailVC = DetailController() 64 | detailVC.heroId = hero[indexPath.row]["id"] as! Int 65 | detailVC.heroName = hero[indexPath.row]["name"] as! String 66 | 67 | navigationController?.pushViewController(detailVC, animated: true) 68 | 69 | 70 | } 71 | 72 | @objc func addToFav(sender:UIButton) { 73 | 74 | let cell = self.collectionView.cellForItem(at: IndexPath.init(row: sender.tag, section: 0)) as! HeroCell 75 | 76 | var hero = ["id" : 0 , "name" : "" , "url" : ""] as [String : Any] 77 | hero["id"] = cell.id 78 | hero["name"] = cell.name 79 | hero["url"] = cell.url 80 | 81 | if favListArray.contains(hero) { 82 | 83 | favListArray.remove(hero) 84 | 85 | }else{ 86 | 87 | favListArray.add(hero) 88 | } 89 | 90 | collectionView.reloadData() 91 | 92 | UserDefaults.standard.set(favListArray, forKey: "favorites") 93 | 94 | } 95 | 96 | 97 | 98 | 99 | override func viewDidLoad() { 100 | super.viewDidLoad() 101 | 102 | let nibCell = UINib(nibName: MyCollectionViewCellId, bundle: nil) 103 | collectionView.register(nibCell, forCellWithReuseIdentifier: MyCollectionViewCellId) 104 | collectionView.delegate = self 105 | collectionView.dataSource = self 106 | collectionView.backgroundColor = UIColor.gray.withAlphaComponent(1) 107 | self.title = "Favorites" 108 | self.view.addSubview(collectionView) 109 | 110 | 111 | } 112 | 113 | override func viewWillAppear(_ animated: Bool) { 114 | 115 | super.viewWillAppear(animated) 116 | hero.removeAll() 117 | 118 | if UserDefaults.standard.object(forKey: "favorites") != nil { 119 | 120 | favListArray = NSMutableArray.init(array: UserDefaults.standard.object(forKey: "favorites") as! NSArray).mutableCopy() as! NSMutableArray 121 | print(favListArray) 122 | 123 | 124 | self.collectionView.reloadData() 125 | 126 | } 127 | 128 | for item in favListArray { 129 | 130 | hero.append(item as! [String : Any]) 131 | 132 | } 133 | 134 | } 135 | 136 | 137 | 138 | } 139 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/WebServiceParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebServiceParser.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | class WebServiceParser { 11 | 12 | static func parsCharacters(req : URLRequest , complimatin : @escaping (JSONReprese)->Void) { 13 | 14 | URLSession.shared.dataTask(with: req) { (data, response, error) in 15 | 16 | if let data = data { 17 | 18 | do { 19 | 20 | let result = try JSONDecoder().decode(JSONReprese.self, from: data) 21 | 22 | complimatin(result) 23 | 24 | } catch let error { 25 | 26 | print("Error : data parser : \(error)") 27 | 28 | } 29 | 30 | }else { 31 | 32 | print("data is not valid") 33 | 34 | } 35 | 36 | }.resume() 37 | } 38 | 39 | static func parsComics(req : URLRequest , complimatin : @escaping (JsonRepreseCo)->Void) { 40 | 41 | URLSession.shared.dataTask(with: req) { (data, response, error) in 42 | 43 | if let data = data { 44 | 45 | do { 46 | 47 | let result = try JSONDecoder().decode(JsonRepreseCo.self, from: data) 48 | 49 | complimatin(result) 50 | 51 | } catch let error { 52 | 53 | print("Error : data parser : \(error)") 54 | 55 | } 56 | 57 | }else { 58 | 59 | print("data is not valid") 60 | 61 | } 62 | 63 | }.resume() 64 | } 65 | 66 | static func parsEvents(req : URLRequest , complimatin : @escaping (JsonRepreseEv)->Void) { 67 | 68 | URLSession.shared.dataTask(with: req) { (data, response, error) in 69 | 70 | if let data = data { 71 | 72 | do { 73 | 74 | let result = try JSONDecoder().decode(JsonRepreseEv.self, from: data) 75 | 76 | complimatin(result) 77 | 78 | } catch let error { 79 | 80 | print("Error : data parser : \(error)") 81 | 82 | } 83 | 84 | }else { 85 | 86 | print("data is not valid") 87 | 88 | } 89 | 90 | }.resume() 91 | } 92 | 93 | static func parsStories(req : URLRequest , complimatin : @escaping (JsonRepreseSt)->Void) { 94 | 95 | URLSession.shared.dataTask(with: req) { (data, response, error) in 96 | 97 | if let data = data { 98 | 99 | do { 100 | 101 | let result = try JSONDecoder().decode(JsonRepreseSt.self, from: data) 102 | 103 | complimatin(result) 104 | 105 | } catch let error { 106 | 107 | print("Error : data parser : \(error)") 108 | 109 | } 110 | 111 | }else { 112 | 113 | print("data is not valid") 114 | 115 | } 116 | 117 | }.resume() 118 | } 119 | 120 | static func parsSeries(req : URLRequest , complimatin : @escaping (JsonRepreseSe)->Void) { 121 | 122 | URLSession.shared.dataTask(with: req) { (data, response, error) in 123 | 124 | if let data = data { 125 | 126 | do { 127 | 128 | let result = try JSONDecoder().decode(JsonRepreseSe.self, from: data) 129 | 130 | complimatin(result) 131 | 132 | } catch let error { 133 | 134 | print("Error : data parser : \(error)") 135 | 136 | } 137 | 138 | }else { 139 | 140 | print("data is not valid") 141 | 142 | } 143 | 144 | }.resume() 145 | } 146 | 147 | 148 | } 149 | -------------------------------------------------------------------------------- /Marvel-Hero/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Marvel-Hero/Models/ApiHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ApiHandler.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 1/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ApiHandler { 12 | 13 | var parserManager = WebServiceParser() 14 | 15 | 16 | static func getSearchedCharacters(url : String , complimatin : @escaping (JSONReprese)->Void) { 17 | 18 | guard let getSearchedCharactersURL = URL.init(string: url) else {return} 19 | 20 | var getSearchedCharactersReq = URLRequest.init(url: getSearchedCharactersURL) 21 | getSearchedCharactersReq.httpMethod = "GET" 22 | 23 | // print("url address is :\(finalApiAddress)") 24 | 25 | WebServiceParser.parsCharacters(req: getSearchedCharactersReq) { (result) in 26 | 27 | complimatin(result) 28 | 29 | } 30 | } 31 | 32 | 33 | static func getCharacters(offset : Int ,limit : Int, complimatin : @escaping (JSONReprese)->Void) { 34 | 35 | let urlString = "https://gateway.marvel.com:443/v1/public/characters?" 36 | 37 | let apiAddress = AuthenticationHandler.getAccessAddress(firstPart: urlString) 38 | 39 | let finalApiAddress = "\(apiAddress)&offset=\(offset)&limit=\(limit)" 40 | 41 | guard let getCharactersURL = URL.init(string: finalApiAddress) else {return} 42 | 43 | var getCharactersReq = URLRequest.init(url: getCharactersURL) 44 | getCharactersReq.httpMethod = "GET" 45 | 46 | print("url address is :\(finalApiAddress)") 47 | 48 | print(finalApiAddress) 49 | WebServiceParser.parsCharacters(req: getCharactersReq) { (result) in 50 | 51 | complimatin(result) 52 | 53 | } 54 | 55 | } 56 | 57 | 58 | static func getComics(heroId : Int , offset : Int ,limit : Int, complimatin : @escaping (JsonRepreseCo)->Void) { 59 | 60 | let urlString = "http://gateway.marvel.com/v1/public/characters/\(heroId)/comics?" 61 | 62 | let apiAddress = AuthenticationHandler.getAccessAddress(firstPart: urlString) 63 | 64 | let finalApiAddress = "\(apiAddress)&offset=\(offset)&limit=\(limit)" 65 | 66 | guard let getComicsURL = URL.init(string: finalApiAddress) else {return} 67 | 68 | var getComicsReq = URLRequest.init(url: getComicsURL) 69 | getComicsReq.httpMethod = "GET" 70 | 71 | print("url address is :\(finalApiAddress)") 72 | 73 | print(finalApiAddress) 74 | WebServiceParser.parsComics(req: getComicsReq) { (result) in 75 | 76 | complimatin(result) 77 | 78 | } 79 | 80 | } 81 | 82 | 83 | static func getEvents(heroId : Int , offset : Int ,limit : Int, complimatin : @escaping (JsonRepreseEv)->Void) { 84 | 85 | let urlString = "http://gateway.marvel.com/v1/public/characters/\(heroId)/events?" 86 | 87 | let apiAddress = AuthenticationHandler.getAccessAddress(firstPart: urlString) 88 | 89 | let finalApiAddress = "\(apiAddress)&offset=\(offset)&limit=\(limit)" 90 | 91 | guard let getEventsURL = URL.init(string: finalApiAddress) else {return} 92 | 93 | var getEventsReq = URLRequest.init(url: getEventsURL) 94 | getEventsReq.httpMethod = "GET" 95 | 96 | print("url address is :\(finalApiAddress)") 97 | 98 | print(finalApiAddress) 99 | WebServiceParser.parsEvents(req: getEventsReq) { (result) in 100 | 101 | complimatin(result) 102 | 103 | } 104 | 105 | } 106 | 107 | static func getStories(heroId : Int , offset : Int ,limit : Int, complimatin : @escaping (JsonRepreseSt)->Void) { 108 | 109 | let urlString = "http://gateway.marvel.com/v1/public/characters/\(heroId)/stories?" 110 | 111 | let apiAddress = AuthenticationHandler.getAccessAddress(firstPart: urlString) 112 | 113 | let finalApiAddress = "\(apiAddress)&offset=\(offset)&limit=\(limit)" 114 | 115 | guard let getStoriesURL = URL.init(string: finalApiAddress) else {return} 116 | 117 | var getStoriesReq = URLRequest.init(url: getStoriesURL) 118 | getStoriesReq.httpMethod = "GET" 119 | 120 | print("url address is :\(finalApiAddress)") 121 | 122 | print(finalApiAddress) 123 | WebServiceParser.parsStories(req: getStoriesReq) { (result) in 124 | 125 | complimatin(result) 126 | 127 | } 128 | 129 | } 130 | 131 | static func getSeries(heroId : Int , offset : Int ,limit : Int, complimatin : @escaping (JsonRepreseSe)->Void) { 132 | 133 | let urlString = "http://gateway.marvel.com/v1/public/characters/\(heroId)/series?" 134 | 135 | let apiAddress = AuthenticationHandler.getAccessAddress(firstPart: urlString) 136 | 137 | let finalApiAddress = "\(apiAddress)&offset=\(offset)&limit=\(limit)" 138 | 139 | guard let getSeriesURL = URL.init(string: finalApiAddress) else {return} 140 | 141 | var getSeriesReq = URLRequest.init(url: getSeriesURL) 142 | getSeriesReq.httpMethod = "GET" 143 | 144 | print("url address is :\(finalApiAddress)") 145 | 146 | print(finalApiAddress) 147 | WebServiceParser.parsSeries(req: getSeriesReq) { (result) in 148 | 149 | complimatin(result) 150 | 151 | } 152 | 153 | } 154 | 155 | 156 | 157 | } 158 | -------------------------------------------------------------------------------- /Marvel-Hero/Views/DetailCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 37 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/SearchController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchController.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/12/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SearchController: UIViewController , UITableViewDelegate , UITableViewDataSource , UISearchBarDelegate{ 12 | 13 | 14 | let mainSearchBar = MainSearchBar() 15 | let cellId = "cellId" 16 | var tempArray = [String]() 17 | var myHeroes = [Result]() 18 | var filteredArray = [String]() 19 | var isSearching = false 20 | var activityView = UIActivityIndicatorView() 21 | var name = "" 22 | 23 | 24 | lazy var mainTable: UITableView = { 25 | let table = UITableView() 26 | table.translatesAutoresizingMaskIntoConstraints = false 27 | table.register(UITableViewCell.self, forCellReuseIdentifier: cellId) 28 | return table 29 | }() 30 | 31 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 32 | return myHeroes.count 33 | } 34 | 35 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 36 | 37 | let cell = mainTable.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as UITableViewCell 38 | cell.textLabel?.text = myHeroes[indexPath.row].name 39 | return cell 40 | } 41 | 42 | func searchBarTextDidEndEditing(_ searchBar: UISearchBar) { 43 | if name != "" { 44 | showDownloading() 45 | }else if name == "" 46 | { 47 | myHeroes.removeAll() 48 | self.mainTable.reloadData() 49 | hideDownloading() 50 | } 51 | 52 | self.fillArray(name: name) 53 | myHeroes.removeAll() 54 | 55 | } 56 | 57 | func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 58 | 59 | name = searchText 60 | 61 | if searchText != "" { 62 | showDownloading() 63 | }else if searchText == "" 64 | { 65 | myHeroes.removeAll() 66 | self.mainTable.reloadData() 67 | hideDownloading() 68 | } 69 | 70 | self.fillArray(name: searchText) 71 | myHeroes.removeAll() 72 | 73 | } 74 | 75 | 76 | func fillArray(name : String){ 77 | showDownloading() 78 | 79 | if name != "" { 80 | SearchModel.getResultListByName(name: "\(name)") { (result) in 81 | 82 | if (result.data?.results.count)! > 0 { 83 | 84 | for item in result.data!.results { 85 | 86 | 87 | self.myHeroes.append(item) 88 | 89 | } 90 | DispatchQueue.main.async { 91 | self.mainTable.reloadData() 92 | } 93 | 94 | } 95 | 96 | self.hideDownloading() 97 | 98 | } 99 | } 100 | 101 | 102 | 103 | } 104 | 105 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 106 | 107 | tableView.deselectRow(at: indexPath, animated: true) 108 | print(myHeroes[indexPath.row].name!) 109 | let detailVC = DetailController() 110 | detailVC.heroId = myHeroes[indexPath.row].id! 111 | detailVC.heroName = myHeroes[indexPath.row].name! 112 | 113 | navigationController?.pushViewController(detailVC, animated: true) 114 | 115 | 116 | } 117 | 118 | 119 | 120 | override func viewDidLoad() { 121 | 122 | setupView() 123 | 124 | mainTable.delegate = self 125 | mainTable.dataSource = self 126 | mainSearchBar.delegate = self 127 | mainSearchBar.returnKeyType = UIReturnKeyType.done 128 | 129 | 130 | UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red] 131 | 132 | self.view.backgroundColor = .red 133 | super.viewDidLoad() 134 | 135 | } 136 | 137 | func setupView(){ 138 | 139 | view.addSubview(mainSearchBar) 140 | view.addSubview(mainTable) 141 | 142 | mainSearchBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true 143 | mainSearchBar.heightAnchor.constraint(equalToConstant: 50).isActive = true 144 | mainSearchBar.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true 145 | mainSearchBar.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true 146 | 147 | mainTable.topAnchor.constraint(equalTo: mainSearchBar.bottomAnchor, constant: 0).isActive = true 148 | mainTable.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true 149 | mainTable.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true 150 | mainTable.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true 151 | mainTable.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 152 | } 153 | 154 | func showDownloading(){ 155 | activityView.color = .black 156 | activityView.hidesWhenStopped = true 157 | activityView.center = self.view.center 158 | let barButton = UIBarButtonItem(customView: activityView) 159 | self.navigationItem.setRightBarButton(barButton, animated: true) 160 | activityView.alpha = 1 161 | activityView.startAnimating() 162 | 163 | } 164 | func hideDownloading() { 165 | DispatchQueue.main.async { 166 | self.activityView.alpha = 0 167 | } 168 | } 169 | 170 | 171 | 172 | } 173 | -------------------------------------------------------------------------------- /Marvel-Hero/Views/HeroCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 39 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/MainController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainController.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/10/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainController: UICollectionViewController { 12 | 13 | var offset = 0 14 | var limit = 14 15 | var is_finished = false 16 | var is_waiting = Bool() 17 | var myCharsArray = [Result]() 18 | var myResCount = 0 19 | let MyCollectionViewCellId: String = "HeroCell" 20 | var favListArray:NSMutableArray = [] 21 | let activityView = UIActivityIndicatorView(style: .whiteLarge) 22 | 23 | 24 | //numberOfSections 25 | 26 | override func numberOfSections(in collectionView: UICollectionView) -> Int { 27 | return 1 28 | } 29 | 30 | //numberOfItemsInSection 31 | 32 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 33 | return myCharsArray.count 34 | } 35 | 36 | //cellForItemAt 37 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 38 | 39 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCellId, for: indexPath) as! HeroCell 40 | 41 | cell.layer.cornerRadius = 10 42 | cell.layer.masksToBounds = true 43 | 44 | let pathUrl = self.myCharsArray[indexPath.row].thumbnail?.path 45 | let pathExt = self.myCharsArray[indexPath.row].thumbnail?.thumbnailExtension 46 | let avatarUrl = "\(pathUrl!).\(pathExt!)" 47 | 48 | cell.configureWith(urlString: "\(avatarUrl)", name: self.myCharsArray[indexPath.row].name! , id : self.myCharsArray[indexPath.row].id!) 49 | 50 | var hero = ["id" : 0 , "name" : "" , "url" : ""] as [String : Any] 51 | hero["id"] = cell.id 52 | hero["name"] = cell.name 53 | hero["url"] = cell.url 54 | 55 | if favListArray.contains(hero) { 56 | 57 | cell.favBtnClicked.setImage(UIImage.init(named: "filled"), for: UIControl.State.normal) 58 | 59 | }else{ 60 | 61 | cell.favBtnClicked.setImage(UIImage.init(named: "star"), for: UIControl.State.normal) 62 | } 63 | 64 | cell.favBtnClicked.tag = indexPath.row 65 | 66 | cell.favBtnClicked.addTarget(self, action:#selector(addToFav) , for: UIControl.Event.touchUpInside) 67 | 68 | 69 | 70 | return cell 71 | } 72 | 73 | @objc func addToFav(sender:UIButton) { 74 | 75 | let cell = self.collectionView.cellForItem(at: IndexPath.init(row: sender.tag, section: 0)) as! HeroCell 76 | 77 | var hero = ["id" : 0 , "name" : "" , "url" : ""] as [String : Any] 78 | hero["id"] = cell.id 79 | hero["name"] = cell.name 80 | hero["url"] = cell.url 81 | 82 | if favListArray.contains(hero) { 83 | 84 | favListArray.remove(hero) 85 | 86 | }else{ 87 | 88 | favListArray.add(hero) 89 | } 90 | 91 | collectionView.reloadData() 92 | 93 | UserDefaults.standard.set(favListArray, forKey: "favorites") 94 | 95 | } 96 | 97 | 98 | 99 | override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { 100 | 101 | if (indexPath.row == myCharsArray.count - 1 ){ 102 | print("loading") 103 | 104 | if(self.is_finished == false){ 105 | 106 | activityView.color = .white 107 | showDownloading() 108 | 109 | ApiHandler.getCharacters(offset: offset, limit: limit) { (results) in 110 | 111 | if ((results.data?.count)! < self.limit) { 112 | self.is_finished = true 113 | } 114 | 115 | for item in results.data!.results { 116 | 117 | self.myCharsArray.append(item) 118 | print("my final array count is : \(self.myCharsArray.count)") 119 | } 120 | 121 | DispatchQueue.main.async { 122 | self.collectionView.reloadData() 123 | } 124 | self.hideDownloading() 125 | 126 | self.offset += self.limit 127 | 128 | } 129 | } 130 | } 131 | } 132 | 133 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 134 | 135 | let detailVC = DetailController() 136 | detailVC.heroId = myCharsArray[indexPath.row].id! 137 | detailVC.heroName = myCharsArray[indexPath.row].name! 138 | 139 | navigationController?.pushViewController(detailVC, animated: true) 140 | 141 | self.activityView.isHidden = true 142 | 143 | 144 | } 145 | 146 | 147 | 148 | override func viewWillAppear(_ animated: Bool) { 149 | 150 | super.viewWillAppear(animated) 151 | 152 | if UserDefaults.standard.object(forKey: "favorites") != nil { 153 | 154 | favListArray = NSMutableArray.init(array: UserDefaults.standard.object(forKey: "favorites") as! NSArray).mutableCopy() as! NSMutableArray 155 | 156 | } 157 | 158 | collectionView.reloadData() 159 | // print(favListArray) 160 | 161 | } 162 | 163 | 164 | 165 | override func viewDidLoad() { 166 | 167 | super.viewDidLoad() 168 | 169 | fetchContent() 170 | print("loadd") 171 | let nibCell = UINib(nibName: MyCollectionViewCellId, bundle: nil) 172 | collectionView.register(nibCell, forCellWithReuseIdentifier: MyCollectionViewCellId) 173 | 174 | collectionView.backgroundColor = UIColor.red.withAlphaComponent(0.4) 175 | 176 | self.title = "MARVEL" 177 | let search = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(searchTapped)) 178 | let favorite = UIBarButtonItem(barButtonSystemItem: .bookmarks, target: self, action: #selector(favoriteTapped)) 179 | 180 | navigationItem.rightBarButtonItems = [search] 181 | navigationItem.leftBarButtonItems = [favorite] 182 | 183 | } 184 | 185 | func showDownloading(){ 186 | activityView.style = UIActivityIndicatorView.Style.whiteLarge 187 | activityView.color = .white 188 | activityView.hidesWhenStopped = true 189 | activityView.center = self.view.center 190 | self.view.addSubview(activityView) 191 | activityView.alpha = 1 192 | activityView.startAnimating() 193 | 194 | } 195 | func hideDownloading() { 196 | DispatchQueue.main.async { 197 | self.activityView.alpha = 0 198 | } 199 | } 200 | 201 | 202 | func fetchContent(){ 203 | 204 | if (myCharsArray.count == 0){ 205 | showDownloading() 206 | ApiHandler.getCharacters(offset: offset, limit: limit) { (result) in 207 | 208 | for item in result.data!.results { 209 | 210 | self.myCharsArray.append(item) 211 | 212 | } 213 | print("my final array count is : \(self.myCharsArray.count)") 214 | 215 | DispatchQueue.main.async { 216 | self.collectionView.reloadData() 217 | } 218 | 219 | self.offset += self.limit 220 | self.myResCount = self.myCharsArray.count 221 | self.is_waiting = false 222 | DispatchQueue.main.sync { 223 | self.hideDownloading() 224 | } 225 | } 226 | 227 | } 228 | 229 | 230 | } 231 | 232 | @objc func searchTapped(){ 233 | 234 | let searchVC = SearchController() 235 | navigationController?.pushViewController(searchVC, animated: true) 236 | 237 | 238 | } 239 | 240 | @objc func favoriteTapped(){ 241 | 242 | let flowLayout = UICollectionViewFlowLayout() 243 | flowLayout.minimumInteritemSpacing = CGFloat(10) 244 | flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width / 2 - 20, height: 200) 245 | flowLayout.sectionInset = UIEdgeInsets(top: 20, left: 12, bottom: 5, right: 12) 246 | 247 | 248 | let favoriteVC = FavoriteController(collectionViewLayout: flowLayout) 249 | 250 | 251 | navigationController?.pushViewController(favoriteVC, animated: true) 252 | 253 | 254 | } 255 | 256 | 257 | 258 | } 259 | -------------------------------------------------------------------------------- /Marvel-Hero/Controllers/DetailController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailController.swift 3 | // Marvel-Hero 4 | // 5 | // Created by Work on 2/11/20. 6 | // Copyright © 2020 Kian Anvari. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DetailController: UIViewController , UITableViewDataSource , UITableViewDelegate { 12 | 13 | var favListArray:NSMutableArray = [] 14 | var activityView = UIActivityIndicatorView() 15 | var avatarImageViewer = UIImageView() 16 | var segmentController = UISegmentedControl.init(items: ["Stories" ,"Series" , "Events" ,"Comics"]) 17 | var tableView = UITableView() 18 | var heroId = 0 19 | var myHero = [Result]() 20 | var heroCo = [ResultCo]();var heroSt = [ResultSt]();var heroSe = [ResultSe]();var heroEv = [ResultEv]() 21 | var heroName = "" 22 | var avatarUrl = "" 23 | 24 | var flag = 0 25 | var is_fav = false 26 | 27 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 28 | switch flag { 29 | case 0: 30 | return heroSt.count 31 | case 1: 32 | return heroSe.count 33 | case 2: 34 | return heroEv.count 35 | case 3: 36 | return heroCo.count 37 | default: 38 | print("default") 39 | } 40 | return 0 41 | } 42 | 43 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 44 | let cell = Bundle.main.loadNibNamed("DetailCell", owner: self, options: nil)?.last as! DetailCell 45 | 46 | 47 | switch flag { 48 | case 0: 49 | 50 | let pathUrl = self.heroSt[indexPath.row].thumbnail?.path 51 | let pathExt = self.heroSt[indexPath.row].thumbnail?.thumbnailExtension 52 | if let pathUrl = pathUrl { 53 | let avatarUrl = "\(pathUrl).\(pathExt!)" 54 | cell.configureWith(urlString: avatarUrl, name: heroSt[indexPath.row].title!, description: heroSt[indexPath.row].resultDescription) 55 | } 56 | cell.configureWith(urlString: "", name: heroSt[indexPath.row].title!, description: heroSt[indexPath.row].resultDescription) 57 | 58 | break 59 | 60 | case 1: 61 | 62 | let pathUrl = self.heroSe[indexPath.row].thumbnail?.path 63 | let pathExt = self.heroSe[indexPath.row].thumbnail?.thumbnailExtension 64 | if let pathUrl = pathUrl { 65 | let avatarUrl = "\(pathUrl).\(pathExt!)" 66 | cell.configureWith(urlString: avatarUrl, name: heroSe[indexPath.row].title!, description: heroSe[indexPath.row].resultDescription) 67 | } 68 | cell.configureWith(urlString: "", name: heroSe[indexPath.row].title!, description: heroSe[indexPath.row].resultDescription) 69 | 70 | 71 | break 72 | case 2: 73 | 74 | let pathUrl = self.heroEv[indexPath.row].thumbnail?.path 75 | let pathExt = self.heroEv[indexPath.row].thumbnail?.thumbnailExtension 76 | if let pathUrl = pathUrl { 77 | let avatarUrl = "\(pathUrl).\(pathExt!)" 78 | cell.configureWith(urlString: avatarUrl, name: heroEv[indexPath.row].title!, description: heroEv[indexPath.row].resultDescription) 79 | } 80 | cell.configureWith(urlString: "", name: heroEv[indexPath.row].title!, description: heroEv[indexPath.row].resultDescription) 81 | 82 | 83 | break 84 | case 3: 85 | 86 | let pathUrl = self.heroCo[indexPath.row].thumbnail?.path 87 | let pathExt = self.heroCo[indexPath.row].thumbnail?.thumbnailExtension 88 | if let pathUrl = pathUrl { 89 | let avatarUrl = "\(pathUrl).\(pathExt!)" 90 | cell.configureWith(urlString: avatarUrl, name: heroCo[indexPath.row].title!, description: heroCo[indexPath.row].resultDescription) 91 | } 92 | cell.configureWith(urlString: "", name: heroCo[indexPath.row].title!, description: heroCo[indexPath.row].resultDescription) 93 | 94 | 95 | break 96 | default: 97 | print("default") 98 | } 99 | 100 | 101 | return cell 102 | } 103 | 104 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 105 | return 120 106 | } 107 | 108 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 109 | tableView.deselectRow(at: indexPath, animated: true) 110 | } 111 | 112 | override func viewDidLoad() { 113 | super.viewDidLoad() 114 | 115 | self.title = heroName 116 | self.view.backgroundColor = UIColor.red.withAlphaComponent(1) 117 | getStories() 118 | showDownloading() 119 | SearchModel.getResultListById(heroId: heroId) { (result) in 120 | 121 | self.myHero = (result.data?.results)! 122 | DispatchQueue.main.async { 123 | self.showAvatar() 124 | } 125 | 126 | 127 | } 128 | 129 | 130 | self.tableView.delegate = self 131 | self.tableView.dataSource = self 132 | 133 | 134 | setAvatarImageViewer() 135 | setsegmentController() 136 | settableView() 137 | 138 | // Do any additional setup after loading the view. 139 | } 140 | 141 | 142 | 143 | 144 | 145 | func getStories(){ 146 | 147 | if (heroSt.count == 0) { 148 | ApiHandler.getStories(heroId: heroId, offset: 0, limit: 10) { (result) in 149 | if result.data.count != 0 { 150 | 151 | for item in result.data.results { 152 | 153 | self.heroSt.append(item) 154 | 155 | } 156 | } 157 | 158 | DispatchQueue.main.async { 159 | self.tableView.reloadData() 160 | } 161 | self.hideDownloading() 162 | } 163 | 164 | }else{ 165 | self.hideDownloading() 166 | } 167 | 168 | } 169 | 170 | func getSeries(){ 171 | 172 | if (heroSe.count == 0 ){ 173 | 174 | ApiHandler.getSeries(heroId: heroId, offset: 0, limit: 10) { (result) in 175 | if result.data.count != 0 { 176 | // print(result.data.results[0].title) 177 | for item in result.data.results { 178 | 179 | self.heroSe.append(item) 180 | 181 | } 182 | } 183 | DispatchQueue.main.async { 184 | self.tableView.reloadData() 185 | } 186 | self.hideDownloading() 187 | } 188 | }else{ 189 | self.hideDownloading() 190 | } 191 | 192 | } 193 | 194 | 195 | func getEvents(){ 196 | 197 | if (heroEv.count == 0){ 198 | 199 | ApiHandler.getEvents(heroId: heroId, offset: 0, limit: 10) { (result) in 200 | 201 | if result.data.count != 0 { 202 | // print(result.data.results[0].start) 203 | for item in result.data.results { 204 | 205 | self.heroEv.append(item) 206 | 207 | } 208 | } 209 | DispatchQueue.main.async { 210 | self.tableView.reloadData() 211 | } 212 | self.hideDownloading() 213 | } 214 | 215 | }else{ 216 | self.hideDownloading() 217 | } 218 | 219 | } 220 | 221 | 222 | func getComics(){ 223 | 224 | if (heroCo.count == 0){ 225 | 226 | ApiHandler.getComics(heroId: heroId, offset: 0, limit: 10) { (result) in 227 | 228 | if result.data.count != 0 { 229 | // print(result.data.results[0].resultDescription) 230 | for item in result.data.results { 231 | 232 | self.heroCo.append(item) 233 | 234 | } 235 | } 236 | DispatchQueue.main.async { 237 | self.tableView.reloadData() 238 | } 239 | self.hideDownloading() 240 | } 241 | 242 | }else{ 243 | self.hideDownloading() 244 | } 245 | 246 | } 247 | 248 | 249 | 250 | func showAvatar(){ 251 | 252 | let pathUrl = self.myHero[0].thumbnail?.path 253 | let pathExt = self.myHero[0].thumbnail?.thumbnailExtension 254 | avatarUrl = "\(pathUrl!).\(pathExt!)" 255 | 256 | avatarImageViewer.downloadImage(from: avatarUrl) 257 | 258 | } 259 | 260 | @objc func indexChanged(_ sender: UISegmentedControl) { 261 | showDownloading() 262 | switch sender.selectedSegmentIndex{ 263 | case 0: 264 | print("Stories"); 265 | getStories() 266 | flag = 0 267 | self.tableView.reloadData() 268 | break 269 | case 1: 270 | print("Series") 271 | getSeries() 272 | flag = 1 273 | self.tableView.reloadData() 274 | break 275 | case 2: 276 | print("Events"); 277 | getEvents() 278 | flag = 2 279 | self.tableView.reloadData() 280 | break 281 | case 3: 282 | print("Comics") 283 | getComics() 284 | flag = 3 285 | self.tableView.reloadData() 286 | break 287 | default: 288 | break 289 | } 290 | } 291 | 292 | @objc func favTapped(){ 293 | 294 | 295 | if (is_fav) { 296 | 297 | for item in favListArray{ 298 | 299 | var curr = item as! [String:Any] 300 | 301 | if (curr["id"] as! Int == heroId) { 302 | favListArray.remove(curr) 303 | } 304 | let barButton = UIBarButtonItem.init(barButtonSystemItem: .save, target: self, action: #selector(favTapped)) 305 | self.navigationItem.setRightBarButton(barButton, animated: true) 306 | } 307 | 308 | 309 | }else{ 310 | 311 | var hero = ["id" : heroId , "name" : heroName , "url" : avatarUrl] as [String : Any] 312 | 313 | // print(hero) 314 | favListArray.add(hero) 315 | let barButton = UIBarButtonItem.init(barButtonSystemItem: .stop, target: self, action: #selector(favTapped)) 316 | self.navigationItem.setRightBarButton(barButton, animated: true) 317 | } 318 | 319 | UserDefaults.standard.set(favListArray, forKey: "favorites") 320 | 321 | print("hellp") 322 | 323 | 324 | } 325 | 326 | 327 | override func viewWillAppear(_ animated: Bool) { 328 | 329 | if UserDefaults.standard.object(forKey: "favorites") != nil { 330 | 331 | favListArray = NSMutableArray.init(array: UserDefaults.standard.object(forKey: "favorites") as! NSArray).mutableCopy() as! NSMutableArray 332 | // print(favListArray) 333 | 334 | 335 | } 336 | 337 | for item in favListArray{ 338 | 339 | var curr = item as! [String:Any] 340 | 341 | if (curr["id"] as! Int == heroId) { 342 | is_fav = true 343 | print(is_fav) 344 | } 345 | 346 | } 347 | 348 | if(is_fav){ 349 | let barButton = UIBarButtonItem.init(barButtonSystemItem: .stop, target: self, action: #selector(favTapped)) 350 | self.navigationItem.setRightBarButton(barButton, animated: true) 351 | }else{ 352 | 353 | let barButton = UIBarButtonItem.init(barButtonSystemItem: .save, target: self, action: #selector(favTapped)) 354 | self.navigationItem.setRightBarButton(barButton, animated: true) 355 | } 356 | 357 | 358 | 359 | } 360 | 361 | 362 | func setAvatarImageViewer(){ 363 | 364 | // avatarImageViewer.image = UIImage.init(named: "Marvel") 365 | avatarImageViewer.frame = CGRect.init(x: self.view.frame.width/2 - 100, y: 100, width: 200, height: 200) 366 | avatarImageViewer.layer.cornerRadius = 25 367 | avatarImageViewer.layer.masksToBounds = true 368 | avatarImageViewer.contentMode = .scaleAspectFill 369 | view.addSubview(avatarImageViewer) 370 | } 371 | 372 | func setsegmentController(){ 373 | 374 | segmentController.frame = CGRect(x: 40 , y: self.avatarImageViewer.frame.size.height + 140 , width: 300, height: 30) 375 | 376 | segmentController.selectedSegmentIndex = 0 377 | segmentController.addTarget(self, action: #selector(indexChanged(_:)), for: .valueChanged) 378 | 379 | segmentController.layer.cornerRadius = 5.0 380 | segmentController.backgroundColor = .red 381 | segmentController.tintColor = .white 382 | 383 | view.addSubview(segmentController) 384 | 385 | } 386 | 387 | 388 | func settableView(){ 389 | 390 | tableView.frame = CGRect.init(x: 8, y: 400, width: 360 , height: 430) 391 | view.addSubview(tableView) 392 | 393 | } 394 | 395 | func showDownloading(){ 396 | 397 | activityView.color = .red 398 | activityView.hidesWhenStopped = true 399 | self.tableView.addSubview(activityView) 400 | tableView.backgroundView = activityView 401 | activityView.alpha = 1 402 | activityView.startAnimating() 403 | 404 | } 405 | 406 | func hideDownloading() { 407 | DispatchQueue.main.async { 408 | self.activityView.alpha = 0 409 | } 410 | } 411 | 412 | } 413 | -------------------------------------------------------------------------------- /Marvel-Hero.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 96284FFD23DF0AC3000CCCD2 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96284FFC23DF0AC3000CCCD2 /* SearchModel.swift */; }; 11 | 96287EA823EF240C00AB7F61 /* JsonRepreseSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EA723EF240C00AB7F61 /* JsonRepreseSt.swift */; }; 12 | 96287EAA23EF242400AB7F61 /* DataClassSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EA923EF242400AB7F61 /* DataClassSt.swift */; }; 13 | 96287EAC23EF242E00AB7F61 /* ResultSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EAB23EF242E00AB7F61 /* ResultSt.swift */; }; 14 | 96287EAE23EF243600AB7F61 /* CharactersSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EAD23EF243600AB7F61 /* CharactersSt.swift */; }; 15 | 96287EB023EF243E00AB7F61 /* OriginalIssueSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EAF23EF243E00AB7F61 /* OriginalIssueSt.swift */; }; 16 | 96287EB223EF244800AB7F61 /* CreatorsSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EB123EF244800AB7F61 /* CreatorsSt.swift */; }; 17 | 96287EB423EF245300AB7F61 /* ItemSt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EB323EF245300AB7F61 /* ItemSt.swift */; }; 18 | 96287EB923EF512300AB7F61 /* JsonRepreseEv.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EB823EF512300AB7F61 /* JsonRepreseEv.swift */; }; 19 | 96287EBB23EF513400AB7F61 /* DataClassEv.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EBA23EF513400AB7F61 /* DataClassEv.swift */; }; 20 | 96287EBD23EF513E00AB7F61 /* ResultEv.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EBC23EF513E00AB7F61 /* ResultEv.swift */; }; 21 | 96287EBF23EF515200AB7F61 /* Characters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EBE23EF515200AB7F61 /* Characters.swift */; }; 22 | 96287EC123EF515D00AB7F61 /* Next.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EC023EF515D00AB7F61 /* Next.swift */; }; 23 | 96287EC323EF518D00AB7F61 /* Creators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EC223EF518D00AB7F61 /* Creators.swift */; }; 24 | 96287EC523EF519600AB7F61 /* CreatorsItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EC423EF519600AB7F61 /* CreatorsItem.swift */; }; 25 | 96287EC723EF519F00AB7F61 /* StoriesEv.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EC623EF519F00AB7F61 /* StoriesEv.swift */; }; 26 | 96287EC923EF51AB00AB7F61 /* StoriesItemEv.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EC823EF51AB00AB7F61 /* StoriesItemEv.swift */; }; 27 | 96287ECC23EF55C700AB7F61 /* JsonRepreseSe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ECB23EF55C700AB7F61 /* JsonRepreseSe.swift */; }; 28 | 96287ECE23EF55DD00AB7F61 /* DataClassSe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ECD23EF55DD00AB7F61 /* DataClassSe.swift */; }; 29 | 96287ED023EF55F800AB7F61 /* ResultSe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ECF23EF55F800AB7F61 /* ResultSe.swift */; }; 30 | 96287ED423EF571600AB7F61 /* JsonRepreseCo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ED323EF571600AB7F61 /* JsonRepreseCo.swift */; }; 31 | 96287ED623EF572100AB7F61 /* DataClassCo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ED523EF572100AB7F61 /* DataClassCo.swift */; }; 32 | 96287ED823EF572900AB7F61 /* ResultCo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ED723EF572900AB7F61 /* ResultCo.swift */; }; 33 | 96287EDA23EF577300AB7F61 /* TextObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287ED923EF577300AB7F61 /* TextObject.swift */; }; 34 | 96287EDC23EF586000AB7F61 /* Price.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EDB23EF586000AB7F61 /* Price.swift */; }; 35 | 96287EDE23EF589700AB7F61 /* DateElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EDD23EF589700AB7F61 /* DateElement.swift */; }; 36 | 96287EE023EF592F00AB7F61 /* Series.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EDF23EF592F00AB7F61 /* Series.swift */; }; 37 | 96287EE323F15AF400AB7F61 /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EE223F15AF400AB7F61 /* MainController.swift */; }; 38 | 96287EEA23F1C72000AB7F61 /* HeroCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96287EE823F1C72000AB7F61 /* HeroCell.swift */; }; 39 | 96287EEB23F1C72000AB7F61 /* HeroCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 96287EE923F1C72000AB7F61 /* HeroCell.xib */; }; 40 | 96320ED623C9F8410077867B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96320ED523C9F8410077867B /* AppDelegate.swift */; }; 41 | 96320EDB23C9F8410077867B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96320ED923C9F8410077867B /* Main.storyboard */; }; 42 | 96320EDD23C9F8420077867B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96320EDC23C9F8420077867B /* Assets.xcassets */; }; 43 | 96320EE023C9F8420077867B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96320EDE23C9F8420077867B /* LaunchScreen.storyboard */; }; 44 | 96320EEB23C9F8420077867B /* Marvel_HeroTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96320EEA23C9F8420077867B /* Marvel_HeroTests.swift */; }; 45 | 96320EF623C9F8420077867B /* Marvel_HeroUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96320EF523C9F8420077867B /* Marvel_HeroUITests.swift */; }; 46 | 96320F0423C9F8520077867B /* ApiHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96320F0323C9F8520077867B /* ApiHandler.swift */; }; 47 | 96320F0623C9F8960077867B /* WebServiceParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96320F0523C9F8960077867B /* WebServiceParser.swift */; }; 48 | 963CFDAF23CA6AED007E7DCF /* AuthenticationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963CFDAE23CA6AED007E7DCF /* AuthenticationHandler.swift */; }; 49 | 963CFDB323CA6EF9007E7DCF /* string+md5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963CFDB223CA6EF9007E7DCF /* string+md5.swift */; }; 50 | 96423A2523E0C59500C737E5 /* HashGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96423A2423E0C59500C737E5 /* HashGenerator.swift */; }; 51 | 9657940323F493E500D56D11 /* FavoriteController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9657940223F493E500D56D11 /* FavoriteController.swift */; }; 52 | 965DEA2A23F1F1CD00EC24E6 /* uiImageView + Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965DEA2923F1F1CD00EC24E6 /* uiImageView + Downloader.swift */; }; 53 | 96684A9823F31D560054EE61 /* DetailCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96684A9623F31D560054EE61 /* DetailCell.swift */; }; 54 | 96684A9923F31D560054EE61 /* DetailCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 96684A9723F31D560054EE61 /* DetailCell.xib */; }; 55 | 96684A9B23F42F560054EE61 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96684A9A23F42F560054EE61 /* SearchController.swift */; }; 56 | 96684A9D23F4318E0054EE61 /* MainSearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96684A9C23F4318E0054EE61 /* MainSearchBar.swift */; }; 57 | 96C91D1723D437D800834C8A /* JSONReprese.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D1623D437D800834C8A /* JSONReprese.swift */; }; 58 | 96C91D1923D4382500834C8A /* DataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D1823D4382500834C8A /* DataClass.swift */; }; 59 | 96C91D1C23D4399500834C8A /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D1B23D4399500834C8A /* Result.swift */; }; 60 | 96C91D1E23D439AF00834C8A /* Comics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D1D23D439AF00834C8A /* Comics.swift */; }; 61 | 96C91D2023D439C200834C8A /* ComicsItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D1F23D439C200834C8A /* ComicsItem.swift */; }; 62 | 96C91D2223D439DA00834C8A /* Stories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D2123D439DA00834C8A /* Stories.swift */; }; 63 | 96C91D2423D439F000834C8A /* StoriesItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D2323D439F000834C8A /* StoriesItem.swift */; }; 64 | 96C91D2823D43A1A00834C8A /* Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D2723D43A1A00834C8A /* Thumbnail.swift */; }; 65 | 96C91D2A23D43A4400834C8A /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D2923D43A4400834C8A /* Extension.swift */; }; 66 | 96C91D2D23D43A5900834C8A /* URLElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D2C23D43A5900834C8A /* URLElement.swift */; }; 67 | 96C91D2F23D43A6600834C8A /* URLType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C91D2E23D43A6600834C8A /* URLType.swift */; }; 68 | 96D71D0723F2B8D0005B3B06 /* DetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D71D0623F2B8D0005B3B06 /* DetailController.swift */; }; 69 | /* End PBXBuildFile section */ 70 | 71 | /* Begin PBXContainerItemProxy section */ 72 | 96320EE723C9F8420077867B /* PBXContainerItemProxy */ = { 73 | isa = PBXContainerItemProxy; 74 | containerPortal = 96320ECA23C9F8410077867B /* Project object */; 75 | proxyType = 1; 76 | remoteGlobalIDString = 96320ED123C9F8410077867B; 77 | remoteInfo = "Marvel-Hero"; 78 | }; 79 | 96320EF223C9F8420077867B /* PBXContainerItemProxy */ = { 80 | isa = PBXContainerItemProxy; 81 | containerPortal = 96320ECA23C9F8410077867B /* Project object */; 82 | proxyType = 1; 83 | remoteGlobalIDString = 96320ED123C9F8410077867B; 84 | remoteInfo = "Marvel-Hero"; 85 | }; 86 | /* End PBXContainerItemProxy section */ 87 | 88 | /* Begin PBXFileReference section */ 89 | 96284FFC23DF0AC3000CCCD2 /* SearchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = ""; }; 90 | 96287EA723EF240C00AB7F61 /* JsonRepreseSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRepreseSt.swift; sourceTree = ""; }; 91 | 96287EA923EF242400AB7F61 /* DataClassSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataClassSt.swift; sourceTree = ""; }; 92 | 96287EAB23EF242E00AB7F61 /* ResultSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultSt.swift; sourceTree = ""; }; 93 | 96287EAD23EF243600AB7F61 /* CharactersSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharactersSt.swift; sourceTree = ""; }; 94 | 96287EAF23EF243E00AB7F61 /* OriginalIssueSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OriginalIssueSt.swift; sourceTree = ""; }; 95 | 96287EB123EF244800AB7F61 /* CreatorsSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatorsSt.swift; sourceTree = ""; }; 96 | 96287EB323EF245300AB7F61 /* ItemSt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemSt.swift; sourceTree = ""; }; 97 | 96287EB823EF512300AB7F61 /* JsonRepreseEv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRepreseEv.swift; sourceTree = ""; }; 98 | 96287EBA23EF513400AB7F61 /* DataClassEv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataClassEv.swift; sourceTree = ""; }; 99 | 96287EBC23EF513E00AB7F61 /* ResultEv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultEv.swift; sourceTree = ""; }; 100 | 96287EBE23EF515200AB7F61 /* Characters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Characters.swift; sourceTree = ""; }; 101 | 96287EC023EF515D00AB7F61 /* Next.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Next.swift; sourceTree = ""; }; 102 | 96287EC223EF518D00AB7F61 /* Creators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Creators.swift; sourceTree = ""; }; 103 | 96287EC423EF519600AB7F61 /* CreatorsItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatorsItem.swift; sourceTree = ""; }; 104 | 96287EC623EF519F00AB7F61 /* StoriesEv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoriesEv.swift; sourceTree = ""; }; 105 | 96287EC823EF51AB00AB7F61 /* StoriesItemEv.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoriesItemEv.swift; sourceTree = ""; }; 106 | 96287ECB23EF55C700AB7F61 /* JsonRepreseSe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRepreseSe.swift; sourceTree = ""; }; 107 | 96287ECD23EF55DD00AB7F61 /* DataClassSe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataClassSe.swift; sourceTree = ""; }; 108 | 96287ECF23EF55F800AB7F61 /* ResultSe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultSe.swift; sourceTree = ""; }; 109 | 96287ED323EF571600AB7F61 /* JsonRepreseCo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonRepreseCo.swift; sourceTree = ""; }; 110 | 96287ED523EF572100AB7F61 /* DataClassCo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataClassCo.swift; sourceTree = ""; }; 111 | 96287ED723EF572900AB7F61 /* ResultCo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultCo.swift; sourceTree = ""; }; 112 | 96287ED923EF577300AB7F61 /* TextObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextObject.swift; sourceTree = ""; }; 113 | 96287EDB23EF586000AB7F61 /* Price.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Price.swift; sourceTree = ""; }; 114 | 96287EDD23EF589700AB7F61 /* DateElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateElement.swift; sourceTree = ""; }; 115 | 96287EDF23EF592F00AB7F61 /* Series.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Series.swift; sourceTree = ""; }; 116 | 96287EE223F15AF400AB7F61 /* MainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = ""; }; 117 | 96287EE823F1C72000AB7F61 /* HeroCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeroCell.swift; sourceTree = ""; }; 118 | 96287EE923F1C72000AB7F61 /* HeroCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HeroCell.xib; sourceTree = ""; }; 119 | 96320ED223C9F8410077867B /* Marvel-Hero.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Marvel-Hero.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 120 | 96320ED523C9F8410077867B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 121 | 96320EDA23C9F8410077867B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 122 | 96320EDC23C9F8420077867B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 123 | 96320EDF23C9F8420077867B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 124 | 96320EE123C9F8420077867B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 125 | 96320EE623C9F8420077867B /* Marvel-HeroTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Marvel-HeroTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 126 | 96320EEA23C9F8420077867B /* Marvel_HeroTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Marvel_HeroTests.swift; sourceTree = ""; }; 127 | 96320EEC23C9F8420077867B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 128 | 96320EF123C9F8420077867B /* Marvel-HeroUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Marvel-HeroUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 129 | 96320EF523C9F8420077867B /* Marvel_HeroUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Marvel_HeroUITests.swift; sourceTree = ""; }; 130 | 96320EF723C9F8420077867B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 131 | 96320F0323C9F8520077867B /* ApiHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiHandler.swift; sourceTree = ""; }; 132 | 96320F0523C9F8960077867B /* WebServiceParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebServiceParser.swift; sourceTree = ""; }; 133 | 963CFDAE23CA6AED007E7DCF /* AuthenticationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationHandler.swift; sourceTree = ""; }; 134 | 963CFDB223CA6EF9007E7DCF /* string+md5.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "string+md5.swift"; sourceTree = ""; }; 135 | 96423A2423E0C59500C737E5 /* HashGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashGenerator.swift; sourceTree = ""; }; 136 | 9657940223F493E500D56D11 /* FavoriteController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteController.swift; sourceTree = ""; }; 137 | 965DEA2923F1F1CD00EC24E6 /* uiImageView + Downloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "uiImageView + Downloader.swift"; sourceTree = ""; }; 138 | 96684A9623F31D560054EE61 /* DetailCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCell.swift; sourceTree = ""; }; 139 | 96684A9723F31D560054EE61 /* DetailCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DetailCell.xib; sourceTree = ""; }; 140 | 96684A9A23F42F560054EE61 /* SearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchController.swift; sourceTree = ""; }; 141 | 96684A9C23F4318E0054EE61 /* MainSearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainSearchBar.swift; sourceTree = ""; }; 142 | 96C91D1623D437D800834C8A /* JSONReprese.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONReprese.swift; sourceTree = ""; }; 143 | 96C91D1823D4382500834C8A /* DataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataClass.swift; sourceTree = ""; }; 144 | 96C91D1B23D4399500834C8A /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; 145 | 96C91D1D23D439AF00834C8A /* Comics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comics.swift; sourceTree = ""; }; 146 | 96C91D1F23D439C200834C8A /* ComicsItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComicsItem.swift; sourceTree = ""; }; 147 | 96C91D2123D439DA00834C8A /* Stories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stories.swift; sourceTree = ""; }; 148 | 96C91D2323D439F000834C8A /* StoriesItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoriesItem.swift; sourceTree = ""; }; 149 | 96C91D2723D43A1A00834C8A /* Thumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbnail.swift; sourceTree = ""; }; 150 | 96C91D2923D43A4400834C8A /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = ""; }; 151 | 96C91D2C23D43A5900834C8A /* URLElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLElement.swift; sourceTree = ""; }; 152 | 96C91D2E23D43A6600834C8A /* URLType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLType.swift; sourceTree = ""; }; 153 | 96D71D0623F2B8D0005B3B06 /* DetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailController.swift; sourceTree = ""; }; 154 | /* End PBXFileReference section */ 155 | 156 | /* Begin PBXFrameworksBuildPhase section */ 157 | 96320ECF23C9F8410077867B /* Frameworks */ = { 158 | isa = PBXFrameworksBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | 96320EE323C9F8420077867B /* Frameworks */ = { 165 | isa = PBXFrameworksBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | }; 171 | 96320EEE23C9F8420077867B /* Frameworks */ = { 172 | isa = PBXFrameworksBuildPhase; 173 | buildActionMask = 2147483647; 174 | files = ( 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXFrameworksBuildPhase section */ 179 | 180 | /* Begin PBXGroup section */ 181 | 96287EB723EF246A00AB7F61 /* Stories */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 96287EA723EF240C00AB7F61 /* JsonRepreseSt.swift */, 185 | 96287EA923EF242400AB7F61 /* DataClassSt.swift */, 186 | 96287EAB23EF242E00AB7F61 /* ResultSt.swift */, 187 | 96287EAD23EF243600AB7F61 /* CharactersSt.swift */, 188 | 96287EAF23EF243E00AB7F61 /* OriginalIssueSt.swift */, 189 | 96287EB123EF244800AB7F61 /* CreatorsSt.swift */, 190 | 96287EB323EF245300AB7F61 /* ItemSt.swift */, 191 | ); 192 | path = Stories; 193 | sourceTree = ""; 194 | }; 195 | 96287ECA23EF52B500AB7F61 /* Events */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 96287EB823EF512300AB7F61 /* JsonRepreseEv.swift */, 199 | 96287EBA23EF513400AB7F61 /* DataClassEv.swift */, 200 | 96287EBC23EF513E00AB7F61 /* ResultEv.swift */, 201 | 96287EC623EF519F00AB7F61 /* StoriesEv.swift */, 202 | 96287EC823EF51AB00AB7F61 /* StoriesItemEv.swift */, 203 | ); 204 | path = Events; 205 | sourceTree = ""; 206 | }; 207 | 96287ED123EF566F00AB7F61 /* Series */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | 96287ECB23EF55C700AB7F61 /* JsonRepreseSe.swift */, 211 | 96287ECD23EF55DD00AB7F61 /* DataClassSe.swift */, 212 | 96287ECF23EF55F800AB7F61 /* ResultSe.swift */, 213 | ); 214 | path = Series; 215 | sourceTree = ""; 216 | }; 217 | 96287ED223EF568000AB7F61 /* GlobalModels */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | 96287EDB23EF586000AB7F61 /* Price.swift */, 221 | 96287EDF23EF592F00AB7F61 /* Series.swift */, 222 | 96287EDD23EF589700AB7F61 /* DateElement.swift */, 223 | 96287EBE23EF515200AB7F61 /* Characters.swift */, 224 | 96287EC023EF515D00AB7F61 /* Next.swift */, 225 | 96287EC223EF518D00AB7F61 /* Creators.swift */, 226 | 96287EC423EF519600AB7F61 /* CreatorsItem.swift */, 227 | 96C91D2923D43A4400834C8A /* Extension.swift */, 228 | 96C91D2C23D43A5900834C8A /* URLElement.swift */, 229 | 96C91D2E23D43A6600834C8A /* URLType.swift */, 230 | ); 231 | path = GlobalModels; 232 | sourceTree = ""; 233 | }; 234 | 96287EE123EF596000AB7F61 /* Comics */ = { 235 | isa = PBXGroup; 236 | children = ( 237 | 96287ED323EF571600AB7F61 /* JsonRepreseCo.swift */, 238 | 96287ED923EF577300AB7F61 /* TextObject.swift */, 239 | 96287ED523EF572100AB7F61 /* DataClassCo.swift */, 240 | 96287ED723EF572900AB7F61 /* ResultCo.swift */, 241 | ); 242 | path = Comics; 243 | sourceTree = ""; 244 | }; 245 | 96320EC923C9F8410077867B = { 246 | isa = PBXGroup; 247 | children = ( 248 | 96320ED423C9F8410077867B /* Marvel-Hero */, 249 | 96320EE923C9F8420077867B /* Marvel-HeroTests */, 250 | 96320EF423C9F8420077867B /* Marvel-HeroUITests */, 251 | 96320ED323C9F8410077867B /* Products */, 252 | ); 253 | sourceTree = ""; 254 | }; 255 | 96320ED323C9F8410077867B /* Products */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | 96320ED223C9F8410077867B /* Marvel-Hero.app */, 259 | 96320EE623C9F8420077867B /* Marvel-HeroTests.xctest */, 260 | 96320EF123C9F8420077867B /* Marvel-HeroUITests.xctest */, 261 | ); 262 | name = Products; 263 | sourceTree = ""; 264 | }; 265 | 96320ED423C9F8410077867B /* Marvel-Hero */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | 96320ED523C9F8410077867B /* AppDelegate.swift */, 269 | 963CFDB223CA6EF9007E7DCF /* string+md5.swift */, 270 | 96423A2423E0C59500C737E5 /* HashGenerator.swift */, 271 | 965DEA2923F1F1CD00EC24E6 /* uiImageView + Downloader.swift */, 272 | 9657940423F52F4600D56D11 /* Controllers */, 273 | 9657940523F52F5300D56D11 /* Views */, 274 | 96C91D1A23D4394C00834C8A /* Models */, 275 | 96320ED923C9F8410077867B /* Main.storyboard */, 276 | 96320EDC23C9F8420077867B /* Assets.xcassets */, 277 | 96320EDE23C9F8420077867B /* LaunchScreen.storyboard */, 278 | 96320EE123C9F8420077867B /* Info.plist */, 279 | ); 280 | path = "Marvel-Hero"; 281 | sourceTree = ""; 282 | }; 283 | 96320EE923C9F8420077867B /* Marvel-HeroTests */ = { 284 | isa = PBXGroup; 285 | children = ( 286 | 96320EEA23C9F8420077867B /* Marvel_HeroTests.swift */, 287 | 96320EEC23C9F8420077867B /* Info.plist */, 288 | ); 289 | path = "Marvel-HeroTests"; 290 | sourceTree = ""; 291 | }; 292 | 96320EF423C9F8420077867B /* Marvel-HeroUITests */ = { 293 | isa = PBXGroup; 294 | children = ( 295 | 96320EF523C9F8420077867B /* Marvel_HeroUITests.swift */, 296 | 96320EF723C9F8420077867B /* Info.plist */, 297 | ); 298 | path = "Marvel-HeroUITests"; 299 | sourceTree = ""; 300 | }; 301 | 9657940423F52F4600D56D11 /* Controllers */ = { 302 | isa = PBXGroup; 303 | children = ( 304 | 96D71D0623F2B8D0005B3B06 /* DetailController.swift */, 305 | 96684A9C23F4318E0054EE61 /* MainSearchBar.swift */, 306 | 96684A9A23F42F560054EE61 /* SearchController.swift */, 307 | 96287EE223F15AF400AB7F61 /* MainController.swift */, 308 | 9657940223F493E500D56D11 /* FavoriteController.swift */, 309 | 96684A9623F31D560054EE61 /* DetailCell.swift */, 310 | 96287EE823F1C72000AB7F61 /* HeroCell.swift */, 311 | ); 312 | path = Controllers; 313 | sourceTree = ""; 314 | }; 315 | 9657940523F52F5300D56D11 /* Views */ = { 316 | isa = PBXGroup; 317 | children = ( 318 | 96684A9723F31D560054EE61 /* DetailCell.xib */, 319 | 96287EE923F1C72000AB7F61 /* HeroCell.xib */, 320 | ); 321 | path = Views; 322 | sourceTree = ""; 323 | }; 324 | 96C91D1A23D4394C00834C8A /* Models */ = { 325 | isa = PBXGroup; 326 | children = ( 327 | 963CFDAE23CA6AED007E7DCF /* AuthenticationHandler.swift */, 328 | 96284FFC23DF0AC3000CCCD2 /* SearchModel.swift */, 329 | 96320F0323C9F8520077867B /* ApiHandler.swift */, 330 | 96320F0523C9F8960077867B /* WebServiceParser.swift */, 331 | 96287ED223EF568000AB7F61 /* GlobalModels */, 332 | 96FE478923D9ED2200E0821F /* Chars */, 333 | 96287EB723EF246A00AB7F61 /* Stories */, 334 | 96287ECA23EF52B500AB7F61 /* Events */, 335 | 96287ED123EF566F00AB7F61 /* Series */, 336 | 96287EE123EF596000AB7F61 /* Comics */, 337 | ); 338 | path = Models; 339 | sourceTree = ""; 340 | }; 341 | 96FE478923D9ED2200E0821F /* Chars */ = { 342 | isa = PBXGroup; 343 | children = ( 344 | 96C91D2723D43A1A00834C8A /* Thumbnail.swift */, 345 | 96C91D1623D437D800834C8A /* JSONReprese.swift */, 346 | 96C91D1823D4382500834C8A /* DataClass.swift */, 347 | 96C91D1B23D4399500834C8A /* Result.swift */, 348 | 96C91D1D23D439AF00834C8A /* Comics.swift */, 349 | 96C91D1F23D439C200834C8A /* ComicsItem.swift */, 350 | 96C91D2123D439DA00834C8A /* Stories.swift */, 351 | 96C91D2323D439F000834C8A /* StoriesItem.swift */, 352 | ); 353 | path = Chars; 354 | sourceTree = ""; 355 | }; 356 | /* End PBXGroup section */ 357 | 358 | /* Begin PBXNativeTarget section */ 359 | 96320ED123C9F8410077867B /* Marvel-Hero */ = { 360 | isa = PBXNativeTarget; 361 | buildConfigurationList = 96320EFA23C9F8420077867B /* Build configuration list for PBXNativeTarget "Marvel-Hero" */; 362 | buildPhases = ( 363 | 96320ECE23C9F8410077867B /* Sources */, 364 | 96320ECF23C9F8410077867B /* Frameworks */, 365 | 96320ED023C9F8410077867B /* Resources */, 366 | ); 367 | buildRules = ( 368 | ); 369 | dependencies = ( 370 | ); 371 | name = "Marvel-Hero"; 372 | productName = "Marvel-Hero"; 373 | productReference = 96320ED223C9F8410077867B /* Marvel-Hero.app */; 374 | productType = "com.apple.product-type.application"; 375 | }; 376 | 96320EE523C9F8420077867B /* Marvel-HeroTests */ = { 377 | isa = PBXNativeTarget; 378 | buildConfigurationList = 96320EFD23C9F8420077867B /* Build configuration list for PBXNativeTarget "Marvel-HeroTests" */; 379 | buildPhases = ( 380 | 96320EE223C9F8420077867B /* Sources */, 381 | 96320EE323C9F8420077867B /* Frameworks */, 382 | 96320EE423C9F8420077867B /* Resources */, 383 | ); 384 | buildRules = ( 385 | ); 386 | dependencies = ( 387 | 96320EE823C9F8420077867B /* PBXTargetDependency */, 388 | ); 389 | name = "Marvel-HeroTests"; 390 | productName = "Marvel-HeroTests"; 391 | productReference = 96320EE623C9F8420077867B /* Marvel-HeroTests.xctest */; 392 | productType = "com.apple.product-type.bundle.unit-test"; 393 | }; 394 | 96320EF023C9F8420077867B /* Marvel-HeroUITests */ = { 395 | isa = PBXNativeTarget; 396 | buildConfigurationList = 96320F0023C9F8420077867B /* Build configuration list for PBXNativeTarget "Marvel-HeroUITests" */; 397 | buildPhases = ( 398 | 96320EED23C9F8420077867B /* Sources */, 399 | 96320EEE23C9F8420077867B /* Frameworks */, 400 | 96320EEF23C9F8420077867B /* Resources */, 401 | ); 402 | buildRules = ( 403 | ); 404 | dependencies = ( 405 | 96320EF323C9F8420077867B /* PBXTargetDependency */, 406 | ); 407 | name = "Marvel-HeroUITests"; 408 | productName = "Marvel-HeroUITests"; 409 | productReference = 96320EF123C9F8420077867B /* Marvel-HeroUITests.xctest */; 410 | productType = "com.apple.product-type.bundle.ui-testing"; 411 | }; 412 | /* End PBXNativeTarget section */ 413 | 414 | /* Begin PBXProject section */ 415 | 96320ECA23C9F8410077867B /* Project object */ = { 416 | isa = PBXProject; 417 | attributes = { 418 | LastSwiftUpdateCheck = 1000; 419 | LastUpgradeCheck = 1000; 420 | ORGANIZATIONNAME = "Kian Anvari"; 421 | TargetAttributes = { 422 | 96320ED123C9F8410077867B = { 423 | CreatedOnToolsVersion = 10.0; 424 | }; 425 | 96320EE523C9F8420077867B = { 426 | CreatedOnToolsVersion = 10.0; 427 | TestTargetID = 96320ED123C9F8410077867B; 428 | }; 429 | 96320EF023C9F8420077867B = { 430 | CreatedOnToolsVersion = 10.0; 431 | TestTargetID = 96320ED123C9F8410077867B; 432 | }; 433 | }; 434 | }; 435 | buildConfigurationList = 96320ECD23C9F8410077867B /* Build configuration list for PBXProject "Marvel-Hero" */; 436 | compatibilityVersion = "Xcode 9.3"; 437 | developmentRegion = en; 438 | hasScannedForEncodings = 0; 439 | knownRegions = ( 440 | en, 441 | Base, 442 | ); 443 | mainGroup = 96320EC923C9F8410077867B; 444 | productRefGroup = 96320ED323C9F8410077867B /* Products */; 445 | projectDirPath = ""; 446 | projectRoot = ""; 447 | targets = ( 448 | 96320ED123C9F8410077867B /* Marvel-Hero */, 449 | 96320EE523C9F8420077867B /* Marvel-HeroTests */, 450 | 96320EF023C9F8420077867B /* Marvel-HeroUITests */, 451 | ); 452 | }; 453 | /* End PBXProject section */ 454 | 455 | /* Begin PBXResourcesBuildPhase section */ 456 | 96320ED023C9F8410077867B /* Resources */ = { 457 | isa = PBXResourcesBuildPhase; 458 | buildActionMask = 2147483647; 459 | files = ( 460 | 96320EE023C9F8420077867B /* LaunchScreen.storyboard in Resources */, 461 | 96320EDD23C9F8420077867B /* Assets.xcassets in Resources */, 462 | 96320EDB23C9F8410077867B /* Main.storyboard in Resources */, 463 | 96287EEB23F1C72000AB7F61 /* HeroCell.xib in Resources */, 464 | 96684A9923F31D560054EE61 /* DetailCell.xib in Resources */, 465 | ); 466 | runOnlyForDeploymentPostprocessing = 0; 467 | }; 468 | 96320EE423C9F8420077867B /* Resources */ = { 469 | isa = PBXResourcesBuildPhase; 470 | buildActionMask = 2147483647; 471 | files = ( 472 | ); 473 | runOnlyForDeploymentPostprocessing = 0; 474 | }; 475 | 96320EEF23C9F8420077867B /* Resources */ = { 476 | isa = PBXResourcesBuildPhase; 477 | buildActionMask = 2147483647; 478 | files = ( 479 | ); 480 | runOnlyForDeploymentPostprocessing = 0; 481 | }; 482 | /* End PBXResourcesBuildPhase section */ 483 | 484 | /* Begin PBXSourcesBuildPhase section */ 485 | 96320ECE23C9F8410077867B /* Sources */ = { 486 | isa = PBXSourcesBuildPhase; 487 | buildActionMask = 2147483647; 488 | files = ( 489 | 96287ECE23EF55DD00AB7F61 /* DataClassSe.swift in Sources */, 490 | 96684A9B23F42F560054EE61 /* SearchController.swift in Sources */, 491 | 96287EC323EF518D00AB7F61 /* Creators.swift in Sources */, 492 | 96287EDC23EF586000AB7F61 /* Price.swift in Sources */, 493 | 96287EA823EF240C00AB7F61 /* JsonRepreseSt.swift in Sources */, 494 | 96C91D2823D43A1A00834C8A /* Thumbnail.swift in Sources */, 495 | 96C91D2D23D43A5900834C8A /* URLElement.swift in Sources */, 496 | 96287EC723EF519F00AB7F61 /* StoriesEv.swift in Sources */, 497 | 96D71D0723F2B8D0005B3B06 /* DetailController.swift in Sources */, 498 | 96287EB023EF243E00AB7F61 /* OriginalIssueSt.swift in Sources */, 499 | 96287ED023EF55F800AB7F61 /* ResultSe.swift in Sources */, 500 | 96C91D1923D4382500834C8A /* DataClass.swift in Sources */, 501 | 96C91D2F23D43A6600834C8A /* URLType.swift in Sources */, 502 | 96287EAE23EF243600AB7F61 /* CharactersSt.swift in Sources */, 503 | 96287EB223EF244800AB7F61 /* CreatorsSt.swift in Sources */, 504 | 96320ED623C9F8410077867B /* AppDelegate.swift in Sources */, 505 | 96287EC923EF51AB00AB7F61 /* StoriesItemEv.swift in Sources */, 506 | 96684A9D23F4318E0054EE61 /* MainSearchBar.swift in Sources */, 507 | 96320F0423C9F8520077867B /* ApiHandler.swift in Sources */, 508 | 96287ECC23EF55C700AB7F61 /* JsonRepreseSe.swift in Sources */, 509 | 96C91D1E23D439AF00834C8A /* Comics.swift in Sources */, 510 | 96684A9823F31D560054EE61 /* DetailCell.swift in Sources */, 511 | 96287ED823EF572900AB7F61 /* ResultCo.swift in Sources */, 512 | 96287EB923EF512300AB7F61 /* JsonRepreseEv.swift in Sources */, 513 | 96287EBF23EF515200AB7F61 /* Characters.swift in Sources */, 514 | 96287EE323F15AF400AB7F61 /* MainController.swift in Sources */, 515 | 96287EAA23EF242400AB7F61 /* DataClassSt.swift in Sources */, 516 | 96287EC523EF519600AB7F61 /* CreatorsItem.swift in Sources */, 517 | 96287EE023EF592F00AB7F61 /* Series.swift in Sources */, 518 | 96287EDA23EF577300AB7F61 /* TextObject.swift in Sources */, 519 | 96287EC123EF515D00AB7F61 /* Next.swift in Sources */, 520 | 96287EBD23EF513E00AB7F61 /* ResultEv.swift in Sources */, 521 | 96287EAC23EF242E00AB7F61 /* ResultSt.swift in Sources */, 522 | 963CFDB323CA6EF9007E7DCF /* string+md5.swift in Sources */, 523 | 96C91D2A23D43A4400834C8A /* Extension.swift in Sources */, 524 | 96C91D2023D439C200834C8A /* ComicsItem.swift in Sources */, 525 | 96C91D1723D437D800834C8A /* JSONReprese.swift in Sources */, 526 | 963CFDAF23CA6AED007E7DCF /* AuthenticationHandler.swift in Sources */, 527 | 96287ED623EF572100AB7F61 /* DataClassCo.swift in Sources */, 528 | 96320F0623C9F8960077867B /* WebServiceParser.swift in Sources */, 529 | 96287EEA23F1C72000AB7F61 /* HeroCell.swift in Sources */, 530 | 96287EB423EF245300AB7F61 /* ItemSt.swift in Sources */, 531 | 96C91D2423D439F000834C8A /* StoriesItem.swift in Sources */, 532 | 9657940323F493E500D56D11 /* FavoriteController.swift in Sources */, 533 | 96284FFD23DF0AC3000CCCD2 /* SearchModel.swift in Sources */, 534 | 96423A2523E0C59500C737E5 /* HashGenerator.swift in Sources */, 535 | 96C91D1C23D4399500834C8A /* Result.swift in Sources */, 536 | 96287EDE23EF589700AB7F61 /* DateElement.swift in Sources */, 537 | 96287ED423EF571600AB7F61 /* JsonRepreseCo.swift in Sources */, 538 | 96287EBB23EF513400AB7F61 /* DataClassEv.swift in Sources */, 539 | 96C91D2223D439DA00834C8A /* Stories.swift in Sources */, 540 | 965DEA2A23F1F1CD00EC24E6 /* uiImageView + Downloader.swift in Sources */, 541 | ); 542 | runOnlyForDeploymentPostprocessing = 0; 543 | }; 544 | 96320EE223C9F8420077867B /* Sources */ = { 545 | isa = PBXSourcesBuildPhase; 546 | buildActionMask = 2147483647; 547 | files = ( 548 | 96320EEB23C9F8420077867B /* Marvel_HeroTests.swift in Sources */, 549 | ); 550 | runOnlyForDeploymentPostprocessing = 0; 551 | }; 552 | 96320EED23C9F8420077867B /* Sources */ = { 553 | isa = PBXSourcesBuildPhase; 554 | buildActionMask = 2147483647; 555 | files = ( 556 | 96320EF623C9F8420077867B /* Marvel_HeroUITests.swift in Sources */, 557 | ); 558 | runOnlyForDeploymentPostprocessing = 0; 559 | }; 560 | /* End PBXSourcesBuildPhase section */ 561 | 562 | /* Begin PBXTargetDependency section */ 563 | 96320EE823C9F8420077867B /* PBXTargetDependency */ = { 564 | isa = PBXTargetDependency; 565 | target = 96320ED123C9F8410077867B /* Marvel-Hero */; 566 | targetProxy = 96320EE723C9F8420077867B /* PBXContainerItemProxy */; 567 | }; 568 | 96320EF323C9F8420077867B /* PBXTargetDependency */ = { 569 | isa = PBXTargetDependency; 570 | target = 96320ED123C9F8410077867B /* Marvel-Hero */; 571 | targetProxy = 96320EF223C9F8420077867B /* PBXContainerItemProxy */; 572 | }; 573 | /* End PBXTargetDependency section */ 574 | 575 | /* Begin PBXVariantGroup section */ 576 | 96320ED923C9F8410077867B /* Main.storyboard */ = { 577 | isa = PBXVariantGroup; 578 | children = ( 579 | 96320EDA23C9F8410077867B /* Base */, 580 | ); 581 | name = Main.storyboard; 582 | sourceTree = ""; 583 | }; 584 | 96320EDE23C9F8420077867B /* LaunchScreen.storyboard */ = { 585 | isa = PBXVariantGroup; 586 | children = ( 587 | 96320EDF23C9F8420077867B /* Base */, 588 | ); 589 | name = LaunchScreen.storyboard; 590 | sourceTree = ""; 591 | }; 592 | /* End PBXVariantGroup section */ 593 | 594 | /* Begin XCBuildConfiguration section */ 595 | 96320EF823C9F8420077867B /* Debug */ = { 596 | isa = XCBuildConfiguration; 597 | buildSettings = { 598 | ALWAYS_SEARCH_USER_PATHS = NO; 599 | CLANG_ANALYZER_NONNULL = YES; 600 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 601 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 602 | CLANG_CXX_LIBRARY = "libc++"; 603 | CLANG_ENABLE_MODULES = YES; 604 | CLANG_ENABLE_OBJC_ARC = YES; 605 | CLANG_ENABLE_OBJC_WEAK = YES; 606 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 607 | CLANG_WARN_BOOL_CONVERSION = YES; 608 | CLANG_WARN_COMMA = YES; 609 | CLANG_WARN_CONSTANT_CONVERSION = YES; 610 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 611 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 612 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 613 | CLANG_WARN_EMPTY_BODY = YES; 614 | CLANG_WARN_ENUM_CONVERSION = YES; 615 | CLANG_WARN_INFINITE_RECURSION = YES; 616 | CLANG_WARN_INT_CONVERSION = YES; 617 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 618 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 619 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 620 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 621 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 622 | CLANG_WARN_STRICT_PROTOTYPES = YES; 623 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 624 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 625 | CLANG_WARN_UNREACHABLE_CODE = YES; 626 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 627 | CODE_SIGN_IDENTITY = "iPhone Developer"; 628 | COPY_PHASE_STRIP = NO; 629 | DEBUG_INFORMATION_FORMAT = dwarf; 630 | ENABLE_STRICT_OBJC_MSGSEND = YES; 631 | ENABLE_TESTABILITY = YES; 632 | GCC_C_LANGUAGE_STANDARD = gnu11; 633 | GCC_DYNAMIC_NO_PIC = NO; 634 | GCC_NO_COMMON_BLOCKS = YES; 635 | GCC_OPTIMIZATION_LEVEL = 0; 636 | GCC_PREPROCESSOR_DEFINITIONS = ( 637 | "DEBUG=1", 638 | "$(inherited)", 639 | ); 640 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 641 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 642 | GCC_WARN_UNDECLARED_SELECTOR = YES; 643 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 644 | GCC_WARN_UNUSED_FUNCTION = YES; 645 | GCC_WARN_UNUSED_VARIABLE = YES; 646 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 647 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 648 | MTL_FAST_MATH = YES; 649 | ONLY_ACTIVE_ARCH = YES; 650 | SDKROOT = iphoneos; 651 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 652 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 653 | }; 654 | name = Debug; 655 | }; 656 | 96320EF923C9F8420077867B /* Release */ = { 657 | isa = XCBuildConfiguration; 658 | buildSettings = { 659 | ALWAYS_SEARCH_USER_PATHS = NO; 660 | CLANG_ANALYZER_NONNULL = YES; 661 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 662 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 663 | CLANG_CXX_LIBRARY = "libc++"; 664 | CLANG_ENABLE_MODULES = YES; 665 | CLANG_ENABLE_OBJC_ARC = YES; 666 | CLANG_ENABLE_OBJC_WEAK = YES; 667 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 668 | CLANG_WARN_BOOL_CONVERSION = YES; 669 | CLANG_WARN_COMMA = YES; 670 | CLANG_WARN_CONSTANT_CONVERSION = YES; 671 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 672 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 673 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 674 | CLANG_WARN_EMPTY_BODY = YES; 675 | CLANG_WARN_ENUM_CONVERSION = YES; 676 | CLANG_WARN_INFINITE_RECURSION = YES; 677 | CLANG_WARN_INT_CONVERSION = YES; 678 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 679 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 680 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 681 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 682 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 683 | CLANG_WARN_STRICT_PROTOTYPES = YES; 684 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 685 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 686 | CLANG_WARN_UNREACHABLE_CODE = YES; 687 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 688 | CODE_SIGN_IDENTITY = "iPhone Developer"; 689 | COPY_PHASE_STRIP = NO; 690 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 691 | ENABLE_NS_ASSERTIONS = NO; 692 | ENABLE_STRICT_OBJC_MSGSEND = YES; 693 | GCC_C_LANGUAGE_STANDARD = gnu11; 694 | GCC_NO_COMMON_BLOCKS = YES; 695 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 696 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 697 | GCC_WARN_UNDECLARED_SELECTOR = YES; 698 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 699 | GCC_WARN_UNUSED_FUNCTION = YES; 700 | GCC_WARN_UNUSED_VARIABLE = YES; 701 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 702 | MTL_ENABLE_DEBUG_INFO = NO; 703 | MTL_FAST_MATH = YES; 704 | SDKROOT = iphoneos; 705 | SWIFT_COMPILATION_MODE = wholemodule; 706 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 707 | VALIDATE_PRODUCT = YES; 708 | }; 709 | name = Release; 710 | }; 711 | 96320EFB23C9F8420077867B /* Debug */ = { 712 | isa = XCBuildConfiguration; 713 | buildSettings = { 714 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 715 | CODE_SIGN_STYLE = Automatic; 716 | INFOPLIST_FILE = "Marvel-Hero/Info.plist"; 717 | LD_RUNPATH_SEARCH_PATHS = ( 718 | "$(inherited)", 719 | "@executable_path/Frameworks", 720 | ); 721 | PRODUCT_BUNDLE_IDENTIFIER = "Kian.Marvel-Hero"; 722 | PRODUCT_NAME = "$(TARGET_NAME)"; 723 | SWIFT_VERSION = 4.2; 724 | TARGETED_DEVICE_FAMILY = "1,2"; 725 | }; 726 | name = Debug; 727 | }; 728 | 96320EFC23C9F8420077867B /* Release */ = { 729 | isa = XCBuildConfiguration; 730 | buildSettings = { 731 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 732 | CODE_SIGN_STYLE = Automatic; 733 | INFOPLIST_FILE = "Marvel-Hero/Info.plist"; 734 | LD_RUNPATH_SEARCH_PATHS = ( 735 | "$(inherited)", 736 | "@executable_path/Frameworks", 737 | ); 738 | PRODUCT_BUNDLE_IDENTIFIER = "Kian.Marvel-Hero"; 739 | PRODUCT_NAME = "$(TARGET_NAME)"; 740 | SWIFT_VERSION = 4.2; 741 | TARGETED_DEVICE_FAMILY = "1,2"; 742 | }; 743 | name = Release; 744 | }; 745 | 96320EFE23C9F8420077867B /* Debug */ = { 746 | isa = XCBuildConfiguration; 747 | buildSettings = { 748 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 749 | BUNDLE_LOADER = "$(TEST_HOST)"; 750 | CODE_SIGN_STYLE = Automatic; 751 | INFOPLIST_FILE = "Marvel-HeroTests/Info.plist"; 752 | LD_RUNPATH_SEARCH_PATHS = ( 753 | "$(inherited)", 754 | "@executable_path/Frameworks", 755 | "@loader_path/Frameworks", 756 | ); 757 | PRODUCT_BUNDLE_IDENTIFIER = "Kian.Marvel-HeroTests"; 758 | PRODUCT_NAME = "$(TARGET_NAME)"; 759 | SWIFT_VERSION = 4.2; 760 | TARGETED_DEVICE_FAMILY = "1,2"; 761 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Marvel-Hero.app/Marvel-Hero"; 762 | }; 763 | name = Debug; 764 | }; 765 | 96320EFF23C9F8420077867B /* Release */ = { 766 | isa = XCBuildConfiguration; 767 | buildSettings = { 768 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 769 | BUNDLE_LOADER = "$(TEST_HOST)"; 770 | CODE_SIGN_STYLE = Automatic; 771 | INFOPLIST_FILE = "Marvel-HeroTests/Info.plist"; 772 | LD_RUNPATH_SEARCH_PATHS = ( 773 | "$(inherited)", 774 | "@executable_path/Frameworks", 775 | "@loader_path/Frameworks", 776 | ); 777 | PRODUCT_BUNDLE_IDENTIFIER = "Kian.Marvel-HeroTests"; 778 | PRODUCT_NAME = "$(TARGET_NAME)"; 779 | SWIFT_VERSION = 4.2; 780 | TARGETED_DEVICE_FAMILY = "1,2"; 781 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Marvel-Hero.app/Marvel-Hero"; 782 | }; 783 | name = Release; 784 | }; 785 | 96320F0123C9F8420077867B /* Debug */ = { 786 | isa = XCBuildConfiguration; 787 | buildSettings = { 788 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 789 | CODE_SIGN_STYLE = Automatic; 790 | INFOPLIST_FILE = "Marvel-HeroUITests/Info.plist"; 791 | LD_RUNPATH_SEARCH_PATHS = ( 792 | "$(inherited)", 793 | "@executable_path/Frameworks", 794 | "@loader_path/Frameworks", 795 | ); 796 | PRODUCT_BUNDLE_IDENTIFIER = "Kian.Marvel-HeroUITests"; 797 | PRODUCT_NAME = "$(TARGET_NAME)"; 798 | SWIFT_VERSION = 4.2; 799 | TARGETED_DEVICE_FAMILY = "1,2"; 800 | TEST_TARGET_NAME = "Marvel-Hero"; 801 | }; 802 | name = Debug; 803 | }; 804 | 96320F0223C9F8420077867B /* Release */ = { 805 | isa = XCBuildConfiguration; 806 | buildSettings = { 807 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 808 | CODE_SIGN_STYLE = Automatic; 809 | INFOPLIST_FILE = "Marvel-HeroUITests/Info.plist"; 810 | LD_RUNPATH_SEARCH_PATHS = ( 811 | "$(inherited)", 812 | "@executable_path/Frameworks", 813 | "@loader_path/Frameworks", 814 | ); 815 | PRODUCT_BUNDLE_IDENTIFIER = "Kian.Marvel-HeroUITests"; 816 | PRODUCT_NAME = "$(TARGET_NAME)"; 817 | SWIFT_VERSION = 4.2; 818 | TARGETED_DEVICE_FAMILY = "1,2"; 819 | TEST_TARGET_NAME = "Marvel-Hero"; 820 | }; 821 | name = Release; 822 | }; 823 | /* End XCBuildConfiguration section */ 824 | 825 | /* Begin XCConfigurationList section */ 826 | 96320ECD23C9F8410077867B /* Build configuration list for PBXProject "Marvel-Hero" */ = { 827 | isa = XCConfigurationList; 828 | buildConfigurations = ( 829 | 96320EF823C9F8420077867B /* Debug */, 830 | 96320EF923C9F8420077867B /* Release */, 831 | ); 832 | defaultConfigurationIsVisible = 0; 833 | defaultConfigurationName = Release; 834 | }; 835 | 96320EFA23C9F8420077867B /* Build configuration list for PBXNativeTarget "Marvel-Hero" */ = { 836 | isa = XCConfigurationList; 837 | buildConfigurations = ( 838 | 96320EFB23C9F8420077867B /* Debug */, 839 | 96320EFC23C9F8420077867B /* Release */, 840 | ); 841 | defaultConfigurationIsVisible = 0; 842 | defaultConfigurationName = Release; 843 | }; 844 | 96320EFD23C9F8420077867B /* Build configuration list for PBXNativeTarget "Marvel-HeroTests" */ = { 845 | isa = XCConfigurationList; 846 | buildConfigurations = ( 847 | 96320EFE23C9F8420077867B /* Debug */, 848 | 96320EFF23C9F8420077867B /* Release */, 849 | ); 850 | defaultConfigurationIsVisible = 0; 851 | defaultConfigurationName = Release; 852 | }; 853 | 96320F0023C9F8420077867B /* Build configuration list for PBXNativeTarget "Marvel-HeroUITests" */ = { 854 | isa = XCConfigurationList; 855 | buildConfigurations = ( 856 | 96320F0123C9F8420077867B /* Debug */, 857 | 96320F0223C9F8420077867B /* Release */, 858 | ); 859 | defaultConfigurationIsVisible = 0; 860 | defaultConfigurationName = Release; 861 | }; 862 | /* End XCConfigurationList section */ 863 | }; 864 | rootObject = 96320ECA23C9F8410077867B /* Project object */; 865 | } 866 | --------------------------------------------------------------------------------