iOS 11 tắt tùy chọn xem phụ kiện tự động điền mật khẩu?


81

Hiện tại, tôi muốn chọn không tham gia tùy chọn mới mà iOS 11 cung cấp, đó là đề xuất mật khẩu trong ứng dụng. Khi tôi chạy ứng dụng trên iOS 11, tôi nhận được tùy chọn tự động điền trên đầu bàn phím và trường văn bản tên người dùng và mật khẩu của tôi thậm chí không hiển thị.

Vì vậy, câu hỏi của tôi là, làm thế nào tôi có thể vô hiệu hóa tất cả tính năng tự động điền mật khẩu mới để phím trên bàn phím hoàn toàn không hiển thị và hành vi tổng thể giống như trước iOS 11?

nhập mô tả hình ảnh ở đây


Hãy thử đặt thuộc tính của trường tên người dùng và mật khẩu textContentTypethành .textContentType- Điều này sẽ cho iOS 11 biết rằng các trường của bạn không phải là trường tên người dùng / mật khẩu (mặc dù chúng là như vậy) và ngăn chế độ xem phụ kiện được hiển thị; Một cái gì đó như `self.passwordField.textContentType = .textContentType`
Paulw11

@zumzum bạn có giải pháp nào không. hãy chia sẻ
Nazmul Hasan

2
Đây cũng là một vấn đề đối với tôi. Tính năng tự động hoàn thành xuất hiện trên các trường để đăng ký, điều này không được mong muốn. Tôi chỉ muốn họ có mặt trên các cánh đồng để đăng nhập. Thật kỳ lạ.
Brad Root

2
Có vẻ như trên iOS12, nó lại xuất hiện. Làm thế nào bạn giải quyết nó ở đó?
đô la 2048

Trong iOS12, nó vẫn xuất hiện. Bạn còn ý kiến ​​nào không ?
Emrah Akgül

Câu trả lời:


78

iOS 11 & 12 & 13 - Swift 4.2 & 5 (Cập nhật):

if #available(iOS 12, *) {
    // iOS 12 & 13: Not the best solution, but it works.
    passwordTextField.textContentType = .oneTimeCode
} else {
    // iOS 11: Disables the autofill accessory view. 
    // For more information see the explanation below.
    emailTextField.textContentType = .init(rawValue: "")
    passwordTextField.textContentType = .init(rawValue: "")
}

Giải thích iOS 11 :

Đảm bảo rằng bạn thiết lập tất cả các UITextFieldđối tượng của mình như thế này.

Ví dụ: nếu bạn có một UITextFieldđối tượng trong đó người dùng phải nhập địa chỉ email của mình và một đối tượng khác mà người dùng phải nhập mật khẩu được gán UITextContentType("")cho cả hai thuộc tính của họ textContentType. Nếu không, nó sẽ không hoạt động và chế độ xem phụ kiện Tự động điền sẽ vẫn được hiển thị.


1
Nó có sẵn ở dạng iOS 10, không phải iOS 11.
matm

@GalShahar Tôi không thể kiểm tra nó ngay bây giờ nhưng đây là gợi ý của tôi: iOS 12 giới thiệu một phiên bản mới UITextContentTypeđược gọi là newPassword (xem: developer.apple.com/documentation/uikit/uitextcontenttype/… ). Hãy thử đặt kiểu nội dung của trường văn bản mật khẩu thành kiểu này. Tôi đoán khi đó iOS sẽ không hiển thị chế độ xem phụ kiện tự động điền vì người dùng buộc phải thiết lập mật khẩu mới và không được sử dụng / truy cập mật khẩu đã được thiết lập trước đó bằng cách sử dụng chế độ xem phụ kiện tự động điền. Hiện tại đây chỉ là lý thuyết. Tôi không chắc liệu điều này có hiệu quả hay không, nhưng hãy cho tôi biết liệu nó có hiệu quả không!
Baran Emre

Được rồi, các bạn hãy quên những gì tôi đã viết về iOS 12. Cài đặt UITextContentType thành newPasswordkhông hoạt động. Tôi đã thử giải pháp của @GalShahar, nhưng tôi không thích nó. Thay vào đó, tôi đang đặt UITextContentTypethành oneTimeCode . Điều đó hoạt động cho bây giờ.
Baran Emre

