Việc sử dụng suy luận Swift 3 @objc trong chế độ Swift 4 có bị phản đối không?


485

Tóm lại, trong khi sử dụng Xcode 9 Beta, tôi đã gặp phải cảnh báo sau:

Việc sử dụng suy luận Swift 3 @objc trong chế độ Swift 4 không được chấp nhận. Vui lòng giải quyết các cảnh báo suy luận @objc không dùng nữa, kiểm tra mã của bạn bằng cách sử dụng Swift 3 @objc suy luận Đăng nhập được kích hoạt và vô hiệu hóa suy luận Swift 3 @objc. **

Sau một số nghiên cứu, tôi vẫn không biết làm thế nào để khắc phục vấn đề. Tôi sẽ đánh giá rất cao bất kỳ lời khuyên nào về cách khắc phục vấn đề này cũng như giải thích về những gì đang xảy ra.

Mục tiêu của tôi là nắm bắt sự hiểu biết tốt hơn về những gì đang xảy ra với mã của tôi.


4
Tôi thực sự không nhận được từ tin nhắn cảnh báo đối tượng nào gây ra nó. Xcode đơn giản là không nói rõ đối tượng đó thuộc dòng nào. Bất kỳ lời khuyên làm thế nào để tìm ra cảnh báo này đến từ đâu?
olyv

Câu trả lời:


816

Tôi đã thoát khỏi cảnh báo này bằng cách thay đổi cài đặt xây dựng "Swift 3 @objc Inference" của các mục tiêu của tôi thành "Mặc định".

Vô hiệu hóa suy luận Swift 3 @objc trong Xcode9

Từ bài viết này :

Trước Swift 4, trình biên dịch đã thực hiện một số khai báo Swift tự động có sẵn cho Objective-C . Ví dụ: nếu một lớp con từ NSObject, trình biên dịch đã tạo các điểm nhập Objective-C cho tất cả các phương thức trong các lớp đó. Cơ chế được gọi là suy luận @objc.

Trong Swift 4, suy luận @objc tự động như vậy không được chấp nhận vì việc tạo ra tất cả các điểm vào Objective-C đó rất tốn kém. Khi cài đặt "Swift 3 @objc Inference" được đặt thành "Bật", nó cho phép mã cũ hoạt động. Tuy nhiên, nó sẽ hiển thị cảnh báo khấu hao cần được giải quyết. Bạn nên "sửa" các cảnh báo này và chuyển cài đặt thành "Mặc định" , đây là mặc định cho các dự án Swift mới.

Vui lòng tham khảo đề xuất Swift này để biết thêm thông tin.


5
Cảm ơn Evgenii. Đây có phải là một giải pháp lâu dài?
DaleK

6
@DaleK vâng, tôi tin là như vậy. Theo đề xuất Swift mà tôi đã đề cập trong câu trả lời của mình, suy luận objc bị phản đối. Cài đặt "Swift 3 objc Inference" chỉ xuất hiện trong các dự án được di chuyển từ các phiên bản cũ của Swift. Nếu một người tạo một dự án mới, cài đặt không còn nữa, điều đó có nghĩa là suy luận objc bị tắt. Bạn nên giải quyết mọi cảnh báo suy luận objc và đặt thành "Tắt".
Evgenii

4
Thông báo thông tin trong XCode gợi ý rằng: "Việc sử dụng @objcsuy luận Swift 3 trong chế độ Swift 4 không được chấp nhận. Vui lòng giải quyết @objccác cảnh báo suy luận không được chấp nhận , kiểm tra mã của bạn bằng cách sử dụng @objcsuy luận Swift 3 không được chấp nhận khi đăng nhập và kích hoạt@objc suy luận Swift 3 ". Bất kỳ ý tưởng nơi để kích hoạt @objcghi nhật ký suy luận Swift 3 đã nói ?
lịch sự

