├── 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 |
--------------------------------------------------------------------------------