Đối với iOS 12, tôi phải đặt isSecureTextEntrythành false trước tiên ngoài việc đặt UITextContentTypethành oneTimeCode. Chúng ta có thể đặt isSecureTextEntrythành bất kỳ thứ gì chúng ta muốn sau khi họ bắt đầu nhập trường văn bản.
da1

@ da1 Chúng tôi đang đặt .isSecureTextEntrythành truetrước khi đặt textContentTypethành .oneTimeCodevà nó hoạt động như mong đợi. Tôi không biết mã của bạn trông như thế nào, nhưng khi khởi tạo trường văn bản, thứ tự thiết lập các thuộc tính của nó không quan trọng.
Baran Emre

13

iOS 12 dường như cũng nhận ra mật khẩu textFields theo thuộc isSecureTextEntrytính chứ không chỉ theo thuộc textContentTypetính, vì vậy, việc làm cho chế độ xem phụ kiện này biến mất là không thực sự khả thi trừ khi bạn đặt cả textContentType thành không có gì và xóa tính năng secureEntry (và gây ra lỗi bảo mật trong ứng dụng của bạn). sau đó ngăn iOS 12 nhận dạng textField dưới dạng textField mật khẩu và hiển thị chế độ xem phụ kiện khó chịu này.

Trong trường hợp của tôi, phụ kiện đã gây ra lỗi khiến ứng dụng của tôi không phản hồi khi chạm vào (Điều này cũng khiến ứng dụng của tôi bị từ chối trong quá trình xem xét ứng dụng). Vì vậy, tôi đã phải loại bỏ tính năng này. Tôi không muốn từ bỏ tính năng bảo mật này nên tôi phải tự giải quyết mọi việc.

Ý tưởng là loại bỏ tính năng secureEntry nhưng tự thêm nó theo cách thủ công. Nó đã hoạt động:

nhập mô tả hình ảnh ở đây


Nó có thể được thực hiện như vậy:

Swift 4 cách:

Đầu tiên, như đã trả lời ở đây, hãy đặt textContentTypethành không:

if #available(iOS 10.0, *) {
    passwordText.textContentType = UITextContentType("")
    emailText.textContentType = UITextContentType("")
}

Hơn nữa, hãy khai báo một biến String mà sau này sẽ chứa nội dung thực của textField:

var passwordValue = ""

Thêm mục tiêu vào passwordTextField, sẽ được gọi mỗi khi nội dung textField thay đổi:

passwordText.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)

Bây giờ đó là những gì sẽ làm điều kỳ diệu, hãy khai báo hàm sẽ xử lý các văn bản thay thế:

@objc func textFieldDidChange(_ textField: UITextField) {
    if textField.text!.count > 1 {
        // User did copy & paste
        if passwordValue.count == 0 { // Pasted into an empty textField
            passwordValue = String(textField.text!)
        } else { // Pasted to a non empty textField
            passwordValue += textField.text!.substring(from: passwordValue.count)
        }
    } else {
        // User did input by keypad
        if textField.text!.count > passwordValue.count { // Added chars
            passwordValue += String(textField.text!.last!)
        } else if textField.text!.count < passwordValue.count { // Removed chars
            passwordValue = String(passwordValue.dropLast())
        }
    }
    self.passwordText.text = String(repeating: "•", count: self.passwordText.text!.count)
}

Cuối cùng, Set TextField là autocorrectionTypeđể .noloại bỏ văn bản tiên đoán:

passwordText.autocorrectionType = .no

Vậy là xong, sử dụng passwordValueđể thực hiện đăng nhập của bạn.

Hy vọng nó sẽ giúp một ai đó.

CẬP NHẬT

Nó cũng bắt các giá trị đã dán, bạn đã quên thêm nó trước đó.


2
Siêu! Tốt lắm bạn hack! xấu hổ rằng iOS khiến chúng ta bị hack hơn là cung cấp những cách sạch hơn để thực hiện những điều cơ bản nhất. Đây phải là câu trả lời được chấp nhận.
sandpat 24/09/18

9

Tính năng này có thể bị vô hiệu hóa bằng cách chỉ định loại nội dung không phải là tên người dùng hay mật khẩu. Ví dụ: nếu người dùng phải nhập địa chỉ email, bạn có thể sử dụng

