Skip to content
This repository was archived by the owner on Oct 14, 2018. It is now read-only.

Commit ab09687

Browse files
authored
Merge pull request #3 from AnderGoig/develop
Develop
2 parents 53fcc21 + 8af54bc commit ab09687

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+9024
-755
lines changed

.assets/Getting-Started.png

17 KB
Loading

.codebeatignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docs/**

.github/ISSUE_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Checklist
1+
## Checklist
22

33
- [ ] I've the [latest update](https://github.com/AnderGoig/SwiftInstagram/releases) of Swiftinstagram.
44
- [ ] I've searched for [existing GitHub issues](https://github.com/AnderGoig/SwiftInstagram/issues).

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88

9+
## [1.0.4] - 2017-10-10
10+
### Added
11+
- 100% documented code.
12+
### Changed
13+
- Now, the redirection URI must be defined in the Info.plist file. See [wiki](https://github.com/AnderGoig/SwiftInstagram/wiki/Authentication).
14+
- The `createdTime` attribute of the classes `InstagramComment` and `InstagramMedia` has been renamed to `createdDate` and returns an object of type `Date`.
15+
- Improves [Codebeat](https://codebeat.co/projects/github-com-andergoig-swiftinstagram-master) GBA.
16+
### Fixed
17+
- Fixed the type of the returned errors.
18+
919
## [1.0.3] - 2017-10-08
1020
### Changed
1121
- Improved documentation.
@@ -34,7 +44,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
3444
### Added
3545
- Initial release.
3646

37-
[Unreleased]: https://github.com/AnderGoig/SwiftInstagram/compare/v1.0.3...develop
47+
[Unreleased]: https://github.com/AnderGoig/SwiftInstagram/compare/v1.0.4...develop
48+
[1.0.4]: https://github.com/AnderGoig/SwiftInstagram/compare/v1.0.3...v1.0.4
3849
[1.0.3]: https://github.com/AnderGoig/SwiftInstagram/compare/v1.0.2...v1.0.3
3950
[1.0.2]: https://github.com/AnderGoig/SwiftInstagram/compare/v1.0.1...v1.0.2
4051
[1.0.1]: https://github.com/AnderGoig/SwiftInstagram/compare/v1.0.0...v1.0.1

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@
99
<img src="https://img.shields.io/cocoapods/p/SwiftInstagram.svg"
1010
alt="Platforms">
1111
</a>
12-
<a href="https://developer.apple.com/swift" target="_blank">
12+
<a href="https://developer.apple.com/swift">
1313
<img src="https://img.shields.io/badge/Swift-4.0-orange.svg?style=flat"
1414
alt="Swift 4.0">
1515
</a>
1616
<a href="https://travis-ci.org/AnderGoig/SwiftInstagram/branches">
1717
<img src="https://img.shields.io/travis/AnderGoig/SwiftInstagram/master.svg"
1818
alt="Travis">
1919
</a>
20-
<a href="https://andergoig.github.io/SwiftInstagram/Classes/Instagram.html" target="_blank">
21-
<img src="https://img.shields.io/badge/Documentation-available-blue.svg"
20+
<a href="https://codebeat.co/projects/github-com-andergoig-swiftinstagram-master">
21+
<img src="https://codebeat.co/badges/e5274943-8feb-4e51-a937-43552205f62e" alt="Codebeat">
22+
</a>
23+
<a href="https://andergoig.github.io/SwiftInstagram/Classes/Instagram.html">
24+
<img src="docs/badge.svg"
2225
alt="Documentation">
2326
</a>
2427
<a href="https://raw.githubusercontent.com/AnderGoig/SwiftInstagram/master/LICENSE">
@@ -46,12 +49,19 @@
4649

4750
**SwiftInstagram** is a **wrapper** for the **Instagram API** written in **Swift**. It allows you to authenticate users and request data from Instagram effortlessly.
4851

49-
- [Requirements](#requirements)
50-
- [Usage](#usage)
51-
- [Contributing](#contributing)
52-
- [Credits](#credits)
53-
- [License](#license)
54-
- [Author](#author)
52+
## Features
53+
54+
- [x] Effortless and straightforward use of Instagram API.
55+
- [x] Up-to-date with the latest of [Instagram API](https://www.instagram.com/developer/).
56+
- [x] Client-Side authentication.
57+
- [x] Secure access token storing, thanks to [keychain-swift](https://github.com/evgenyneu/keychain-swift).
58+
- [x] Up-to-date with the latest Apple technologies (Swift 4, Xcode 9, etc).
59+
60+
### Coming features - [SwiftInstagram 2.0.0](https://github.com/AnderGoig/SwiftInstagram/projects/1)
61+
62+
- [ ] Multiple users login
63+
- [ ] [Instagram Business API](https://developers.facebook.com/docs/instagram-api/v2.10) support
64+
- [ ] And more ...
5565

5666
## Requirements
5767

Sources/Instagram.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,26 @@ public class Instagram {
1818

1919
public typealias EmptySuccessHandler = () -> Void
2020
public typealias SuccessHandler<T> = (_ data: T) -> Void
21-
public typealias FailureHandler = (_ error: Error) -> Void
21+
public typealias FailureHandler = (_ error: InstagramError) -> Void
2222

2323
// MARK: - Properties
2424

2525
private let urlSession = URLSession(configuration: .default)
2626
private let keychain = KeychainSwift()
2727
private let decoder = JSONDecoder()
2828

29-
private var clientId: String?
29+
private var client: InstagramClient?
3030

3131
// MARK: - Initializers
3232

33-
/// Shared instance of Instagram (singleton)
33+
/// Returns a shared instance of Instagram.
3434
public static let shared = Instagram()
3535

3636
private init() {
37-
let bundlePath = Bundle.main.path(forResource: "Info", ofType: "plist")
38-
39-
if let path = bundlePath, let dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] {
40-
self.clientId = dict["InstagramClientId"] as? String
37+
if client == nil, let path = Bundle.main.path(forResource: "Info", ofType: "plist"), let dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] {
38+
let clientId = dict["InstagramClientId"] as? String
39+
let redirectURI = dict["InstagramRedirectURI"] as? String
40+
client = InstagramClient(clientId: clientId, redirectURI: redirectURI)
4141
}
4242
}
4343

@@ -49,13 +49,14 @@ public class Instagram {
4949
///
5050
/// - Parameter navController: Your current `UINavigationController`.
5151
/// - Parameter scopes: The scope of the access you are requesting from the user. Basic access by default.
52-
/// - Parameter redirectURI: Your Instagram API client redirection URI.
5352
/// - Parameter success: The callback called after a correct login.
5453
/// - Parameter failure: The callback called after an incorrect login.
5554

56-
public func login(navController: UINavigationController, scopes: [InstagramScope] = [.basic], redirectURI: String, success: EmptySuccessHandler? = nil, failure: FailureHandler? = nil) {
57-
if let clientId = self.clientId {
58-
let vc = InstagramLoginViewController(clientId: clientId, scopes: scopes, redirectURI: redirectURI, success: { accessToken in
55+
public func login(navController: UINavigationController, scopes: [InstagramScope] = [.basic], success: EmptySuccessHandler? = nil, failure: FailureHandler? = nil) {
56+
client?.scopes = scopes
57+
58+
if let client = client {
59+
let vc = InstagramLoginViewController(client: client, success: { accessToken in
5960
if !self.keychain.set(accessToken, forKey: "accessToken") {
6061
failure?(InstagramError(kind: .keychainError(code: self.keychain.lastResultCode), message: "Error storing access token into keychain."))
6162
} else {
@@ -66,7 +67,7 @@ public class Instagram {
6667

6768
navController.show(vc, sender: nil)
6869
} else {
69-
failure?(InstagramError(kind: .missingClientId, message: "Instagram Client ID not provided."))
70+
failure?(InstagramError(kind: .missingClient, message: "Instagram Client not provided."))
7071
}
7172
}
7273

@@ -75,7 +76,7 @@ public class Instagram {
7576
/// - Returns: True if a session is currently available, false otherwise.
7677

7778
public func isSessionValid() -> Bool {
78-
return self.keychain.get("accessToken") != nil
79+
return keychain.get("accessToken") != nil
7980
}
8081

8182
/// Ends the current session.
@@ -84,7 +85,7 @@ public class Instagram {
8485

8586
@discardableResult
8687
public func logout() -> Bool {
87-
return self.keychain.delete("accessToken")
88+
return keychain.delete("accessToken")
8889
}
8990

9091
// MARK: -
@@ -99,7 +100,7 @@ public class Instagram {
99100
var urlRequest = URLRequest(url: buildURL(for: endpoint, withParameters: parameters))
100101
urlRequest.httpMethod = method.rawValue
101102

102-
self.urlSession.dataTask(with: urlRequest) { (data, _, error) in
103+
urlSession.dataTask(with: urlRequest) { (data, _, error) in
103104
if let data = data {
104105
DispatchQueue.global(qos: .utility).async {
105106
do {
@@ -128,7 +129,7 @@ public class Instagram {
128129

129130
var items = [URLQueryItem]()
130131

131-
let accessToken = self.keychain.get("accessToken")
132+
let accessToken = keychain.get("accessToken")
132133
items.append(URLQueryItem(name: "access_token", value: accessToken ?? ""))
133134

134135
parameters?.forEach({ parameter in
@@ -453,8 +454,7 @@ public class Instagram {
453454
/// to your own user.
454455

455456
public func like(media mediaId: String, failure: FailureHandler? = nil) {
456-
request("/media/\(mediaId)/likes", method: .post, success: { (_: InstagramResponse<Any?>) in return },
457-
failure: failure)
457+
request("/media/\(mediaId)/likes", method: .post, success: { (_: InstagramResponse<Any?>) in return }, failure: failure)
458458
}
459459

460460
/// Remove a like on this media by the currently authenticated user.

Sources/Models/InstagramClient.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// InstagramClient.swift
3+
// SwiftInstagram
4+
//
5+
// Created by Ander Goig on 8/10/17.
6+
// Copyright © 2017 Ander Goig. All rights reserved.
7+
//
8+
9+
struct InstagramClient {
10+
11+
let clientId: String?
12+
let redirectURI: String?
13+
var scopes: [InstagramScope] = [.basic]
14+
15+
init(clientId: String?, redirectURI: String?) {
16+
self.clientId = clientId
17+
self.redirectURI = redirectURI
18+
}
19+
20+
}

Sources/Models/InstagramComment.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@
1010

1111
public struct InstagramComment: Decodable {
1212

13+
/// The comment identifier.
1314
public let id: String
15+
16+
/// The comment text.
1417
public let text: String
15-
public let createdTime: String
18+
19+
/// The user who created the comment.
1620
public let from: InstagramUser
1721

22+
/// The date and time when the comment was created.
23+
public var createdDate: Date {
24+
return Date(timeIntervalSince1970: Double(createdTime)!)
25+
}
26+
27+
private let createdTime: String
28+
1829
private enum CodingKeys: String, CodingKey {
1930
case id, text, from
2031
case createdTime = "created_time"

Sources/Models/InstagramError.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,34 @@
66
// Copyright © 2017 Ander Goig. All rights reserved.
77
//
88

9-
/// The struct containing an Instagram error.
9+
/// A type representing an error value that can be thrown.
1010

1111
public struct InstagramError: Error {
1212

13-
public enum ErrorKind: CustomStringConvertible {
13+
enum ErrorKind: CustomStringConvertible {
1414
case invalidRequest
1515
case jsonParseError
1616
case keychainError(code: OSStatus)
17-
case missingClientId
17+
case missingClient
1818

19-
public var description: String {
19+
var description: String {
2020
switch self {
2121
case .invalidRequest:
2222
return "invalidRequest"
2323
case .jsonParseError:
2424
return "jsonParseError"
2525
case .keychainError(let code):
2626
return "keychainError(code: \(code)"
27-
case .missingClientId:
28-
return "missingClientId"
27+
case .missingClient:
28+
return "missingClient"
2929
}
3030
}
3131
}
3232

33-
public let kind: ErrorKind
34-
public let message: String
33+
let kind: ErrorKind
34+
let message: String
3535

36+
/// Retrieve the localized description for this error.
3637
public var localizedDescription: String {
3738
return "[\(kind.description)] - \(message)"
3839
}

Sources/Models/InstagramLocation.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,25 @@ import CoreLocation
1212

1313
public struct InstagramLocation: Codable {
1414

15-
let latitude: Double
16-
let longitude: Double
15+
/// The location identifier.
1716
public let id: String
17+
18+
/// The location name.
1819
public let name: String
20+
21+
/// The location address.
1922
public let streetAddress: String?
2023

24+
/// The location coordinates (latitude and logitude).
2125
public var coordinates: CLLocationCoordinate2D {
22-
return CLLocationCoordinate2D(latitude: self.latitude, longitude: self.longitude)
26+
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
2327
}
2428

29+
private let latitude: Double
30+
private let longitude: Double
31+
2532
private enum CodingKeys: String, CodingKey {
26-
case latitude, longitude, id, name
33+
case id, name, latitude, longitude
2734
case streetAddress = "street_address"
2835
}
2936

0 commit comments

Comments
 (0)