4
@courteouselk, theo đề xuất của Swift, người ta có thể đặt biến môi trường SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT thành các giá trị từ 1 đến 3 để xem cách sử dụng các điểm nhập Objective-C trong nhật ký.
Evgenii

14
Chỉ cần thêm - Bạn cần làm điều này cho tất cả các thẻ xây dựng, không chỉ cho dự án.
Krivvenz

270

- @objcSuy luận là gì? Chuyện gì đang xảy ra vậy?

Trong Swift 3, trình biên dịch xâm nhập @objcvào một số nơi để bạn không phải đến. Nói cách khác, nó chắc chắn để thêm @objccho bạn!

Trong Swift 4, trình biên dịch không còn làm điều này (càng nhiều). Bây giờ bạn phải thêm @objcmột cách rõ ràng.

Theo mặc định, nếu bạn có dự án trước Swift 4, bạn sẽ nhận được cảnh báo về điều này. Trong một dự án Swift 4, bạn sẽ gặp lỗi xây dựng. Điều này được kiểm soát thông qua SWIFT_SWIFT3_OBJC_INFERENCEcài đặt xây dựng. Trong một dự án trước Swift 4, điều này được đặt thành On. Tôi khuyên bạn nên đặt cái này thành Default(hoặc Off), hiện là tùy chọn mặc định cho một dự án mới.

Sẽ mất một chút thời gian để chuyển đổi mọi thứ, nhưng vì nó là mặc định cho Swift 4, nên đáng để làm điều đó.

- Làm cách nào để dừng cảnh báo / lỗi trình biên dịch?

Có hai cách để chuyển đổi mã của bạn để trình biên dịch không phàn nàn.

Một là sử dụng @objctrên từng chức năng hoặc biến cần được tiếp xúc với thời gian chạy Objective-C:

@objc func foo() {

}

Khác là để sử dụng @objcMembersbởi một Classtuyên bố. Điều này đảm bảo tự động thêm @objcvào TẤT CẢ các hàm và biến trong lớp. Đây là cách dễ dàng, nhưng nó có chi phí, ví dụ, nó có thể tăng kích thước ứng dụng của bạn bằng cách hiển thị các chức năng không cần phải tiếp xúc.

@objcMembers class Test {

}

- Cái gì @objcvà tại sao cần thiết?

Nếu bạn giới thiệu các phương thức hoặc biến mới cho một lớp Swift, đánh dấu chúng là @objchiển thị chúng cho thời gian chạy Objective-C. Điều này là cần thiết khi bạn có mã Objective-C sử dụng lớp Swift của bạn hoặc, nếu bạn đang sử dụng các tính năng loại Objective-C như Selectors. Ví dụ: mẫu hành động đích: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Tại sao tôi không đánh dấu mọi thứ @objc?

Có những tiêu cực đi kèm với việc đánh dấu một cái gì đó như @objc:

  • Tăng kích thước nhị phân ứng dụng
  • Không có chức năng quá tải

Xin lưu ý rằng đây là một bản tóm tắt cấp cao và nó phức tạp hơn tôi đã viết. Tôi khuyên bạn nên đọc đề xuất thực tế để biết thêm thông tin.

Nguồn:


@objckhông ngụ ý công văn động, Swift có thể tự do sử dụng công văn tĩnh hoặc ảo (và có thể thực thi các mã khác nhau). Các dynamictừ khóa được yêu cầu để buộc Swift dùng dispatch động.
kevin

7
Có những cách khác để thêm hành động cho nút? Nếu @objcdepric những gì chúng ta phải sử dụng?
Aznix