usernameTextField?.textContentType = .emailAddress

1
Điều thú vị là tôi có trường địa chỉ email phía trên trường mật khẩu và trường địa chỉ email cung cấp tính năng tự động hoàn tất.
Brad Root

1
@BradRoot cũng thay đổi trường mật khẩu của bạn textContentype! nếu email của bạn đã được lưu trong chuỗi khóa thì email đó sẽ hiển thị thông tin trên thanh nhanh, vì vậy tốt hơn cho người dùng .nickname hoặc thử mã này nếu #available (iOS 10.0, *) {self.passwordTextField.textContentType = UITextContentType.init (rawValue: " ")} else {// Dự phòng về các phiên bản trước}
Sahil

8

Bạn có thể thêm tiện ích mở rộng cho UITextContentType như thế này

extension UITextContentType {
    public static let unspecified = UITextContentType("unspecified")
}

sau đó, bạn có thể sử dụng nó

if #available(iOS 10.0, *) {
    passwordField.textContentType = .unspecified
}

6

Một cách tiếp cận rất đơn giản trong ios11 đã phù hợp với tôi. Giả sử iboutlet của bạn là usernametextfield và passwordtextfield. Trong hàm viewDidLoad () của bộ điều khiển chế độ xem của bạn, hàm chứa cả hai chức năng tốt nhất, hãy sử dụng mã sau

usernametextfield.textContentType = UITextContentType("")
passwordtextfield.textContentType = UITextContentType("")

Sau đó, bạn sẽ không thấy tùy chọn phụ kiện tự động điền khi bạn nhấn vào các trường văn bản của mình.


6

để đáp lại @Gal Shahar Answer.

iOS 12 nhận dạng văn bản mật khẩu Các trường theo thuộc isSecureTextEntrytính chứ không chỉ theo thuộc textContentTypetính.

Cách xung quanh để bỏ qua Đề xuất tự động điền.

  1. đặt thuộc isSecureTextEntry tính thành false.

self.passwordTextField.secureTextEntry = NO;

  1. Thêm một phương pháp ủy quyền UITextField và kích hoạt thuộc isSecureTextEntry tính.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == self.passwordTextField && !self.passwordTextField.secureTextEntry) {
        self.passwordTextField.secureTextEntry = YES;
    }

    return YES;
}

LƯU Ý: - KHÔNG sử dụng shouldBeginEditingphương pháp ủy quyền UITextField, nó sẽ vẫn hiển thị Đề xuất tự động điền. Đừng KHÔNG Sử dụng textFieldDidChangephương pháp đại biểu UITextField nó sẽ tự động xóa các charachter đầu tiên là nó sẽ xảy ra sau khi charachter đầu tiên được hiển thị. Và 'secureTextEntry' sẽ làm trống trường.


1
Điều này không chỉ giải quyết vấn đề đã thảo luận mà còn giải quyết vấn đề đọc sai chiều cao bàn phím từ UIKeyboardWillShowNotification khi lần đầu tiên chạm vào trường mật khẩu. Câu trả lời chính xác.
ekashking

5

Objective-C

if (@available(iOS 10, *)){
    self.tfEmail.textContentType = @"";
    self.tfPassword.textContentType = @"";
}

Điều này đã làm việc cho tôi.


3

Tự động điền được bật theo mặc định cho người dùng. iOS lưu tất cả mật khẩu trong chuỗi khóa và cung cấp chúng trên bàn phím trong ứng dụng của bạn. UITextViewUITextFieldtự động được xem xét cho mật khẩu Tự động điền. bạn có thể vô hiệu hóa bằng cách chỉ định loại nội dung không phải là tên người dùng cũng như mật khẩu nhưng nếu thông tin loại nội dung đã được lưu trữ trong chuỗi khóa, thông tin đó sẽ hiển thị trong thanh nhanh. vì vậy tốt hơn nên chỉ định UITextContentTypeloại trống và nó sẽ không hiển thị thanh nhanh.

Thí dụ:

  if #available(iOS 10.0, *) {
  self.textField.textContentType = UITextContentType("")
  } else {
  // Fallback on earlier versions
 }

