XCode nu suportă versiunea actuală de IOS. Ce este de făcut?

Tocmai ce-am făcut update la ultima versiune de IOS – 11.3 (15E216) și bineînțeles că versiunea mea de XCode – 9.2 (9C40b) nu mai îmi poate “vedea” telefonul pentru teste.Din ce motiv se întâmplă acest lucru?

Ori de câte ori este lansată o nouă versiune semnificativă de iOS, Apple lansează și o nouă versiune de XCode. La sfârșitul lunii martie 2018 a fost lansată versiunea 11.3 de IOS simultan cu XCode 9.3, prin urmare dacă sunt developer și îmi actualizez telefonul la ultima versiune de IOS, musai trebuie să actualizez și XCode-ul. Însă developer-ii nu-și actualizează XCode-ul imediat după apariția sa, acest lucru însemnând, de cele mai multe ori, upgrade de proiect.
Revenind, nouă versiune de XCode – 9.3 conține DeveloperDiskImage, un folder având numele versiunii, în cazul nostru – 11.3 (15E216), necesară pentru a rula proiectele pe cele mai recente versiuni de iOS. Prin urmare, pentru a rula o aplicație pe un IOS 11.3 ar trebui neapărat să actualizăm XCode-ul la 9.3.

Cum putem ieși din acest impas?
Momentan, țin XCode-ul la 9.2 fiind limitat de faptul că 9.3 îmi cere și upgrade la sistemul de operare, fiind necesar High Sierra. Soluția utilizată în aceste situații este folosirea unui disk DeveloperDiskImage de IOS 11.3 de la un XCode 9.3 pe care să-l importăm în Xcode-ul nostru 9.2. Practic, este un folder care va ști să “asculte” device-urile cu IOS 11.3 pe versiuni inferioare de XCode.

Această arhivă conține DeveloperDiskImage de IOS – 11.3 (15E216). Conținutul arhivei, folderul numit 11.3 (15E216) trebuie copiat în /Application/XCode/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/. Restart la XCode-ul nostru și acum putem rula aplicațiile noastre din XCode 9.2 în IOS 11.3

Share Button

Profanity list – Swift3

Adium pentru IOS are un plugin special pentru filtrarea cuvintelor urate – profanity list – care in schimb e foarte Objective C.
Am modelat in playground o clasa speciala de Regular Expression prin intermediul careia filtrez continutul unui dictionar. Ideea de baza este de aici

var badWordDictionary: [String : String] = [
"cuvant1" : "*******",
"cuvant2" : "*******",
"cuvant3" : "*******",
"cuvant4" : "*******",
"cuvant5" : "*******",
"cuvant6" : "*******",
]
var bannedWords = badWordDictionary.keys
var bannedPattern = bannedWords.joined(separator: "|")
var badWordPattern = "\\b(?:\(bannedPattern))\\b"

class MeetMeBadWordRegularExpression: NSRegularExpression {
override func replacementString(for result: NSTextCheckingResult, in string: String, offset: Int, template templ: String) -> String {
let matchingRange = result.range
let matchingWord = (string as NSString).substring(with: matchingRange)
if let replacedWord = badWordDictionary[matchingWord] {
return replacedWord
} else {
return "*"
}
}
}

Apoi vom folosi astfel:

var bodyMessage = "acesta este cuvant1"
let regex = try! MeetMeBadWordRegularExpression(pattern: badWordPattern, options: [])
let clearBodyMessage = regex.stringByReplacingMatches(in: bodyMessage as! String, options: [], range: NSRange(0..<(bodyMessage as! String).utf16.count), withTemplate: "") print("clean message - \(clearBodyMessage)")

Vom avea clean message - acesta este *******

Share Button

Transmiterea unei imagini in format base64 catre server in Swift3

Avem o imagine. O transformam in string pentru a o putea transfera catre un server tert:

let image = UIImage(...)
let imageData = UIImageJPEGRepresentation(image!, 0.7)
let imageString:String = imageData!.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength64Characters) as String

Ca si observatie, e important sa stabilim optiunea lineLength64Characters pentru codarea imaginii, acesta fiind formatul folosit de un server Apache pentru decodarea base64.