5
@Stefan có, có thể có một chút để chuyển đổi. Chia nó thành các giai đoạn. Để lại SWIFT_SWIFT3_OBJC_INFERENCEtại On. Chuyển đổi sang Swift 4. Sau đó giải quyết các @objccông cụ. Để làm cho nó đơn giản, hãy làm theo các quy tắc cơ bản: NẾU lớp Swift được sử dụng trong mã Objc-C (thông qua tiêu đề bắc cầu) @objcMembers, nếu không, hãy sử dụng thêm từng cái một @objc. Chỉ cần sử dụng tìm kiếm Xcode để tìm hiểu xem lớp Swift có được gọi từ bất kỳ .mtệp nào không . Điều này sẽ làm cho việc chuyển đổi tương đối không đau.
kgaidis

5
@DaleK này nên được chấp nhận câu trả lời. Việc ngăn chặn các cảnh báo và khiến mọi thứ hoạt động như trong Swift 3 là một lựa chọn, nhưng IMHO không phải là lựa chọn tốt nhất. Điều quan trọng là phải hiểu tại sao @objcthay đổi trong Swift 4 và sau đó đưa ra quyết định sửa chữa dự án và giữ nguyên dự án.
derpoliuk

2
Cảm ơn vì lời giải thích ngắn gọn này
Schmoudi

48

Migrator không thể xác định tất cả các chức năng mà cần @objc suy ra Objective-C thunks đánh dấu là bị phản đối để giúp bạn tìm thấy chúng
• Xây dựng cảnh báo về phương pháp NỮA
• Tin nhắn Bảng điều khiển khi chạy thunks bị phản đối

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


1
Vậy tôi nên làm gì với @objc? loại bỏ nó? bỏ nó đi Tôi đã loại bỏ điều đó. và tôi đưa ra những cảnh báo đó để tôi phải thêm chúng? Tôi nên làm gì với bước 3?
Shial

Thêm @objc ngay trước func
Hassan Taleb

1
Bước 3 là gì? Bạn có thể thêm một số mô tả :)
Shial

Và trong trường hợp của tôi, tôi nhận được cảnh báo này, nhưng không có mã nào được trỏ đến. Có hai phương pháp được đánh dấu @objc và chúng có vẻ như là những phương pháp duy nhất cần nó. Tôi đã thay đổi nó thành Mặc định và vẫn nhận được các cảnh báo trong quá trình biên dịch.
Maury Markowitz

12

Tôi đã có cảnh báo này với cài đặt "Swift 3 @objc Inference" = "Mặc định". Sau đó, tôi nhận ra rằng nó được đặt cho Dự án - không phải cho mục tiêu. Vì vậy, hãy đảm bảo rằng bạn có cài đặt "Mặc định" trong mục tiêu để thoát khỏi cảnh báo.


Tôi đã lãng phí 20 phút để tìm cách khắc phục lỗi ngay cả khi tôi đã thay đổi thành Mặc định trong cài đặt dự án. Bạn cũng chỉ ra chính xác nó cần phải được thay đổi trong mục tiêu.
SkrewEverything

8

Bạn chỉ có thể chuyển sang "mặc định" thay vì "BẬT". Có vẻ tuân thủ logic của Apple hơn.

(nhưng tất cả các ý kiến ​​khác về việc sử dụng @objvẫn còn hiệu lực.)


7

Thật vậy, bạn sẽ thoát khỏi những cảnh báo đó bằng cách vô hiệu hóa suy luận Swift 3 @objc. Tuy nhiên, các vấn đề tinh tế có thể bật lên. Ví dụ, KVO sẽ ngừng hoạt động. Mã này hoạt động hoàn hảo trong Swift 3:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

Sau khi chuyển sang Swift 4 và đặt "Suy luận Swift 3 @objc" thành mặc định, một số tính năng nhất định trong dự án của tôi đã ngừng hoạt động . Tôi phải mất một số gỡ lỗi và nghiên cứu để tìm ra giải pháp cho việc này. Theo kiến ​​thức tốt nhất của tôi, đây là các tùy chọn:

  • Bật "Suy luận Swift 3 @objc" (chỉ hoạt động nếu bạn đã di chuyển một dự án hiện có từ Swift 3) nhập mô tả hình ảnh ở đây
  • Đánh dấu các phương thức và thuộc tính bị ảnh hưởng là @objc nhập mô tả hình ảnh ở đây
  • Kích hoạt lại suy luận ObjC cho toàn bộ lớp bằng cách sử dụng @objcMembers nhập mô tả hình ảnh ở đây

