Network layer (ongoing)

This commit is contained in:
Rodrigo Pedroso 2019-06-27 00:23:14 -04:00
commit e348ad1eb1
5 changed files with 165 additions and 5 deletions

View file

@ -15,6 +15,8 @@
C10733CA22C468A40095EEDD /* repo_browserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10733C922C468A40095EEDD /* repo_browserTests.swift */; }; C10733CA22C468A40095EEDD /* repo_browserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10733C922C468A40095EEDD /* repo_browserTests.swift */; };
C10733D722C468F90095EEDD /* RepoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10733D522C468F90095EEDD /* RepoCell.swift */; }; C10733D722C468F90095EEDD /* RepoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10733D522C468F90095EEDD /* RepoCell.swift */; };
C10733D822C468F90095EEDD /* RepoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C10733D622C468F90095EEDD /* RepoCell.xib */; }; C10733D822C468F90095EEDD /* RepoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C10733D622C468F90095EEDD /* RepoCell.xib */; };
C10733DA22C46A370095EEDD /* RepoBrowser.plist in Resources */ = {isa = PBXBuildFile; fileRef = C10733D922C46A370095EEDD /* RepoBrowser.plist */; };
C10733DD22C46B3C0095EEDD /* RBRNetworkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10733DC22C46B3C0095EEDD /* RBRNetworkController.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -40,6 +42,8 @@
C10733CB22C468A40095EEDD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; C10733CB22C468A40095EEDD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C10733D522C468F90095EEDD /* RepoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepoCell.swift; sourceTree = "<group>"; }; C10733D522C468F90095EEDD /* RepoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepoCell.swift; sourceTree = "<group>"; };
C10733D622C468F90095EEDD /* RepoCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RepoCell.xib; sourceTree = "<group>"; }; C10733D622C468F90095EEDD /* RepoCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RepoCell.xib; sourceTree = "<group>"; };
C10733D922C46A370095EEDD /* RepoBrowser.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = RepoBrowser.plist; sourceTree = "<group>"; };
C10733DC22C46B3C0095EEDD /* RBRNetworkController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RBRNetworkController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -81,6 +85,7 @@
C10733B322C468A30095EEDD /* repo-browser */ = { C10733B322C468A30095EEDD /* repo-browser */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
C10733DB22C46AF80095EEDD /* Helpers */,
C10733D422C468E10095EEDD /* Cells */, C10733D422C468E10095EEDD /* Cells */,
C10733B422C468A30095EEDD /* AppDelegate.swift */, C10733B422C468A30095EEDD /* AppDelegate.swift */,
C10733B622C468A30095EEDD /* ViewController.swift */, C10733B622C468A30095EEDD /* ViewController.swift */,
@ -88,6 +93,7 @@
C10733BB22C468A40095EEDD /* Assets.xcassets */, C10733BB22C468A40095EEDD /* Assets.xcassets */,
C10733BD22C468A40095EEDD /* LaunchScreen.storyboard */, C10733BD22C468A40095EEDD /* LaunchScreen.storyboard */,
C10733C022C468A40095EEDD /* Info.plist */, C10733C022C468A40095EEDD /* Info.plist */,
C10733D922C46A370095EEDD /* RepoBrowser.plist */,
); );
path = "repo-browser"; path = "repo-browser";
sourceTree = "<group>"; sourceTree = "<group>";
@ -110,6 +116,14 @@
path = Cells; path = Cells;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
C10733DB22C46AF80095EEDD /* Helpers */ = {
isa = PBXGroup;
children = (
C10733DC22C46B3C0095EEDD /* RBRNetworkController.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -192,6 +206,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
C10733BF22C468A40095EEDD /* LaunchScreen.storyboard in Resources */, C10733BF22C468A40095EEDD /* LaunchScreen.storyboard in Resources */,
C10733DA22C46A370095EEDD /* RepoBrowser.plist in Resources */,
C10733BC22C468A40095EEDD /* Assets.xcassets in Resources */, C10733BC22C468A40095EEDD /* Assets.xcassets in Resources */,
C10733BA22C468A30095EEDD /* Main.storyboard in Resources */, C10733BA22C468A30095EEDD /* Main.storyboard in Resources */,
C10733D822C468F90095EEDD /* RepoCell.xib in Resources */, C10733D822C468F90095EEDD /* RepoCell.xib in Resources */,
@ -213,6 +228,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
C10733B722C468A30095EEDD /* ViewController.swift in Sources */, C10733B722C468A30095EEDD /* ViewController.swift in Sources */,
C10733DD22C46B3C0095EEDD /* RBRNetworkController.swift in Sources */,
C10733B522C468A30095EEDD /* AppDelegate.swift in Sources */, C10733B522C468A30095EEDD /* AppDelegate.swift in Sources */,
C10733D722C468F90095EEDD /* RepoCell.swift in Sources */, C10733D722C468F90095EEDD /* RepoCell.swift in Sources */,
); );

