Different ways of adding items to a dictionary with different results - swift2

I'm dabbling in swift after a long time away and I've hit an issue that I can't figure out. I'm trying two different ways to add items to a dictionary and getting some different results.
I was initially adding values to a dictionary by doing:
userInfo = ["username":username]
userInfo = ["email":email]
userInfo = ["password":password]
I would then print("\(userInfo)") but it would only contain password.
I then tried switching it up to:
userInfo!["username"] = username
userInfo!["email"] = email
userInfo!["password"] = password
but this resulted in fatal error: unexpectedly found nil while unwrapping an Optional value for username
I finally switched it to the following configuration
userInfo = ["username":username]
userInfo!["email"] = email
userInfo!["password"] = password
and everything prints put. Whats up with that?
Full implementation:
nextPressed()
{
if let userInfo:[String:String] = try registrationValidation()
{
print("\(userInfo)")
}
}
func registrationValidation () throws -> [String:String]?
{
var userInfo: [String:String]?
var problems: [ValidationMessage] = []
if let username = usernameField.text
{
let p1 = validateUsername(username)
problems.appendContentsOf(p1)
userInfo = ["username":username]
//userInfo!["username"] = username
//Above results in nil, yet lines below work?
}
if let email = emailField.text
{
let p2 = validateEmail(email)
problems.appendContentsOf(p2)
//userInfo = ["email":email]
userInfo!["email"] = email
}
if let password = passwordField.text
{
let p3 = validatePassword(password)
problems.appendContentsOf(p3)
//userInfo = ["password":password]
userInfo!["password"] = password
}
if !problems.isEmpty{
throw ValidationError(problems:problems)
}
else
{
print("validation succeeded")
return userInfo
}
}

I think this would be a better way to do what you want to achieve like :
func registrationValidation () throws -> [String:String]?
{
var userInfo = [String:String]() // **Initialize an empty dictionary**
var problems: [ValidationMessage] = []
if let username = usernameField.text
{
let p1 = validateUsername(username)
problems.appendContentsOf(p1)
userInfo["username"] = username
}
if let email = emailField.text
{
let p2 = validateEmail(email)
problems.appendContentsOf(p2)
//userInfo = ["email":email] **// This line will result in creating a new dictionary object**
userInfo["email"] = email
}
if let password = passwordField.text
{
let p3 = validatePassword(password)
problems.appendContentsOf(p3)
//userInfo = ["password":password]
userInfo["password"] = password
}
if !problems.isEmpty{
throw ValidationError(problems:problems)
}
else
{
print("validation succeeded")
return userInfo
}
}

Related

How work history of web browser under the hood