Kích hoạt lại suy luận @objc để lại cho bạn các cảnh báo, nhưng đó là giải pháp nhanh nhất. Lưu ý rằng nó chỉ khả dụng cho các dự án được di chuyển từ phiên bản Swift trước đó. Hai tùy chọn khác là tẻ nhạt hơn và yêu cầu một số thử nghiệm đào mã và mở rộng.

Xem thêm https://github.com/apple/swift-evolution/blob/master/proposeals/0160-objc-inference.md


7

Tôi là một nhà phát triển iOS không thường xuyên (sắp có thêm) nhưng tôi vẫn không thể tìm thấy cài đặt theo hướng dẫn của câu trả lời khác (vì tôi không có mục Keychain đó mà câu trả lời hiển thị), vì vậy bây giờ tôi đã tìm thấy nó. Tôi có thể chỉ cần thêm ảnh chụp nhanh này với các vị trí được tô sáng mà bạn sẽ cần phải nhấp và tìm.

  1. Bắt đầu ở phía trên bên trái
  2. Chọn biểu tượng thư mục dự án
  3. Chọn tên dự án chính của bạn bên dưới biểu tượng thư mục dự án.
  4. Chọn Cài đặt bản dựng ở bên phải.
  5. Chọn dự án của bạn theo MỤC TIÊU.
  6. Cuộn rất xa xuống (hoặc tìm kiếm từ suy luận trong hộp văn bản tìm kiếm)

Tìm cài đặt


6

Bạn có thể thử "Pod update" và / hoặc "flutter clean"

Tôi cũng đặt cài đặt này trong xcode.

Cài đặt giao diện Objective-C như sau:

Cài đặt giao diện ObjectiveC


2

Suy luận Swift 3 @objc Việc sử dụng suy luận Swift 3 @objc trong chế độ Swift 4 không được chấp nhận. Vui lòng giải quyết các cảnh báo suy luận @objc không dùng nữa, kiểm tra mã của bạn với Sử dụng Swift 3 @objc suy luận đã đăng nhập, sau đó vô hiệu hóa suy luận bằng cách thay đổi cài đặt xây dựng "Swift 3 @objc Inference" thành "Mặc định" cho "XMLParsingURL" Mục tiêu.

đã đến

  1. Bước đầu tiên có Cài đặt bản dựng

  2. Tìm kiếm để xây dựng suy luận thiết lập

  3. thay đổi swift 3 @objc Suy luận Mặc định

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


1

Tất cả những gì bạn cần chỉ là chạy thử nghiệm cho đến khi kết thúc, sau đó chuyển đến Cài đặt xây dựng, Tìm kiếm để xây dựng suy luận thiết lập, thay đổi nhanh chóng 3 @objc Suy luận thành (Mặc định). đó là tất cả những gì tôi đã làm và làm việc hoàn hảo.


0

Việc sử dụng suy luận Swift 3 @objc trong chế độ Swift 4 có bị phản đối không?

sử dụng cuộc gọi func @objc

func call(){

foo()

}

@objc func foo() {

}

0

Ngoài những gì @wisekiddo đã nói, bạn cũng có thể sửa đổi cài đặt bản dựng của mình trong project.pbxprojtệp bằng cách đặt Swift 3 @obj Suy luận thành mặc định như SWIFT_SWIFT3_OBJC_INFERENCE = Default;cho hương vị bản dựng của bạn (ví dụ như gỡ lỗi và phát hành), đặc biệt nếu bạn đến từ một môi trường khác ngoài Xcode

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.