View file

@ -13,7 +13,7 @@
<!--View Controller--> <!--View Controller-->
<scene sceneID="tne-QT-ifu"> <scene sceneID="tne-QT-ifu">
<objects> <objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Repo_browser" customModuleProvider="target" sceneMemberID="viewController"> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="repo_browser" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/> <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -32,7 +32,7 @@
</constraints> </constraints>
</imageView> </imageView>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Repo owner" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="aUR-ad-ow1"> <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Repo owner" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="aUR-ad-ow1">
<rect key="frame" x="20" y="209" width="374" height="30"/> <rect key="frame" x="20" y="209" width="282" height="30"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="30" id="g87-Hx-hqO"/> <constraint firstAttribute="height" constant="30" id="g87-Hx-hqO"/>
</constraints> </constraints>
@ -45,13 +45,25 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableView> </tableView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ikr-FT-rQf">
<rect key="frame" x="310" y="209" width="78" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="78" id="4NP-fv-0qv"/>
<constraint firstAttribute="height" constant="30" id="ZiD-Ny-EUZ"/>
</constraints>
<state key="normal" title="Load"/>
<connections>
<action selector="loadRepo:" destination="BYZ-38-t0r" eventType="touchUpInside" id="Ebf-Os-9AI"/>
</connections>
</button>
</subviews> </subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="aUR-ad-ow1" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="4yT-pH-1sr"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="aUR-ad-ow1" secondAttribute="trailing" constant="20" id="5B0-r3-Ixy"/>
<constraint firstItem="oNG-Cv-10h" firstAttribute="top" secondItem="eQv-L9-z0k" secondAttribute="bottom" constant="8" id="6oz-5Q-p2y"/> <constraint firstItem="oNG-Cv-10h" firstAttribute="top" secondItem="eQv-L9-z0k" secondAttribute="bottom" constant="8" id="6oz-5Q-p2y"/>
<constraint firstItem="ikr-FT-rQf" firstAttribute="top" secondItem="aUR-ad-ow1" secondAttribute="top" id="Azg-LF-tAW"/>
<constraint firstItem="ikr-FT-rQf" firstAttribute="leading" secondItem="aUR-ad-ow1" secondAttribute="trailing" constant="8" id="E5H-wj-pA3"/>
<constraint firstItem="aUR-ad-ow1" firstAttribute="top" secondItem="oNG-Cv-10h" secondAttribute="bottom" constant="8" id="EJ6-Zk-hrd"/> <constraint firstItem="aUR-ad-ow1" firstAttribute="top" secondItem="oNG-Cv-10h" secondAttribute="bottom" constant="8" id="EJ6-Zk-hrd"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="ikr-FT-rQf" secondAttribute="trailing" constant="26" id="Pbn-h4-lhZ"/>
<constraint firstItem="oNG-Cv-10h" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="dQj-eo-yYS"/> <constraint firstItem="oNG-Cv-10h" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="dQj-eo-yYS"/>
<constraint firstItem="eQv-L9-z0k" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="rWA-3I-6aE"/> <constraint firstItem="eQv-L9-z0k" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="rWA-3I-6aE"/>
<constraint firstItem="aUR-ad-ow1" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="20" id="uPl-hj-HvI"/> <constraint firstItem="aUR-ad-ow1" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="20" id="uPl-hj-HvI"/>

View file