I am trying to implement my own web browser history for WKWebView on iOS, but I can't implement this functionality completely, and each time I obtain trouble.
I can create a history where the user did be and then moving forward and backward inside history.
But I have next trouble, and I think it an only one of many problems on my way.
When I have a history with for example 10 elements, and then I am moving back to element number 5 and then go don't forward but try to open the new link I can't remove element 6-10 and put the new link.
I think my problem that I can't fully understand how history work inside all browsers under the hood, this is not a hard task but I am confused inside this algorithm.
My main data structure for holding history
Help me understand how to work this algorithm inside browsers or maybe exist a good theory about it?
I have solved this problem and realize the full algorithm well, the completed project available here: https://github.com/IhorYachmenov/Custom-browser-history-for-WKWebView.
Algorithm:
struct PlayerHistory {
static var shared = PlayerHistory()
var historyExist: Bool = false
var historyCurrentPosition: Int = 0
var historyLastPositionBeforeUpdatingHistory: Int!
var userHistoryKey: String!
var backPressed: Bool!
var forwardPressed: Bool!
var urlOfPlayer: String!
// Function only for first loading inside <viewDidLoad or another method from app LifeCycle>.
mutating func getUrlForFirstLoading(initURL: String, key: String) -> String {
urlOfPlayer = initURL
guard HistoryStorage.shared.getHistoryFromUserDefaults() != nil else {
updateFirstElement(key: key, url: initURL)
return initURL
}
guard HistoryStorage.shared.getHistoryFromUserDefaults()![key] != nil else {
return initURL
}
let position = HistoryStorage.shared.getHistoryFromUserDefaults()![key]!.count - 1
historyExist = true
historyCurrentPosition = position
userHistoryKey = key
let initUrlFromHistoryStorage = HistoryStorage.shared.getHistoryFromUserDefaults()![key]!.last!.url
return initUrlFromHistoryStorage
}
// Create new or update exist history, use this method indsede <decidePolicyForNavigation>.
mutating func updatePlayerHistory(backlisk: [String], key: String) {
var history = [WebViewHistory]()
for i in backlisk {
history.append(WebViewHistory(i))
}
if (historyExist == true) {
// If old history exist need compound both and then to save.
let oldHistory = HistoryStorage.shared.getHistoryFromUserDefaults()![key]
let oldAndNewHostoryTogether = oldHistory! + history
var keyValuePair = Dictionary<String, [WebViewHistory]>()
keyValuePair.updateValue(oldAndNewHostoryTogether, forKey: key)
HistoryStorage.shared.removeHistory()
HistoryStorage.shared.saveHistory(keyValuePair)
setCurrentPosition(url: backlisk.last!, key: key)
} else {
var keyValuePair = Dictionary<String, [WebViewHistory]>()
keyValuePair.updateValue(history, forKey: key)
historyExist = true
HistoryStorage.shared.removeHistory()
HistoryStorage.shared.saveHistory(keyValuePair)
setCurrentPosition(url: backlisk.last!, key: key)
}
}
// Before using this method check if result don't equals nil. Use this method for navigation beetween history
func moveThroughHistory(key: String, direction: Bool) -> String? {
guard historyExist != false else {
return nil
}
let history = HistoryStorage.shared.getHistoryFromUserDefaults()![key]!
if (direction == true) {
let index = historyCurrentPosition + 1
guard index != history.count else { return nil }
return history[index].url
} else {
let index = historyCurrentPosition - 1
guard index > 0 else { return history[0].url }
return history[index].url
}
}
// Method <setCurrentPosition> each time set position at history
mutating func setCurrentPosition(url: String, key: String) {
guard HistoryStorage.shared.getHistoryFromUserDefaults() != nil else { return }
guard HistoryStorage.shared.getHistoryFromUserDefaults()![key] != nil else { return }
let history = HistoryStorage.shared.getHistoryFromUserDefaults()![key]
let index = history?.firstIndex(of: WebViewHistory(url))
guard index != nil else {
historyCurrentPosition = 0
return
}
historyCurrentPosition = index!
}
// <removeUnusedPeaceOfHistory> need use when user want open new page staying inside the middle of history
mutating func removeUnusedPeaceOfHistory(key: String) {
guard HistoryStorage.shared.getHistoryFromUserDefaults() != nil else {
return
}
guard HistoryStorage.shared.getHistoryFromUserDefaults()![key] != nil else {
return
}
var history = HistoryStorage.shared.getHistoryFromUserDefaults()![key]!
let startIndex = historyCurrentPosition + 1
let endIndex = history.endIndex - 1
let countOfAllElements = history.count
guard startIndex != countOfAllElements else { return }
let range = startIndex...endIndex
history.removeSubrange(range)
var keyValuePair = Dictionary<String, [WebViewHistory]>()
keyValuePair.updateValue(history, forKey: key)
HistoryStorage.shared.removeHistory()
HistoryStorage.shared.saveHistory(keyValuePair)
}
// Use <updateFirstElement> inside <getUrlForFirstLoading> if history doesn't exist
private mutating func updateFirstElement(key: String, url: String) {
var history = [WebViewHistory]()
history.insert(WebViewHistory(url), at: 0)
var keyValuePair = Dictionary<String, [WebViewHistory]>()
keyValuePair.updateValue(history, forKey: key)
HistoryStorage.shared.saveHistory(keyValuePair)
historyExist = true
historyCurrentPosition = 0
}
// Use <webViewWillBeClosedSaveHistory> when WKWebView should be closed, if the user moves through history new position will be saved.
mutating func webViewWillBeClosedSaveHistory(key: String) {
let history = HistoryStorage.shared.getHistoryFromUserDefaults()![key]!
let currentPosition = historyCurrentPosition + 1
guard currentPosition != history.count else { return }
removeUnusedPeaceOfHistory(key: key)
}
}

Return ldap entries on paginated form in springboot