3

Điều này hoạt động cho iOS 12 và 10:

if (@available(iOS 10, *)) {
    passwordTextField.textContentType = UITextContentTypeStreetAddressLine2;
}

if (@available(iOS 12, *)) {
    passwordTextField.textContentType = UITextContentTypeOneTimeCode;
}

2

Bạn có thể "tắt" tính năng phát hiện tổ hợp tên người dùng / mật khẩu bằng cách gán một hình nộm textContentTypecho trường văn bản mật khẩu.

passwordFormField.textContentType = UITextContentType("dummy")

Thao tác này đã tắt biểu tượng phím cho cả trường mật khẩu và trường email đứng trước nó, và theo cách này, bạn không sử dụng một trong các giá trị được xác định trước và bạn tránh hiển thị các đề xuất không liên quan trong chế độ xem phụ kiện bàn phím.


Điều này vẫn hoạt động trên iOS 12 beta mới nhất cho bạn chứ?
pfandrade,

Không nó không. Trên iOS 12, nó phát hiện trường này là trường mật khẩu mới và đề xuất một mật khẩu mạnh mới (tính năng iOS 12 mới). Tôi thực sự muốn hành vi này trong trường hợp của mình, vì vậy tôi đang gắn thẻ trường mật khẩu này với newPasswordUITextContentType iOS 12 mới. Tôi không biết làm thế nào để tránh hành vi mới này.
Miguel Cabeça

Đối với iOS 12 beta, nếu sử dụng: textContentType = UITextContentType.oneTimeCode. Sau đó, nó không có móc khóa trên bàn phím. Nó dường như hoạt động tốt cho tôi mà không có bất kỳ tác dụng phụ nào. Nếu bạn sử dụng .newPassword, cách đó cũng hoạt động, nhưng sau đó nó yêu cầu bạn lưu mật khẩu sau khi bạn hoàn tất với mật khẩu.
Daniel Jones

2

Phiên bản Objective C:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
    self.passwordTextField.textContentType = @"";
    self.confirmPasswordTextField.textContentType = @"";
}

Ở đâu

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

1

Từ những gì tôi có thể nói, câu trả lời của Bem không hoạt động trong iOS 12 và câu trả lời của Gal Shahar không giải thích cho một số trường hợp phức tạp (ví dụ: nếu người dùng xóa nhiều ký tự cùng một lúc). Tôi đã giải quyết vấn đề này bằng cách sử dụng IBAction, do đó loại bỏ sự cần thiết phải kiểm tra phiên bản iOS hoàn toàn. Tôi chỉ là người mới bắt đầu, vì vậy đây có thể không phải là câu trả lời "tốt nhất" hoặc hiệu quả nhất, nhưng nó có ý nghĩa nhất đối với tôi:

Đầu tiên, bỏ chọn "Mục nhập văn bản an toàn" trong Bảng phân cảnh hoặc đặt thành "false" / "NO" thông qua mã cho mật khẩu UITextField của bạn. Điều này sẽ ngăn iOS cố gắng Tự động điền.

Sau đó, liên kết mật khẩu UITextField của bạn với một IBAction. Của tôi được gọi vào:

  • Quá trình chỉnh sửa đã bắt đầu
  • Chỉnh sửa đã thay đổi
  • Chỉnh sửa đã kết thúc

Hàm IBAction mà tôi đã viết xác định sự khác biệt giữa mật khẩu bắt đầu của người dùng và những gì đã được nhập vào mật khẩu UITextField và tạo mật khẩu mới dựa trên thông tin này:

class Login: UIViewController {
    var password = ""

    override func viewDidLoad() { super.viewDidLoad() }

