let loginButton = FBSDKLoginButton() loginButton.center = self.view.center loginButton.readPermissions = ["user_posts"] loginButton.delegate = self
// MARK: Facebook Delegate Methods func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) { if ((error) != nil) { // Process error let alert = UIAlertController(title: "", message: error.localizedDescription, preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } else if result.isCancelled { let alert = UIAlertController(title: "", message: "Result is cancelled", preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } else { let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc = storyboard.instantiateViewControllerWithIdentifier("navController") as! UINavigationController self.presentViewController(vc, animated: true, completion: nil) } } func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) { print("User Logged Out") }
func getFeeds() -> Observable<GetFeedsResponse> { return Observable.create { observer in let parameters = ["fields": ""] let friendsRequest = FBSDKGraphRequest.init(graphPath: "me/feed", parameters: parameters, HTTPMethod: "GET") friendsRequest.startWithCompletionHandler { (connection, result, error) -> Void in if error != nil { observer.on(.Error(error!)) } else { let getFeedsResponse = Mapper<GetFeedsResponse>().map(result)! observer.on(.Next(getFeedsResponse)) observer.on(.Completed) } } return AnonymousDisposable { } } }
let parameters = ["fields": ""]
with an empty parameter set. This is necessary so that Facebook does not class GetFeedsResponse: Mappable { var data = [Feed]() var paging: Paging! required init?(_ map: Map){ } // Mappable func mapping(map: Map) { data <- map["data"] paging <- map["paging"] } } class Feed: Mappable { var createdTime: String! var id: String! var story: String? var message: String? required init?(_ map: Map){ } // Mappable func mapping(map: Map) { createdTime <- map["created_time"] id <- map["id"] story <- map["story"] message <- map["message"] } } class Paging: Mappable { var next: String! var previous: String! required init?(_ map: Map){ } // Mappable func mapping(map: Map) { next <- map["next"] previous <- map["previous"] } }
func getFeedInfo(feedId: String) -> Observable<GetFeedInfoResponse> { return Observable.create { observer in let parameters = ["fields" : "id,admin_creator,application,call_to_action,caption,created_time,description,feed_targeting,from,icon,is_hidden,is_published,link,message,message_tags,name,object_id,picture,place,privacy,properties,shares,source,status_type,story,story_tags,targeting,to,type,updated_time,with_tags"] let friendsRequest = FBSDKGraphRequest.init(graphPath: "" + feedId, parameters: parameters, HTTPMethod: "GET") friendsRequest.startWithCompletionHandler { (connection, result, error) -> Void in if error != nil { observer.on(.Error(error!)) } else { print(result) let getFeedInfoResponse = Mapper<GetFeedInfoResponse>().map(result)! observer.on(.Next(getFeedInfoResponse)) observer.on(.Completed) } } return AnonymousDisposable { } } }
class GetFeedInfoResponse: Mappable { var createdTime: String! var from: IdName! var id: String! var isHidden: Bool! var isPublished: Bool! var message: String? var name: String? var statusType: String? var story: String? var to = [IdName]() var type: String! var updatedTime: String! required init?(_ map: Map){ } // Mappable func mapping(map: Map) { createdTime <- map["created_time"] from <- map["from"] id <- map["from"] isHidden <- map["is_hidden"] isPublished <- map["is_published"] message <- map["message"] name <- map["name"] statusType <- map["status_type"] story <- map["story"] // It necessary that Facebook API have a bad structure // buffer%varname% is a temporary variable var bufferTo = NSDictionary() bufferTo <- map["to"] if let bufferData = bufferTo["data"] as? NSArray { for bufferDataElement in bufferData { let bufferToElement = Mapper<IdName>().map(bufferDataElement) to.append(bufferToElement!) } } type <- map["type"] updatedTime <- map["updated_time"] } } class IdName: Mappable { var id: String! var name: String! required init?(_ map: Map){ } // Mappable func mapping(map: Map) { id <- map["id"] name <- map["name"] } }
var bufferTo = NSDictionary() bufferTo <- map["to"] if let bufferData = bufferTo["data"] as? NSArray { for bufferDataElement in bufferData { let bufferToElement = Mapper<IdName>().map(bufferDataElement) to.append(bufferToElement!) } }
class FeedsViewModel { let feedsObservable: Observable<[Feed]> let clickObservable: Observable<GetFeedInfoResponse> // If some process in progress let indicator: Observable<Bool> init(input: ( UITableView ), dependency: ( API: APIManager, wireframe: Wireframe ) ) { let API = dependency.API let wireframe = dependency.wireframe let indicator = ViewIndicator() self.indicator = indicator.asObservable() feedsObservable = API.getFeeds() .trackView(indicator) .map { getFeedResponse in return getFeedResponse.data } .catchError { error in return wireframe.promptFor(String(error), cancelAction: "OK", actions: []) .map { _ in return error } .flatMap { error in return Observable.error(error) } } .shareReplay(1) clickObservable = input .rx_modelSelected(Feed) .flatMap { feed in return API.getFeedInfo(feed.id).trackView(indicator) } .catchError { error in return wireframe.promptFor(String(error), cancelAction: "OK", actions: []) .map { _ in return error } .flatMap { error in return Observable.error(error) } } // If error when click uitableview - set retry() if you want to click cell again .retry() .shareReplay(1) } }
class FeedsViewController: UIViewController, UITableViewDelegate { @IBOutlet weak var feedsTableView: UITableView! var disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() let viewModel = FeedsViewModel( input:feedsTableView, dependency: ( API: APIManager.sharedAPI, wireframe: DefaultWireframe.sharedInstance ) ) let progress = MBProgressHUD() progress.mode = MBProgressHUDMode.Indeterminate progress.labelText = " ..." progress.dimBackground = true viewModel.indicator .bindTo(progress.rx_mbprogresshud_animating) .addDisposableTo(self.disposeBag) feedsTableView.rx_setDelegate(self) viewModel.feedsObservable .bindTo(feedsTableView.rx_itemsWithCellFactory) { tableView, row, feed in let cell = tableView.dequeueReusableCellWithIdentifier("feedTableViewCell") as! FeedTableViewCell cell.feedCreatedTime.text = NSDate().convertFacebookTime(feed.createdTime) if let story = feed.story { cell.feedInfo.text = story } else if let message = feed.message { cell.feedInfo.text = message } cell.layoutMargins = UIEdgeInsetsZero return cell } .addDisposableTo(disposeBag) viewModel.clickObservable .subscribeNext { feed in let storyboard = UIStoryboard(name: "Main", bundle: nil) let feedInfoViewController = storyboard.instantiateViewControllerWithIdentifier("feedInfoViewController") as! FeedInfoViewController feedInfoViewController.feedInfo = feed self.navigationController?.pushViewController(feedInfoViewController, animated: true) } .addDisposableTo(disposeBag) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // Deselect tableView row after click func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) } }
extension MBProgressHUD { /** Bindable sink for MBProgressHUD show/hide methods. */ public var rx_mbprogresshud_animating: AnyObserver<Bool> { return AnyObserver {event in MainScheduler.ensureExecutingOnScheduler() switch (event) { case .Next(let value): if value { let loadingNotification = MBProgressHUD.showHUDAddedTo(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true) loadingNotification.mode = self.mode loadingNotification.labelText = self.labelText loadingNotification.dimBackground = self.dimBackground } else { MBProgressHUD.hideHUDForView(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true) } case .Error(let error): let error = "Binding error to UI: \(error)" #if DEBUG rxFatalError(error) #else print(error) #endif case .Completed: break } } } }
viewModel.indicator .bindTo(progress.rx_mbprogresshud_animating) .addDisposableTo(self.disposeBag)
override func viewDidLoad() { super.viewDidLoad() var feedDetail = "From: " + feedInfo.from.name if feedInfo.to.count > 0 { feedDetail += "\nTo: " for to in feedInfo.to { feedDetail += to.name + "\n" } } if let date = feedInfo.createdTime { feedDetail += "\nDate: " + NSDate().convertFacebookTime(date) } if let story = feedInfo.story { feedDetail += "\nStory: " + story } if let message = feedInfo.message { feedDetail += "\nMessage: " + message } if let name = feedInfo.name { feedDetail += "\nName: " + name } if let type = feedInfo.type { feedDetail += "\nType: " + type } if let updatedTime = feedInfo.updatedTime { feedDetail += "\nupdatedTime: " + NSDate().convertFacebookTime(updatedTime) } feedTextView.text = feedDetail self.navigationController?.navigationBar.tintColor = UIColor.whiteColor() }
Source: https://habr.com/ru/post/276971/
All Articles