I have a ldap method that returns all users that are in it (almost 1300 users) and I want to return them by page, similar to what PagingAndSortingRepository does in Springboot:
If I have this endpoint ( users/?page=0&size=1 )and I wnat to return on page 0 just 1 entry.
Is there any way to do that?
Currently I have this but it doesn´t work:
SearchRequest searchRequest = new SearchRequest(ldapConfig.getBaseDn(), SearchScope.SUB,
Filter.createEqualityFilter("objectClass", "person"));
ASN1OctetString resumeCookie = null;
while (true) {
searchRequest.setControls(new SimplePagedResultsControl(pageable.getPageSize(), resumeCookie));
SearchResult searchResult = ldapConnection.search(searchRequest);
numSearches++;
totalEntriesReturned += searchResult.getEntryCount();
for (SearchResultEntry e : searchResult.getSearchEntries()) {
String[] completeDN = UaaUtils.searchCnInDn(e.getDN());
String[] username = completeDN[0].split("=");
UserEntity u = new UserEntity(username[1]);
list.add(u);
System.out.println("TESTE");
}
SimplePagedResultsControl responseControl = SimplePagedResultsControl.get(searchResult);
if (responseControl.moreResultsToReturn()) {
// The resume cookie can be included in the simple paged results
// control included in the next search to get the next page of results.
System.out.println("Antes "+resumeCookie);
resumeCookie = responseControl.getCookie();
System.out.println("Depois "+resumeCookie);
} else {
break;
}
Page<UserEntity> newPage = new PageImpl<>(list, pageable, totalEntriesReturned);
System.out.println("content " + newPage.getContent());
System.out.println("total elements " + newPage.getTotalElements());
System.out.println(totalEntriesReturned);
}
I'm unsure if this is the proper way, but here's how I went about it:
public PaginatedLookup getAll(String page, String perPage) {
PagedResultsCookie cookie = null;
List<LdapUser> results;
try {
if ( page != null ) {
cookie = new PagedResultsCookie(Hex.decode(page));
} // end if
Integer pageSize = perPage != null ? Integer.parseInt(perPage) : PROCESSOR_PAGE_SIZE;
PagedResultsDirContextProcessor processor = new PagedResultsDirContextProcessor(pageSize, cookie);
LdapName base = LdapUtils.emptyLdapName();
SearchControls sc = new SearchControls();
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
sc.setTimeLimit(THREE_SECONDS);
sc.setCountLimit(pageSize);
sc.setReturningAttributes(new String[]{"cn", "title"});
results = ldapTemplate.search(base, filter.encode(), sc, new PersonAttributesMapper(), processor);
cookie = processor.getCookie();
} catch ( Exception e ) {
log.error(e.getMessage());
return null;
} // end try-catch
String nextPage = null;
if ( cookie != null && cookie.getCookie() != null ) {
nextPage = new String(Hex.encode(cookie.getCookie()));
} // end if
return new PaginatedLookup(nextPage, results);
}
The main issue I kept on hitting was trying to get the cookie as something that could be sent to the client, which is where my Hex.decode and Hex.encode came in handy.
PersonAttributesMapper is a private mapper that I have to make the fields more human readable, and PaginatedLookup is a custom class I use for API responses.

Receive a notification key from ios

I have the following command where I get my notification in ios, I want to get my key more I'm not getting it, what I tried was
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
Messaging.SharedInstance.AppDidReceiveMessage(userInfo);
NSString[] keys = { new NSString("Event_type") };
NSObject[] values = { new NSString("Recieve_Notification") };
var parameters = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(keys, values, keys.Length);
Firebase.Analytics.Analytics.LogEvent("CustomEvent", parameters);
System.Diagnostics.Debug.WriteLine(userInfo);
// var aps_d = userInfo["aps"] as NSDictionary;
//var alert_d = aps_d["alert"] as NSDictionary;
//var body = alert_d["keys"] as NSString;
}
System.Diagnostics.Debug.WriteLine
receive this
[0:] {
aps = {
alert = {
body = "teste";
title = "teste";
};
};
"gcm.message_id" = "0:1505400569099941%712ac0f8712a1234";
"gcm.n.e" = 1;
"google.c.a.c_id" = 5974019197827881234;
"google.c.a.c_l" = "teste";
"google.c.a.e" = 1;
"google.c.a.ts" = 1505400123;
"google.c.a.udt" = 0;
keys = 152113;
}
keys is a top level and last entry in the dictionary, so you can directly access it via userInfo["keys"], i.e:
var keys = userInfo["keys"] as NSString;

How to wait for a background function to finish before calling another one in swift?