    @IBAction func editPasswordField(_ sender: UITextField) {
        var input = Array(sender.text ?? "")
        var oldPassword = Array(password)
        var newPassword = Array("")

        //if character(s) are simply deleted from "passwordField" (not replaced or added to), "cursorPosition" is used to determine which corresponding character(s) need to also be removed from "oldPassword"
        //this is indicated by "input" comprising of only "•" (bullets) and being shorter in length than "oldPassword"
        var onlyBullets = true
        for char in input { if char != "•" { onlyBullets = false } }
        if onlyBullets && input.count < oldPassword.count {
            if let selectedRange = sender.selectedTextRange {
                let cursorPosition = sender.offset(from: sender.beginningOfDocument, to: selectedRange.start)
                let prefix = String(oldPassword.prefix(cursorPosition))
                let suffix = String(oldPassword.suffix(input.count - cursorPosition))
                input = Array(prefix + suffix)
            } else { input = Array("") }
        }

        //if no changes were made via input, input would comprise solely of a number of bullets equal to the length of "oldPassword"
        //therefore, the number of changes made to "oldPassword" via "input" can be measured with "bulletDifference" by calculating the number of characters in "input" that are NOT bullets
        var bulletDifference = oldPassword.count
        for char in input { if char == "•" { bulletDifference -= 1 } }

        //the only way "bulletDifference" can be less than 0 is if a user copy-pasted a bullet into "input", which cannot be allowed because it breaks this function
        //if a user pastes bullet(s) into "input", "input" is deleted
        //an edge case not accounted for is pasting a mix of characters and bullets (i.e. "ex•mple") when "oldPassword.count" exceeds the number of bullets in the mixed input, but this does not cause crashes and therefore is not worth preventing
        if bulletDifference < 0 {
            bulletDifference = oldPassword.count
            input = Array("")
        }

        //"bulletDifference" is used to remove every character from "oldPassword" that corresponds with a character in "input" that has been changed
        //a changed character in "input" is indicated by the fact that it is not a bullet
        //once "bulletDifference" equals the number of bullets deleted, this loop ends
        var bulletsDeleted = 0
        for i in 0..<input.count {
            if bulletsDeleted == bulletDifference { break }
            if input[i] != "•" {
                oldPassword.remove(at: i - bulletsDeleted)
                bulletsDeleted += 1
            }
        }

        //what remains of "oldPassword" is used to substitute bullets in "input" for appropriate characters to create "newPassword"
        //for example, if "oldPassword" is "AcbDE" and "input" is "•bc••", then "oldPassword" will get truncated to "ADE" and "newPassword" will equal "A" + "bc" + "DE", or "AbcDE"
        var i = 0
        for char in input {
            if char == "•" {
                newPassword.append(oldPassword[i])
                i += 1
            } else { newPassword.append(char) }
        }
        password = String(newPassword)

        //"passwordField.text" is then converted into a string of bullets equal to the length of the new password to ensure password security in the UI
        sender.text = String(repeating: "•", count: password.count)
    }
}

Phê bình mang tính xây dựng được đánh giá cao!


1

Bạn có thể thử các câu trả lời khác nhau ở đây để kết luận rằng có thể xóa chế độ xem phụ kiện. Nhưng điều này để lại một số lỗi.

Có lẽ bạn có thể thử triển khai bàn phím tùy chỉnh, chỉ cho các trường mật khẩu. Ngoài ra, hãy cố gắng tắt các đề xuất cho trường văn bản của bạn, tôi nghĩ rằng điều đó cũng ẩnaccessoryView .

CHỈNH SỬA: Vẫn không có câu trả lời trên các diễn đàn của Apple về cùng một câu hỏi. Ngoài ra, tôi không thể tìm thấy bất cứ điều gì liên quan đến điều này trong UITextFieldtài liệu chính thức .


1

Nhân viên điên rồ xảy ra trong chủ đề này. Tôi đã tạo mà không cần iOS đề xuất mật khẩu, nhưng chỉ cung cấp cho tôi tính năng tự động điền cho email. Chỉ cần ai đó cần. Sau khi kết hợp khác nhau và kiểu khác nhau, textContentTypetôi đã làm cho nó như tôi muốn.

  1. Trường Văn bản Email với đề xuất tự động điền iOS là một cái gì đó.
  2. Trường văn bản mật khẩu không có hệ thống iOS đề xuất cho tôi mật khẩu mới nhưng điền mật khẩu vào nếu tôi chọn từ trường văn bản email.
  3. Trường văn bản mật khẩu để có văn bản nhập an toàn.

Và với mã này, nó đã hoạt động. Không quan trọng nếu bạn có emailhay usernamenó sẽ làm cho bạn một đề xuất với những gì bạn cần. Vì vậy, tôi đã tắt chế độ xem tự động điền của phụ kiện và chỉ để lại chế độ tự động điền trong thanh công cụ của bàn phím.