Avem deci in acest moment un string ce contine o imagine pe care dorim sa o trimitem spre un server web.

Folosim un request de tip POST in care specificam metoda de codare x-www-form-urlencoded:

request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

In momentul in care facem request-ul totul este frumos in aplicatia IOS insa pe server toate caracterele “+” sunt codate ” ” adica blank space. Nimeni nu ar observa acest lucru, mai ales ca nu apare nici un warning, nici o eroare pe device-ul IOS. Insa server-side, la decodificarea stringului base64 receptionat vom avea o eroare din cauza faptului ca nu poate fi scoasa imaginea de acolo.

Solutia?

Trebuie sa inlocuim in stringul base64 caracterul “+” cu “%2b” inainte de a face request-ul catre serverul web:

paramsStr = paramsStr.replacingOccurrences(of: "+", with: "%2b")

Share Button

Map, Filter și Reduce în SWIFT – Update 24.05.2017

UPDATE 24.05.2017
Revin cu un exemplu practic pe care l-am incercat azi cu MAP. In Swift developerii folosesc din ce in ce mai mult MAP in locul clasicului FOR.
Convertesc secventa:
for user in (userList as! [String]) {
let fullMessages = SendReceiveMessages.sharedInstance.loadArchivedMessagesFrom(jid: user )
let last = fullMessages.lastObject as! JSQMessage
usersLastMessageStructArray.append(lastMessagesStruct(username: user, message: last.text, date: last.date))
}

in ceva mult mai swifty

usersLastMessageStructArray = (userList as! [String]).map({user in
let fullMessages = SendReceiveMessages.sharedInstance.loadArchivedMessagesFrom(jid: user )
let last = fullMessages.lastObject as! JSQMessage
return lastMessagesStruct(username: user, message: last.text, date: last.date)
})

Sortez de asemenea intr-un mod swifty acest array de struct-uri:

usersLastMessageStructArray = usersLastMessageStructArray.sorted{$0.date > $1.date}

Metode mai puțin cunoscute pentru array-uri însă extrem de puternice. Practic, cu ajutorul lor, nu mai e nevoie de pus o bucla for in sau foreach pe array.

filter(_:) – preia în noul array elementele din vechiul array în aceeași ordine cu precizarea că pot fi omise elementele care sunt specificate în filtru:
let elevi = [“Marius”, “Serban”, “Maria”]
let eleviM = elevi.filter {$0.hasPrefix(“M”)} // [Marius, Maria]

Un exemplu foarte concludent – formarea unui array de elemente pare din array-ul inițial”
let digits = [1,4,10,15]
let even = digits.filter { $0 % 2 == 0 } // [4, 10]

map(_:) – instanțiază un nou array în care fiecare element este rezultatul trecerii fiecărui element din vechiul vector prin funcția furnizată ca și argument. Interesant e faptul că această funcție poate modifica tipul parametrului

let vector = [1,2,3]
let vectorNou = vector.map {$0 * 2} // [2,4,6]

reduce(_:) – combină toate elementele din array pentru a obține o singură valoare
let litere = [“abc”,”def”,”ghi”]
let text = litere.reduce(“”, combine: +) // “abcdefghi”

sau

let array = [1, 4, 9, 13, 118]
let sum = arr.reduce(0) {$0 + $1} // 145

Share Button

Xcode 8 – problema loguri

La rularea unei aplicații în XCode8 apar în consolă tot felul de loguri ciudate:

2016-09-28 10:18:45.945891 test[1106:54365] bundleid: com.test.test, enable_level: 0, persist_level: 0, propagate_with_activity: 0
2016-09-28 10:18:45.946484 test[1106:54365] subsystem: com.apple.siri, category: Intents, enable_level: 1, persist_level: 1, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2016-09-28 10:18:45.956716 test[1106:54704] subsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0

Aceste loguri interne sunt o povară atunci când trebuie să urmăresc logurile mele interne.
Cum le dezactivez?

1- Xcode -> Product -> Scheme -> Edit Scheme

2- Adaug în Environment Variables set OS_ACTIVITY_MODE = disable


xcode

Share Button