I will try to explain briefly what the situation is.
I am building a quiz app and I wanted it to work mainly using the internet, but also to work for a while when the user is disconnected. The older code I was using was made only with synchronous queries, it was taking more time than what I expected. So i decided to reformulate it.
The situation I projected is the following:
When my user selects a subject the app will synchronously get 1 question for each subsubject in order to be ready for my user click and to be faster.
After getting this first question, the app would then get another 4 (or how much is needed to complete 5) for each of the subsubjects asynchronously, while the user is occupied answering the first question that was presented to him.
Finally, the app would save the objects in the local datastore, so that the user can answer 5 questions for each subsubject when he is not connected.
Here is my code:
func getQuestionsRemotelyandSave (subsubject:String?, subject:String?, arrayOfSubsubjects:[String]?) {
self.getFromUserDefaults()
if Reachability.isConnectedToNetwork() == true {
if self.needsToGetQuestions == true {
let user = PFUser.currentUser()
var query = PFQuery(className: "Questions")
query.whereKey("answeredBy", equalTo: user)
query.whereKey("grade", equalTo: user["grade"])
if subsubject != nil && subject == nil {
query.whereKey("subsubject", equalTo: subsubject)
query.limit = 2
let array = query.findObjects()
for item in array {
let object = item as PFObject
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pin()
}
query.limit = 3
query.findObjectsInBackgroundWithBlock({ (objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
let questions = objects as [PFObject]
var QuestionsToPin = [PFObject]()
for object in questions {
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pinInBackground()
}
}
})
}
if subsubject == nil && subject != nil {
var firstTime = true
var semaphore = dispatch_semaphore_create(0)
query.limit = 1
for item in arrayOfSubsubjects! {
if item != "Todas as matérias" {
var query3 = PFQuery(className: "Questions")
query3.fromLocalDatastore()
query3.whereKey("subsubject", equalTo: item)
let count = query3.countObjects()
if count == 0 {
query.whereKey("subsubject", equalTo: item)
let array:NSArray = query.findObjects()
for item in array {
let object = item as PFObject
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pin()
}
}
if count > 0 {
var limit = 5 - count
if limit < 0 {
limit = 0
}
query.limit = limit
if firstTime == false {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}
query.findObjectsInBackgroundWithBlock({ (objects:[AnyObject]!, error:NSError?) -> Void in
if error == nil {
let questions = objects as [PFObject]
for object in questions {
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pinInBackground()
}
dispatch_semaphore_signal(semaphore)
firstTime = false
}
})
}
}
}
}
}
}
}
The problem I'm facing is that I cant request multiple asynchronous functions from Parse. What I thought was maybe waiting for an asynchronous function to finish before the other one starts, but I wanted it to happen without the user having to wait. Is there a way of doing it?
Thank you.

Windows azure - the specified table not found

I'm trying to get the daa from windows azure storage but I'm getting table not found. I've already saw the others answers but nothing works...
I did try this:
private void popula()
{
var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Conn"));
account.CreateCloudTableClient().CreateTableIfNotExist("fiscal");
var context = new CRUDManifestacoesEntities(account.TableEndpoint.ToString(), account.Credentials);
Hashtable ht = (Hashtable)ViewState["filtro"];
var teste = ViewState["x"].ToString();
if (ht == null)
GridView1.DataSource = context.SelectConc(teste);
else
GridView1.DataSource = context.SelectConc(ht);
}
public List<ManifestacaoGrid> SelectConc(string conc)
{
conc = Crypto.DecryptString(conc);
IQueryable<ManifestacaoEntity> results = null;
if (!conc.Equals("dfg"))
results = from c in ManifestacaoEntities where c.concessionaria == conc select c;
else
results = from c in ManifestacaoEntities select c;
var query = results.AsTableServiceQuery<ManifestacaoEntity>();
var queryResults = query.Execute();
List<ManifestacaoGrid> al = new List<ManifestacaoGrid>();
foreach (ManifestacaoEntity mf in queryResults)
{
.......
}
I'm getting this error:
TableNotFoundThe table specified does not exist.
RequestId:285f6ef7-b1ce-4c21-9406-3e9f6a58755b
Time:2014-01-15T14:30:55.7989535Z
EDIT: I did print '_account' to see if the credentials are correct:
var credencial = "Connection string with sensitive data: " + account.ToString(true);
and the AccountName and AccountKey are correct ...but how can I know if the requested table is correct?
The secundary key is needed in storage account?
I did found the problem. I write
public IQueryable<UserEntity> UserEntities
{
get
{
return this.CreateQuery<UserEntity>("tableName");
}
}
Instead of:
public IQueryable<UserEntity> UserEntities
{
get
{
return this.CreateQuery<UserEntity>("UserEntities");
}
}

Resources