self.passwordField.isSecureTextEntry = true

if #available(iOS 11.0, *) {
    self.emailField.textContentType = .username
    self.emailField.keyboardType = .emailAddress
}

if #available(iOS 12.0, *) {
    self.passwordField.textContentType = .password
    self.passwordField.keyboardType = .default
}

0
self.passwordTextField.autocorrectionType = NO;

Nó dường như không hoạt động, dấu hiệu móc khóa vẫn ở đó,

self.passwordTextField.textContentType = UITextContentTypeName;

Đoạn mã trên hoạt động nhưng nếu người dùng thiết lập tài khoản Apple ID của họ, thì tên của id apple sẽ hiển thị trên bàn phím, bạn không thể tắt nó bằng cách đặt autocorrectionType thành Không, không chắc liệu Apple có còn tinh chỉnh tính năng tự động điền này không , nó khá lỗi ngay bây giờ.


Loại 'câu trả lời' này nên được dành riêng cho phần nhận xét, vì nó không đưa ra câu trả lời thực sự hoặc liên kết đến bất kỳ tài liệu tham khảo nào từ apple, v.v. Chào mừng bạn đến với SO!
stktrc

chưa có giải pháp. Không có gì được liệt kê ở đây hoạt động tốt cho tôi.
zumzum

0

Điều này đã làm việc cho tôi:

LƯU Ý: hãy thử đặt mã này trên các trường văn bản mật khẩu, xác nhận mật khẩu (nếu có) VÀ email. Tôi đã không đặt nó trên trường văn bản email và nó vẫn xuất hiện cho hai trường mật khẩu.

if #available(iOS 12, *) {
     // iOS 12: Not the best solution, but it works.
     cell.textField.textContentType = .oneTimeCode
} else {
     // iOS 11: Disables the autofill accessory view.
     cell.textField.textContentType = .init(rawValue: "")
}

1
Điều này giống với câu trả lời của Bem.
Eric Aya

0

Tôi nghĩ rằng đặt tất cả UITextField textContentType ở dạng thành UITextContentType("")hoặc .oneTimeCodekhông phải là một giải pháp sạch. Bật / Tắt isSecureTextEntryvẫn cung cấp cho bạn vấn đề tương tự.

Câu trả lời của @Gal Shahar rất hay nhưng nó vẫn chưa hoàn hảo. Biểu tượng mặt nạ không giống với ký tự mặt nạ được sử dụng trong văn bản nhập an toàn từ apple. Nó phải sử dụng Ký tự Unicode 'BLACK CIRCLE' (U + 25CF) https://www.fileformat.info/info/unicode/char/25cf/index.htm

Ngoài ra, nó không xử lý chuyển động của con trỏ. Nó sẽ thay đổi vị trí con trỏ đến cuối văn bản khi chèn văn bản vào giữa. Nó sẽ cung cấp cho bạn giá trị sai khi chọn và thay thế văn bản.

Khi bạn quyết định sử dụng isSecureEntryText tùy chỉnh để tránh mật khẩu tự động điền, đây là mã:

Swift 5 (phiên bản đơn giản)

@IBOutlet weak var passwordTextField: UITextField!

var maskedPasswordChar: String = "●"
var passwordText: String = ""
var isSecureTextEntry: Bool = true {
    didSet {
        let selectedTextRange = passwordTextField.selectedTextRange
        passwordTextField.text = isSecureTextEntry ? String(repeating: maskedPasswordChar, count: passwordText.count) : passwordText
        passwordTextField.selectedTextRange = selectedTextRange
    }
}

//this is UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if textField == passwordTextField {
        //update password string
        if let swiftRange = Range(range, in: passwordText) {
            passwordText = passwordText.replacingCharacters(in: swiftRange, with: string)
        } else {
            passwordText = string
        }

        //replace textField text with masked password char
        textField.text =  isSecureTextEntry ? String(repeating: maskedPasswordChar, count: passwordText.count) : passwordText

        //handle cursor movement
        if let newPosition = textField.position(from: textField.beginningOfDocument, offset: range.location + string.utf16.count) {
            textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
        }
        return false
    }
    return true
}