@ -0,0 +1,60 @@
//
// RBRNetworkController.swift
// repo-browser
//
// Created by Rodrigo Pedroso on 2019-06-26.
// Copyright © 2019 Rodrigo Pedroso Leite Pinto. All rights reserved.
//
import UIKit
protocol RBRNetworkControllerDelegate: class {
func messageServerDown()
}
class RBRNetworkController: NSObject {
var network: Dictionary<NSObject, AnyObject> = [:]
var api: String = ""
var token: String = ""
let timeOut: TimeInterval = 6.0
weak var delegate: RBRNetworkControllerDelegate?
// MARK: - Initialization
override init() {
// Storing server URL into 'api'
if let path = Bundle.main.path(forResource: "RepoBrowser", ofType: "plist"), let dict = NSDictionary(contentsOfFile: path) {
token = dict["token"] as! String
network = (dict["Network"] as? Dictionary<NSObject, AnyObject>)!
api = network["api" as NSString] as! String
}
}
// MARKL - Network calls
func getRepos(owner: String, completion: @escaping (_ data: Data?, _ HTTPStatusCode: Int, _ error: NSError?) -> Void) {
let urlString: String = api + owner
let targetURL = URL(string: urlString)
var request = URLRequest(url: targetURL!)
request.addValue("application/vnd.github.v3+json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
request.timeoutInterval = timeOut
let session = URLSession.shared
session.dataTask(with: request) {
data, response, err in DispatchQueue.main.async(execute: {
() -> Void in
if (response as? HTTPURLResponse) != nil {
completion(data, (response as! HTTPURLResponse).statusCode, err as NSError?)
}
else {
print("No response: \(String(describing: err))")
self.delegate?.messageServerDown()
}
})
}.resume()
}
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>token</key>
<string>c250629cdcb2d4b36fe85274dcab73917c09d2c4</string>
<key>Network</key>
<dict>
<key>api</key>
<string>https://api.github.com/repos/</string>
</dict>
</dict>
</plist>

View file

@ -8,7 +8,7 @@
import UIKit import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, RBRNetworkControllerDelegate {
@IBOutlet var txfRepoOwner: UITextField! @IBOutlet var txfRepoOwner: UITextField!
@IBOutlet var tblRepoTable: UITableView! @IBOutlet var tblRepoTable: UITableView!
@ -16,6 +16,7 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
let cellIdentifier = "RepoCell" let cellIdentifier = "RepoCell"
var dataSource: Array<Dictionary<String, String>> = [] var dataSource: Array<Dictionary<String, String>> = []
var selectedIndex: Int! var selectedIndex: Int!
let netController = RBRNetworkController()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -64,4 +65,62 @@ class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSour
selectedIndex = indexPath.row selectedIndex = indexPath.row
performSegue(withIdentifier: "sortedDetailSegue", sender: self) performSegue(withIdentifier: "sortedDetailSegue", sender: self)
} }
// MARK: - Network calls
/**
Get all repositories of a user
*/
func getRepos() {
if let owner = txfRepoOwner.text {
weak var weakSelf = self
DispatchQueue.global(qos: .userInitiated).async {
weakSelf?.netController.getRepos(owner: owner, completion: { (data, HTTPStatusCode, error) in
if HTTPStatusCode == 200 && error == nil {
do {
let result = try JSONSerialization.jsonObject(with: data!, options: []) as! Array<Dictionary<String, AnyObject>>
print(result)
// weakSelf?.btnConfigUsers.isHidden = self.appChildren.count > 0 ? false : true
// weakSelf?.cltChildrenCollection.reloadData()
}
catch {
print("Post request try/catch error: \(error)")
}
}
else {
print("Error retrieving repo")
}
})
}
}
else {
self.warnMessage(msg: "Please fill repository owner field")
}
}
// MARK: - Action
@IBAction func loadRepo(_ sender: UIButton) {
self.getRepos()
}
// MARK: - Helpers
func warnMessage(msg: String) {
let alert = UIAlertController(title: "Error", message: msg, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: - Delegates
func messageServerDown() {
let msg: String = "The server is not responding. Please try again later."
let alert = UIAlertController(title: "Error", message: msg, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
} }