Swift 5 (phiên bản HOÀN THÀNH với bảo mật hoạt ảnh ký tự cuối cùng)

private struct Constants {
    static let SecuringLastCharPasswordDelay = 1.5
}

@IBOutlet weak var passwordTextField: UITextField!

private var secureTextAnimationQueue: [String] = []

var maskedPasswordChar: String = "●"
var passwordText: String = ""
var isSecureTextEntry: Bool = true {
    didSet {
        secureTextAnimationQueue.removeAll()
        let selectedTextRange = passwordTextField.selectedTextRange
        passwordTextField.text = isSecureTextEntry ? String(repeating: maskedPasswordChar, count: passwordText.count) : passwordText
        passwordTextField.selectedTextRange = selectedTextRange
    }
}

//this is UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if textField == passwordTextField {
        //update password string
        if let swiftRange = Range(range, in: passwordText) {
            passwordText = passwordText.replacingCharacters(in: swiftRange, with: string)
        } else {
            passwordText = string
        }

        //replace textField text with masked password char
        updateTextFieldString(textField, shouldChangeCharactersIn: range, replacementString: string)

        //handle cursor movement
        if let newPosition = textField.position(from: textField.beginningOfDocument, offset: range.location + string.utf16.count) {
            textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
        }
        return false
    }
    return true
}

private func updateTextFieldString(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) {
    if isSecureTextEntry {
        if string.count == .one, let text = textField.text {
            let maskedText = String(repeating: maskedPasswordChar, count: text.count)

            var newMaskedText = String()
            if let swiftRange = Range(range, in: maskedText) {
                newMaskedText = maskedText.replacingCharacters(in: swiftRange, with: string)
            } else {
                newMaskedText = text + maskedText
            }

            textField.text = newMaskedText
            secureTextAnimationQueue.append(string)
            asyncWorker.asyncAfter(deadline: .now() + Constants.SecuringLastCharPasswordDelay) { [weak self] in
                self?.securingLastPasswordChar()
            }
        } else {
            secureTextAnimationQueue.removeAll()
            textField.text = String(repeating: maskedPasswordChar, count: passwordText.count)
        }
    } else {
        textField.text = passwordText
    }
}

private func securingLastPasswordChar() {
    guard secureTextAnimationQueue.count > .zero, isSecureTextEntry else { return }
    secureTextAnimationQueue.removeFirst()
    if secureTextAnimationQueue.count == .zero {
        let selectedTextRange = passwordTextField.selectedTextRange
        passwordTextField.text = String(repeating: maskedPasswordChar, count: passwordText.count)
        passwordTextField.selectedTextRange = selectedTextRange
    }
}

0

nhập mô tả hình ảnh ở đây

Tôi đã đính kèm ảnh chụp màn hình. bạn có thể thay đổi nội dung Nhập làm Tên người dùng trong bảng phân cảnh hoặc bạn có thể thực hiện theo chương trình. bạn có thể tạo một phần mở rộng cho UITextfield.

func diableAutofill() {
        self.autocorrectionType = .no
        if #available(iOS 11.0, *) {
            self.textContentType = .username
        } else {
            self.textContentType = .init("")
        }
    }

0

Cảm ơn Apple, tôi không thể tìm thấy bất kỳ cách nào với các phương thức gốc khi isSecureTextEntry được đặt thành CÓ. Cách của Gal Shahar là giải pháp duy nhất để tắt tùy chọn xem phụ kiện tự động điền mật khẩu. Nhưng nó dễ thực hiện hơn với

mục tiêu c

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

nhanh

textField(_:shouldChangeCharactersIn:replacementString:)

đại biểu. Và sử dụng mã đơn giản như thế này. Khai báo một biến String sau này sẽ chứa nội dung thực của textField, của tôi là pswd.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        //Thanks iOS13!!!
        if(!_pswd)
        {
            _pswd = @"";
        }
        _pswd = [_pswd stringByReplacingCharactersInRange:range withString:string];

        if (!buttonShowPassword.selected)
        {
            textField.text = [@"" stringByPaddingToLength:_pswd.length withString: @"•" startingAtIndex:0];
        }
        else
        {
            textField.text = _pswd;
        }
        return NO;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.